diff -u --recursive --new-file v2.4.0-test11/linux/CREDITS linux/CREDITS --- v2.4.0-test11/linux/CREDITS Sun Nov 19 18:44:01 2000 +++ linux/CREDITS Mon Dec 11 13:42:08 2000 @@ -41,7 +41,7 @@ E: tigran@veritas.com W: http://www.ocston.org/~tigran D: BFS filesystem -D: Intel P6 CPU microcode update support +D: Intel IA32 CPU microcode update support D: Various kernel patches S: United Kingdom @@ -152,10 +152,12 @@ D: Wrote SYS V IPC (part of standard kernel since 0.99.10) N: Dario Ballabio -E: dario@milano.europe.dg.com +E: ballabio_dario@emc.com +E: dario.ballabio@tiscalinet.it +E: dario.ballabio@inwind.it D: Author and maintainer of the Ultrastor 14F/34F SCSI driver D: Author and maintainer of the EATA ISA/EISA/PCI SCSI driver -S: Data General Corporation +S: EMC Corporation S: Milano S: Italy @@ -339,6 +341,7 @@ N: Al Borchers E: alborchers@steinerpoint.com D: Author/maintainer of Digi AccelePort USB driver +D: work on usbserial and keyspan_pda drivers S: 4912 Zenith Ave. S. S: Minneapolis, MN 55410 S: USA @@ -408,6 +411,10 @@ E: zab@zabbo.net D: maestro pci sound +N: Gary Brubaker +E: xavyer@ix.netcom.com +D: USB Serial Empeg Empeg-car Mark I/II Driver + N: Ray Burr E: ryb@nightmare.com D: Original author of Amiga FFS filesystem @@ -760,6 +767,7 @@ E: nils@kernelconcepts.de D: i810 TCO watchdog driver author D: Mitsumi LU005 tests and fixes +D: port and fixes of cs46xx sounddriver S: Dreisbachstrasse 24 S: D-57250 Netphen S: Germany diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/Changes linux/Documentation/Changes --- v2.4.0-test11/linux/Documentation/Changes Tue Oct 31 12:42:25 2000 +++ linux/Documentation/Changes Mon Dec 11 13:42:08 2000 @@ -185,10 +185,10 @@ kernel source. Pay attention when you recompile your kernel ;-). Also, be sure to upgrade to the latest pcmcia-cs release. -Intel P6 microcode ------------------- +Intel IA32 microcode +-------------------- -A driver has been added to allow updating of Intel P6 microcode, +A driver has been added to allow updating of Intel IA32 microcode, accessible as both a devfs regular file and as a normal (misc) character device. If you are not using devfs you may need to: @@ -198,6 +198,13 @@ as root before you can use this. You'll probably also want to get the user-space microcode_ctl utility to use with this. + +If you have compiled the driver as a module you may need to add +the following line: + +alias char-major-10-184 microcode + +to your /etc/modules.conf file. Networking ========== diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.0-test11/linux/Documentation/Configure.help Sun Nov 19 18:44:01 2000 +++ linux/Documentation/Configure.help Mon Dec 11 13:42:08 2000 @@ -10286,6 +10286,17 @@ The module will be called visor.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB Belkin and Paracom Single Port Serial Driver +CONFIG_USB_SERIAL_BELKIN + Say Y here if you want to use a Belkin USB Serial single port + adaptor (F5U103 is one of the model numbers) or the Peracom single + port USB to serial adapter. + + 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 belkin_sa.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. + USB FTDI Single Port Serial Driver CONFIG_USB_SERIAL_FTDI_SIO Say Y here if you want to use a FTDI SIO single port USB to serial @@ -10361,11 +10372,36 @@ parallel port on the USB 2 appears as a third serial port on Linux. The Digi Acceleport USB 8 is not yet supported by this driver. + This driver works under SMP with the usb-uhci driver. It does not + work under SMP with the uhci driver. + 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 digi_acceleport.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB Empeg empeg-car Mark I/II Driver +CONFIG_USB_SERIAL_EMPEG + Say Y here if you want to connect to your Empeg empeg-car Mark I/II + mp3 player via USB. The driver uses a single ttyUSB{0,1,2,...} + device node. See Documentation/usb/usb-serial.txt for more + tidbits of information. + + 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 empeg.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + +USB MCT Single Port Serial Driver +CONFIG_USB_SERIAL_MCT_U232 + Say Y here if you want to use a USB Serial single port adapter from + Magic Control Technology Corp. (U232 is one of the model numbers). + + 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 mct_u232.o. If you want to compile it as + a module, say M here and read Documentation/modules.txt. + USB Serial Converter verbose debug CONFIG_USB_SERIAL_DEBUG Say Y here if you want verbose debug messages from the USB Serial @@ -13395,13 +13431,24 @@ module, say M here and read Documentation/modules.txt. Most people will say N. -/dev/cpu/microcode - Intel P6 CPU microcode support +Toshiba Laptop support +CONFIG_TOSHIBA + If you intend to run this the kernel on a Toshiba portable say yes + here. This adds a driver to safely access the System Management + Mode of the CPU on Toshiba portables. The System Management Mode + is used to set the BIOS and power saving options on Toshiba portables. + + For information on utilities to make use of this driver see the + Toshiba Linux utilities website at: + http://www.buzzard.org.uk/toshiba/ + +/dev/cpu/microcode - Intel IA32 CPU microcode support CONFIG_MICROCODE If you say Y here and also to "/dev file system support" in the 'File systems' section, you will be able to update the microcode on - Intel processors in the P6 family, e.g. Pentium Pro, Pentium II, - Pentium III, Xeon etc. You will obviously need the actual microcode - binary data itself which is not shipped with the Linux kernel. + Intel processors in the IA32 family, e.g. Pentium Pro, Pentium II, + Pentium III, Pentium 4, Xeon etc. You will obviously need the actual + microcode binary data itself which is not shipped with the Linux kernel. For latest news and information on obtaining all the required ingredients for this driver, check: @@ -13410,7 +13457,9 @@ This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called microcode.o. If you want to compile it as - a module, say M here and read Documentation/modules.txt. + a module, say M here and read Documentation/modules.txt. If you use + modprobe or kmod you may also want to add the line + 'alias char-major-10-184 microcode' to your /etc/modules.conf file. /dev/cpu/*/msr - Model-specific register support CONFIG_X86_MSR @@ -16263,12 +16312,6 @@ (also known as the LART). See http://www.lart.tudelft.nl/ for information on the LART. -Include support for ThinClient -CONFIG_SA1100_THINCLIENT - Say Y here if you are using an Applied Data Systems Intel(R) - StrongARM(R) SA-1100 based Thin Client SBC. See - http://www.flatpanels.com/ for information on this system. - Include support for GraphicsClient CONFIG_SA1100_GRAPHICSCLIENT Say Y here if you are using an Applied Data Systems Intel(R) @@ -16303,6 +16346,27 @@ CONFIG_CPU_ARM920 Say Y here if you wish to include support for the ARM920 processor. +Support ARM610 processor +CONFIG_CPU_ARM6 + Say Y here if you wish to include support for the ARM610 processor. + +Support ARM710 processor +CONFIG_CPU_ARM7 + Say Y here if you wish to include support for the ARM710 processor. + +Support StrongARM(R) SA-110 processor +CONFIG_CPU_SA110 + Say Y here if you wish to include support for the Intel(R) + StrongARM(R) SA-110 processor. + +Support ARM720 processor +CONFIG_CPU_ARM720 + Say Y here if you wish to include support for the ARM720 processor. + +Support ARM920 +CONFIG_CPU_ARM920 + Say Y here if you wish to include support for the ARM920 processor. + Math emulation CONFIG_NWFPE Say Y to include the NWFPE floating point emulator in the kernel. @@ -16425,6 +16489,17 @@ CONFIG_SERIAL_21285_CONSOLE If you have enabled the serial port on the 21285 footbridge you can make it the console by answering Y to this option. + +SA1100 serial port support +CONFIG_SERIAL_SA1100 + If you have a machine based on a SA1100/SA1110 StrongARM CPU you can + enable its onboard serial port by enabling this option. + Please read Documentation/arm/SA1100/serial_UART for further info. + +Console on SA1100 serial port +CONFIG_SERIAL_SA1100_CONSOLE + If you have enabled the serial port on the SA1100/SA1110 StrongARM + CPU you can make it the console by answering Y to this option. L7200 serial port support CONFIG_SERIAL_L7200 diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/DMA-mapping.txt linux/Documentation/DMA-mapping.txt --- v2.4.0-test11/linux/Documentation/DMA-mapping.txt Thu Sep 7 08:31:59 2000 +++ linux/Documentation/DMA-mapping.txt Mon Dec 11 13:45:42 2000 @@ -341,7 +341,7 @@ struct my_card_header *hp; /* Examine the header to see if we wish - * to except the data. But synchronize + * to accept the data. But synchronize * the DMA transfer with the CPU first * so that we see updated contents. */ diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl --- v2.4.0-test11/linux/Documentation/DocBook/kernel-hacking.tmpl Sun May 21 20:18:07 2000 +++ linux/Documentation/DocBook/kernel-hacking.tmpl Mon Nov 27 17:47:38 2000 @@ -846,7 +846,7 @@ first class of operations work on atomic_t include/asm/atomic.h; this - contains a signed integer (at least 32 bits long), and you must use + contains a signed integer (at least 24 bits long), and you must use these functions to manipulate or read atomic_t variables. atomic_read() and atomic_set() get and set the counter, @@ -870,8 +870,8 @@ - The second class of atomic operations is atomic bit operations, - defined in + The second class of atomic operations is atomic bit operations on a + long, defined in include/asm/bitops.h. These operations generally take a pointer to the bit pattern, and a bit @@ -887,8 +887,14 @@ It is possible to call these operations with bit indices greater - than 31. The resulting behavior is strange on big-endian + than BITS_PER_LONG. The resulting behavior is strange on big-endian platforms though so it is a good idea not to do this. + + + + Note that the order of bits depends on the architecture, and in + particular, the bitfield passed to these operations must be at + least as large as a long. diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/DocBook/videobook.tmpl linux/Documentation/DocBook/videobook.tmpl --- v2.4.0-test11/linux/Documentation/DocBook/videobook.tmpl Sun Oct 8 10:50:04 2000 +++ linux/Documentation/DocBook/videobook.tmpl Mon Dec 11 13:42:49 2000 @@ -66,7 +66,7 @@ vertical blanking data interfaces are also provided. - + Radio Devices There are a wide variety of radio interfaces available for PC's, and these diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/README.DAC960 linux/Documentation/README.DAC960 --- v2.4.0-test11/linux/Documentation/README.DAC960 Mon Aug 21 09:23:54 2000 +++ linux/Documentation/README.DAC960 Thu Dec 7 17:05:41 2000 @@ -1,11 +1,11 @@ Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Version 2.2.8 for Linux 2.2.16 - Version 2.4.8 for Linux 2.4.0 + Version 2.2.9 for Linux 2.2.17 + Version 2.4.9 for Linux 2.4.0 PRODUCTION RELEASE - 19 August 2000 + 7 September 2000 Leonard N. Zubkoff Dandelion Digital @@ -203,13 +203,13 @@ DRIVER INSTALLATION -This distribution was prepared for Linux kernel version 2.2.16 or 2.4.0. +This distribution was prepared for Linux kernel version 2.2.17 or 2.4.0. To install the DAC960 RAID driver, you may use the following commands, replacing "/usr/src" with wherever you keep your Linux kernel source tree: cd /usr/src - tar -xvzf DAC960-2.2.8.tar.gz (or DAC960-2.4.8.tar.gz) + tar -xvzf DAC960-2.2.9.tar.gz (or DAC960-2.4.9.tar.gz) mv README.DAC960 linux/Documentation mv DAC960.[ch] linux/drivers/block patch -p0 < DAC960.patch (if DAC960.patch is included) diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/SubmittingDrivers linux/Documentation/SubmittingDrivers --- v2.4.0-test11/linux/Documentation/SubmittingDrivers Sun Oct 8 10:50:04 2000 +++ linux/Documentation/SubmittingDrivers Sun Dec 3 17:48:18 2000 @@ -6,13 +6,17 @@ card drivers you should probably talk to XFree86 (http://wwww.xfree86.org) instead. +Also read the Documentation/SubmittingPatches document. + + Allocating Device Numbers ------------------------- -Major and minor numbers for devices are allocated by the Linux assigned name -and number authority (currently better known as H Peter Anvin). The -site is http://www.lanana.org/. This also deals with allocating numbers for -devices that are not going to be submitted to the mainstream kernel. +Major and minor numbers for block and character devices are allocated +by the Linux assigned name and number authority (currently better +known as H Peter Anvin). The site is http://www.lanana.org/. This +also deals with allocating numbers for devices that are not going to +be submitted to the mainstream kernel. If you don't use assigned numbers then when you device is submitted it will get given an assigned number even if that is different from values you may @@ -76,7 +80,8 @@ the author then patches will be redirected to them unless they are totally obvious and without need of checking. If you want to be the contact and update point for the - driver it is a good idea to state this in the comments. + driver it is a good idea to state this in the comments, + and include an entry in MAINTAINERS for your driver. What Criteria Do Not Determine Acceptance ----------------------------------------- @@ -97,7 +102,8 @@ --------- Linux kernel master tree: - ftp.kernel.org:/pub/linux/kernel/... + ftp.??.kernel.org:/pub/linux/kernel/... + ?? == your country code, such as "us", "uk", "fr", etc. Linux kernel mailing list: linux-kernel@vger.kernel.org diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/SubmittingPatches linux/Documentation/SubmittingPatches --- v2.4.0-test11/linux/Documentation/SubmittingPatches Wed Dec 31 16:00:00 1969 +++ linux/Documentation/SubmittingPatches Sun Dec 3 17:48:18 2000 @@ -0,0 +1,286 @@ + + How to Get Your Change Into the Linux Kernel + or + Care And Operation Of Your Linus Torvalds + + + +For a person or company who wishes to submit a change to the Linux +kernel, the process can sometimes be daunting if you're not familiar +with "the system." This text is a collection of suggestions which +can greatly increase the chances of your change being accepted. + +If you are submitting a driver, also read Documentation/SubmittingDrivers. + + + +-------------------------------------------- +SECTION 1 - CREATING AND SENDING YOUR CHANGE +-------------------------------------------- + + + +1) "diff -u" +------------ + +Use "diff -u" or "diff -urN" to create patches. + +All changes to the Linux kernel occur in the form of patches, as +generated by diff(1). When creating your patch, make sure to create it +in "unified diff" format, as supplied by the '-u' argument to diff(1). +Patches should be based in the root kernel source directory, not in +any lower subdirectory. + +To create a patch for a single file, it is often sufficient to do: + + SRCTREE= /devel/linux-2.4 + MYFILE= drivers/net/mydriver.c + + cd $SRCTREE + cp $MYFILE $MYFILE.orig + vi $MYFILE # make your change + diff -u $MYFILE.orig $MYFILE > /tmp/patch + +To create a patch for multiple files, you should unpack a "vanilla", +or unmodified kernel source tree, and generate a diff against your +own source tree. For example: + + MYSRC= /devel/linux-2.4 + + tar xvfz linux-2.4.0-test11.tar.gz + mv linux linux-vanilla + wget http://www.moses.uklinux.net/patches/dontdiff + diff -urN -X dontdiff linux-vanilla $MYSRC > /tmp/patch + rm -f dontdiff + +"dontdiff" is a list of files which are generated by the kernel during +the build process, and should be ignored in any diff(1)-generated +patch. dontdiff is maintained by Tigran Aivazian + +Make sure your patch does not include any extra files which do not +belong in a patch submission. Make sure to review your patch -after- +generated it with diff(1), to ensure accuracy. + + +2) Describe your changes. + +Describe the technical detail of the change(s) your patch includes. + +Be as specific as possible. The WORST descriptions possible include +things like "update driver X", "bug fix for driver X", or "this patch +includes updates for subsystem X. Please apply." + +If your description starts to get long, that's a sign that you probably +need to split up your patch. See #3, next. + + + +3) Separate your changes. + +Separate each logical change into its own patch. + +For example, if your changes include both bug fixes and performance +enhancements for a single driver, separate those changes into two +or more patches. If your changes include an API update, and a new +driver which uses that new API, separate those into two patches. + +On the other hand, if you make a single change to numerous files, +group those changes into a single patch. Thus a single logical change +is contained within a single patch. + +If one patch depends on another patch in order for a change to be +complete, that is OK. Simply note "this patch depends on patch X" +in your patch description. + + +4) Select e-mail destination. + +Look through the MAINTAINERS file and the source code, and determine +if your change applies to a specific subsystem of the kernel, with +an assigned maintainer. If so, e-mail that person. + +If no maintainer is listed, or the maintainer does not respond, send +your patch to the primary Linux kernel developer's mailing list, +linux-kernel@vger.kernel.org. Most kernel developers monitor this +e-mail list, and can comment on your changes. + +Linus Torvalds is the final arbiter of all changes accepted into the +Linux kernel. His e-mail address is torvalds@transmeta.com. He gets +a lot of e-mail, so typically you should do your best to -avoid- sending +him e-mail. + +Patches which are bug fixes, are "obvious" changes, or similarly +require little discussion should be sent or CC'd to Linus. Patches +which require discussion or do not have a clear advantage should +usually be sent first to linux-kernel. Only after the patch is +discussed should the patch then be submitted to Linus. + + + +5) Select your CC (e-mail carbon copy) list. + +Unless you have a reason NOT to do so, CC linux-kernel@vger.kernel.org. + +Other kernel developers besides Linus need to be aware of your change, +so that they may comment on it and offer code review and suggestions. +linux-kernel is the primary Linux kernel developer mailing list. +Other mailing lists are available for specific subsystems, such as +USB, framebuffer devices, the VFS, the SCSI subsystem, etc. See the +MAINTAINERS file for a mailing list that relates specifically to +your change. + +Even if the maintainer did not respond in step #4, make sure to ALWAYS +copy the maintainer when you change their code. + + + +6) No MIME, no links, no compression, no attachments. Just plain text. + +Linus and other kernel developers need to be able to read and comment +on the changes you are submitting. It is important for a kernel +developer to be able to "quote" your changes, using standard e-mail +tools, so that they may comment on specific portions of your code. + +For this reason, all patches should be submitting e-mail "inline". +WARNING: Be wary of your editor's word-wrap corrupting your patch, +if you choose to cut-n-paste your patch. + +Do not attach the patch as a MIME attachment, compressed or not. +Many popular e-mail applications will not always transmit a MIME +attachment as plain text, making it impossible to comment on your +code. A MIME attachment also takes Linus a bit more time to process, +decreasing the likelihood of your MIME-attached change being accepted. + +Exception: If your mailer is mangling patches then someone may ask +you to re-send them using MIME. + + + +7) E-mail size. + +When sending patches to Linus, always follow step #6. + +Large changes are not appropriate for mailing lists, and some +maintainers. If your patch, uncompressed, exceeds 40Kb in size, +it is preferred that you store your patch on an Internet-accessible +server, and provide instead a URL (link) pointing to your patch. + + + +8) Name your kernel version. + +It is important to note, either in the subject line or in the patch +description, the kernel version to which this patch applies. + +If the patch does not apply cleanly to the latest kernel version, +Linus will not apply it. + + + +9) Don't get discouraged. Re-submit. + +After you have submitted your change, be patient and wait. If Linus +likes your change and applies it, it will appear in the next version +of the kernel that he releases. + +However, if your change doesn't appear in the next version of the +kernel, there could be any number of reasons. It's YOUR job to +narrow down those reasons, correct what was wrong, and submit your +updated change. + +It is quite common for Linus to "drop" your patch without comment. +That's the nature of the system. If he drops your patch, it could be +due to +* Your patch did not apply cleanly to the latest kernel version +* Your patch was not sufficiently discussed on linux-kernel. +* A style issue (see section 2), +* An e-mail formatting issue (re-read this section) +* A technical problem with your change +* He gets tons of e-mail, and yours got lost in the shuffle +* You are being annoying (See Figure 1) + +When in doubt, solicit comments on linux-kernel mailing list. + + + +10) Include PATCH in the subject + +Due to high e-mail traffic to Linus, and to linux-kernel, it is common +convention to prefix your subject line with [PATCH]. This lets Linus +and other kernel developers more easily distinguish patches from other +e-mail discussions. + + + +----------------------------------- +SECTION 2 - HINTS, TIPS, AND TRICKS +----------------------------------- + +This section lists many of the common "rules" associated with code +submitted to the kernel. There are always exceptions... but you must +have a really good reason for doing so. You could probably call this +section Linus Computer Science 101. + + + +1) Read Documentation/CodingStyle + +Nuff said. If your code deviates too much from this, it is likely +to be rejected without further review, and without comment. + + + +2) #ifdefs are ugly + +Code cluttered with ifdefs is difficult to read and maintain. Don't do +it. Instead, put your ifdefs in a header, and conditionally define +'static inline' functions, or macros, which are used in the code. +Let the compiler optimize away the "no-op" case. + +Simple example, of poor code: + + dev = init_etherdev (NULL, 0); + if (!dev) + return -ENODEV; + #ifdef CONFIG_NET_FUNKINESS + init_funky_net(dev); + #endif + +Cleaned-up example: + +(in header) + #ifndef CONFIG_NET_FUNKINESS + static inline void init_funky_net (struct net_device *d) {} + #endif + +(in the code itself) + dev = init_etherdev (NULL, 0); + if (!dev) + return -ENODEV; + init_funky_net(dev); + + + +3) 'static inline' is better than a macro + +Static inline functions are greatly preferred over macros. +They provide type safety, have no length limitations, no formatting +limitations, and under gcc they are as cheap as macros. + +Macros should only be used for cases where a static inline is clearly +suboptimal [there a few, isolated cases of this in fast paths], +or where it is impossible to use a static inline function [such as +string-izing]. + +'static inline' is preferred over 'static __inline__', 'extern inline', +and 'extern __inline__'. + + + +4) Don't over-design. + +Don't try to anticipate nebulous future cases which may or may not +be useful: "Make it as simple as you can, and no simpler" + + + diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/arm/README linux/Documentation/arm/README --- v2.4.0-test11/linux/Documentation/arm/README Sun Oct 8 10:50:04 2000 +++ linux/Documentation/arm/README Mon Nov 27 17:07:59 2000 @@ -157,7 +157,8 @@ the mail a subject of 'Register new architecture': Name: - ARCHDIR: + ArchDir: + Type: Description: diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/arm/SA1100/GraphicsClient linux/Documentation/arm/SA1100/GraphicsClient --- v2.4.0-test11/linux/Documentation/arm/SA1100/GraphicsClient Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/GraphicsClient Mon Nov 27 17:07:59 2000 @@ -0,0 +1,65 @@ +ADS GraphicsClient/ThinClient Single Board Computer + +For more details, contact Applied Data Systems or see +http://www.flatpanels.com/products.html + +The original Linux support for this product has been provided by +Nicolas Pitre . + +It's currently possible to mount a root filesystem via NFS providing a +complete Linux environment. Otherwise a ramdisk image may be used. Use +'make graphicsclient_config' before any 'make config'. This will set up +defaults for GraphicsClient/ThinClient support. + +The kernel zImage is linked to be loaded and executed at 0xc0200000. +Also the following registers should have the specified values upon entry: + + r0 = 0 + r1 = 29 (this is the GraphicsClient architecture number) + +Here is a tipical angel.opt option file if the kernel is loaded through +the Angel Debug Monitor: + +----- begin angelboot.opt ----- +base 0xc0200000 +entry 0xc0200000 +r0 0x00000000 +r1 0x0000001d +device /dev/ttyS1 +options "9600 8N1" +baud 115200 +#otherfile ramdisk.gz +#otherbase 0xc0800000 +exec minicom +----- end angelboot.opt ----- + +Then the kernel (and ramdisk if otherfile/otherbase lines above are +uncommented) would be loaded with: + + angelboot -f angelboot.opt zImage + +Here it is assumed that the board is connected to ttyS1 on your PC +and that minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow +control by default. + +If any other bootloader is used, ensure it accomplish the same, especially +for r0/r1 register values before jumping into the kernel. + + +Supported peripherals: +- SA1100 LCD frame buffer (only 8bpp yet) +- on-board SMC 92C94 ethernet NIC +- SA1100 serial port +- flash memory access +- pcmcia +- possibly UCB1200 audio (not tested yet) + +To do: +- touchscreen driver +- 16bpp frame buffer support +- extra (external) serial port driver +- some console keyboard support (maybe IR?) +- everything else! :-) + +Any contribution can be sent to nico@cam.org and will be greatly welcome! + diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/arm/SA1100/Pangolin linux/Documentation/arm/SA1100/Pangolin --- v2.4.0-test11/linux/Documentation/arm/SA1100/Pangolin Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/Pangolin Mon Nov 27 17:07:59 2000 @@ -0,0 +1,25 @@ +Pangolin is a StrongARM 1110-based evaluation platform produced +by Dialogue Technoloy (http://www.dialogue.com.tw/). +It has EISA slots for ease of configuration with SDRAM/Flash +memory card, USB/Serial/Audio card, Compact Flash card, +and TFT-LCD card. +This platform is currently under development. + +To compile for Pangolin, you must issue the following commands: + + make pangolin_config + make config + [accept all defaults] + make dep + make zImage + +Supported peripherals: +- SA1110 serial port +- flash memory access + +Testing: +- pcmcia driver +- sound driver + +To do: +- MQ-200 driver diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/arm/SA1100/ThinClient linux/Documentation/arm/SA1100/ThinClient --- v2.4.0-test11/linux/Documentation/arm/SA1100/ThinClient Fri Jul 28 12:50:51 2000 +++ linux/Documentation/arm/SA1100/ThinClient Wed Dec 31 16:00:00 1969 @@ -1,68 +0,0 @@ -Thin Client / Single Board Computer - -The Thin Client, a low cost high power single board computer, has been -designed to provide intuitive graphical displays in embedded systems. - -For more details, contact Applied Data Systems or see -http://www.flatpanels.com/products.html - -Current Linux support for this product has been provided by Nicolas Pitre -. - -It's currently possible to mount a root filesystem via NFS providing a -complete Linux environment. Otherwise a ramdisk image may be used. Use -'make thinclient_config' before any 'make config'. This will set up -defaults for ThinClient support. - -The kernel zImage is linked to be loaded and executed at 0xc0200000. -Also the following registers should have the specified values upon entry: - - r0 = 0 - r1 = 24 (this is the ThinClient architecture number) - -Here is a tipical angel.opt option file if the kernel is loaded through -the Angel Debug Monitor: - ------ begin angelboot.opt ----- -base 0xc0200000 -entry 0xc0200000 -r0 0x00000000 -r1 0x00000018 -device /dev/ttyS1 -options "9600 8N1" -baud 115200 -#otherfile ramdisk.gz -#otherbase 0xc0800000 -exec minicom ------ end angelboot.opt ----- - -Then the kernel (and ramdisk if otherfile/otherbase lines above are -uncommented) would be loaded with: - - angelboot -f angelboot.opt zImage - -Here it is assumed that the ThinClient is connected to ttyS1 on your PC -and that minicom is preconfigured with /dev/ttyS1, 9600 baud, 8N1, no flow -control by default. - -If any other bootloader is used, ensure it accomplish the same, especially -for r0/r1 register values before jumping into the kernel. - - -Supported peripherals: -- SA1100 LCD frame buffer (only 8bpp yet) -- on-board SMC 92C94 ethernet NIC -- SA1100 serial port -- flash memory access -- possibly UCB1200 audio (not tested yet) - -To do: -- touchscreen driver -- 16bpp frame buffer support -- extra (external) serial port driver -- pcmcia -- some console keyboard support (maybe IR?) -- everything else! :-) - -Any contribution can be sent to nico@cam.org and will be greatly welcome! - diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/arm/SA1100/serial_UART linux/Documentation/arm/SA1100/serial_UART --- v2.4.0-test11/linux/Documentation/arm/SA1100/serial_UART Wed Dec 31 16:00:00 1969 +++ linux/Documentation/arm/SA1100/serial_UART Mon Nov 27 17:07:59 2000 @@ -0,0 +1,65 @@ +The SA1100 serial port finally had its major/minor numbers officially +assigned: + +> Date: Sun, 24 Sep 2000 21:40:27 -0700 +> From: H. Peter Anvin +> To: Nicolas Pitre +> Cc: Device List Maintainer +> Subject: Re: device +> +> Okay. Note that device numbers 204 and 205 are used for "low density +> serial devices", so you will have a range of minors on those majors (the +> tty device layer handles this just fine, so you don't have to worry about +> doing anything special.) +> +> So your assignments are: +> +> 204 char Low-density serial ports +> 5 = /dev/ttySA0 SA1100 builtin serial port 0 +> 6 = /dev/ttySA1 SA1100 builtin serial port 1 +> 7 = /dev/ttySA2 SA1100 builtin serial port 2 +> +> 205 char Low-density serial ports (alternate device) +> 5 = /dev/cusa0 Callout device for ttySA0 +> 6 = /dev/cusa1 Callout device for ttySA1 +> 7 = /dev/cusa2 Callout device for ttySA2 +> + +So, if you're not using devfs, you must create those inodes in /dev +on the root filesystem used by your SA1100-based device: + + mknod ttySA0 c 204 5 + mknod ttySA1 c 204 6 + mknod ttySA2 c 204 7 + mknod cusa0 c 205 5 + mknod cusa1 c 205 6 + mknod cusa2 c 205 7 + +Note that the old incorrect use of /dev/ttyS0 in order to use the serial port +won't work anymore. This device node is reserved to the conventionnal 16x50 +UART which may appear on devices like PCMCIA modem, etc. + +In addition to the creation of the appropriate device nodes above, you must +ensure your user space applications make use of the correct device name. +The classic example is the content of the /etc/inittab where you might have +a getty process started on ttyS0. In this case you have two choices: + +1- replace occurences of ttyS0 with ttySA0, ttyS1 with ttySA1, etc. + +2- in the occurence of 'ttyS0', you may consider replacing it with 'console'. + as in "T0:12345:respawn:/sbin/getty -L console 9600 vt100" + +(don't forget to add 'ttySA0', 'console', or the appropriate tty name + in /etc/securetty for root to be allowed to login as well.) + +The use of /dev/console has the advantage of being independent of the real +serial device used. The kernel automatically forward all operations on +/dev/console to the apropriate serial device. The nature of the console may +also be modified with a kernel command line parameter (see +Documentation/serial-console.txt for the details). Of course, +/dev/console must have been created as a char device with major 5 minor 1. + +Using /dev/console is also compatible with older kernels that used /dev/ttyS0. +Therefore it is handy for ramdisk images which are targetted for different +StrongARM platforms and older kernels. + diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/cachetlb.txt linux/Documentation/cachetlb.txt --- v2.4.0-test11/linux/Documentation/cachetlb.txt Sun Nov 19 18:44:01 2000 +++ linux/Documentation/cachetlb.txt Mon Dec 11 12:37:04 2000 @@ -257,7 +257,7 @@ Here is the new interface: - void copy_user_page(void *from, void *to, unsigned long address) + void copy_user_page(void *to, void *from, unsigned long address) void clear_user_page(void *to, unsigned long address) These two routines store data in user anonymous or COW diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README --- v2.4.0-test11/linux/Documentation/filesystems/devfs/README Wed Jul 5 21:36:49 2000 +++ linux/Documentation/filesystems/devfs/README Wed Nov 29 10:11:38 2000 @@ -529,7 +529,7 @@ If you want to construct a minimal chroot() gaol, the following command should suffice: -mount -t bind /dev/null /gaol/dev/null +mount --bind /dev/null /gaol/dev/null Repeat for other device nodes you want to expose. Simple! @@ -739,7 +739,7 @@ add the following lines near the very beginning of your boot scripts: -mount -t bind /dev /dev-state +mount --bind /dev /dev-state mount -t devfs none /dev devfsd /dev diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/filesystems/proc.txt linux/Documentation/filesystems/proc.txt --- v2.4.0-test11/linux/Documentation/filesystems/proc.txt Sun Oct 8 10:50:04 2000 +++ linux/Documentation/filesystems/proc.txt Mon Nov 27 17:47:38 2000 @@ -3,8 +3,11 @@ ------------------------------------------------------------------------------ /proc/sys Terrehon Bowden October 7 1999 Bodo Bauer + +2.4.x update Jorge Nerin November 14 2000 ------------------------------------------------------------------------------ -Version 1.2 Kernel version 2.2.12 +Version 1.3 Kernel version 2.2.12 + Kernel version 2.4.0-test11-pre4 ------------------------------------------------------------------------------ Table of Contents @@ -42,17 +45,18 @@ 0.1 Introduction/Credits ------------------------ -This documentation is part of a soon (or so we hope) to be released book on -the SuSE Linux distribution. As there is no complete documentation for the -/proc file system and we've used many freely available sources to write these -chapters, it seems only fair to give the work back to the Linux community. -This work is based on the 2.2.* kernel version. I'm afraid it's still far from -complete, but we hope it will be useful. As far as we know, it is the first -'all-in-one' document about the /proc file system. It is focused on the Intel -x86 hardware, so if you are looking for PPC, ARM, SPARC, APX, etc., features, -you probably won't find what you are looking for. It also only covers IPv4 -networking, not IPv6 nor other protocols - sorry. But additions and patches -are welcome and will be added to this document if you mail them to Bodo. +This documentation is part of a soon (or so we hope) to be released book on +the SuSE Linux distribution. As there is no complete documentation for the +/proc file system and we've used many freely available sources to write these +chapters, it seems only fair to give the work back to the Linux community. +This work is based on the 2.2.* kernel version and the upcomming 2.4.*. I'm +afraid it's still far from complete, but we hope it will be useful. As far as +we know, it is the first 'all-in-one' document about the /proc file system. It +is focused on the Intel x86 hardware, so if you are looking for PPC, ARM, +SPARC, APX, etc., features, you probably won't find what you are looking for. +It also only covers IPv4 networking, not IPv6 nor other protocols - sorry. But +additions and patches are welcome and will be added to this document if you +mail them to Bodo. We'd like to thank Alan Cox, Rik van Riel, and Alexey Kuznetsov and a lot of other people for help compiling this documentation. We'd also like to extend a @@ -65,9 +69,13 @@ contact Bodo Bauer at bb@ricochet.net. We'll be happy to add them to this document. -The latest version of this document is available online at +The latest version of this document is available online at http://skaro.nightcrawler.com/~bb/Docs/Proc as HTML version. +If the above direction does not works for you, ypu could try the kernel +mailing list at linux-kernel@vger.kernel.org and/or try to reach me at +comandante@zaralinux.com. + 0.2 Legal Stuff --------------- @@ -92,7 +100,7 @@ The proc file system acts as an interface to internal data structures in the kernel. It can be used to obtain information about the system and to change -certain kernel parameters at runtime. +certain kernel parameters at runtime (sysctl). First, we'll take a look at the read-only parts of /proc. In Chapter 2, we show you how you can use /proc/sys to change settings. @@ -111,16 +119,17 @@ .............................................................................. File Content cmdline Command line arguments - environ Values of environment variables + cpu Current and last cpu in wich it was executed (2.4)(smp) + cwd Link to the current working directory + environ Values of environment variables + exe Link to the executable of this process fd Directory, which contains all file descriptors + maps Memory maps to executables and library files (2.4) mem Memory held by this process + root Link to the root directory of this process stat Process status - status Process status in human readable form - cwd Link to the current working directory - exe Link to the executable of this process - maps Memory maps - root Link to the root directory of this process statm Process memory status information + status Process status in human readable form .............................................................................. For example, to get the status information of a process, all you have to do is @@ -131,6 +140,7 @@ State: R (running) Pid: 5452 PPid: 743 + TracerPid: 0 (2.4) Uid: 501 501 501 501 Gid: 100 100 100 100 Groups: 100 14 16 @@ -187,13 +197,20 @@ devices Available devices (block and character) dma Used DMS channels filesystems Supported filesystems + driver Various drivers grouped here, currently rtc (2.4) + execdomains Execdomains, related to security (2.4) + fb Frame Buffer devices (2.4) + fs File system parameters, currently nfs/exports (2.4) ide Directory containing info about the IDE subsystem interrupts Interrupt usage + iomem Memory map (2.4) ioports I/O port usage - kcore Kernel core image (can be ELF or A.OUT) + irq Masks for irq to cpu affinity (2.4)(smp?) + isapnp ISA PnP (Plug&Play) Info (2.4) + kcore Kernel core image (can be ELF or A.OUT(deprecated in 2.4)) kmsg Kernel messages ksyms Kernel symbol table - loadavg Load average + loadavg Load average of last 1, 5 & 15 minutes locks Kernel locks meminfo Memory info misc Miscellaneous @@ -201,14 +218,19 @@ mounts Mounted filesystems net Networking info (see text) partitions Table of partitions known to the system + pci Depreciated info of PCI bus (new way -> /proc/bus/pci/, + decoupled by lspci (2.4) rtc Real time clock scsi SCSI info (see text) slabinfo Slab pool info stat Overall statistics swaps Swap space utilization sys See chapter 2 + sysvipc Info of SysVIPC Resources (msg, sem, shm) (2.4) + tty Info of tty drivers uptime System uptime version Kernel version + video bttv info of video resources (2.4) .............................................................................. You can, for example, check which interrupts are currently in use and what @@ -230,6 +252,68 @@ 15: 7 XT-PIC ide1 NMI: 0 +In 2.4.* a couple of lines where added to this file LOC & ERR (this time is the +output of a SMP machine): + + > cat /proc/interrupts + + CPU0 CPU1 + 0: 1243498 1214548 IO-APIC-edge timer + 1: 8949 8958 IO-APIC-edge keyboard + 2: 0 0 XT-PIC cascade + 5: 11286 10161 IO-APIC-edge soundblaster + 8: 1 0 IO-APIC-edge rtc + 9: 27422 27407 IO-APIC-edge 3c503 + 12: 113645 113873 IO-APIC-edge PS/2 Mouse + 13: 0 0 XT-PIC fpu + 14: 22491 24012 IO-APIC-edge ide0 + 15: 2183 2415 IO-APIC-edge ide1 + 17: 30564 30414 IO-APIC-level eth0 + 18: 177 164 IO-APIC-level bttv + NMI: 2457961 2457959 + LOC: 2457882 2457881 + ERR: 2155 + +NMI is incremented in this case because every timer interrupt generates a NMI +(Non Maskable Interrupt) which is used by the NMI Watchdog to detect lookups. + +LOC is the local interrupt counter of the internal APIC of every CPU. + +ERR is incremented in the case of errors in the IO-APIC bus (the bus that +connects the CPUs in a SMP system. This means that an error has been detected, +the IO-APIC automatically retry the transmision, so it should not be a big +problem, but you should read the SMP-FAQ. + +In this context it could be interesting to note the new irq directory in 2.4. +It could be used to set IRQ to CPU affinity, this means that you can "hook" an +IRQ to only one CPU, or to exclude a CPU of handling IRQs. The contents of the +irq subdir is one subdir for each IRQ, and one file; prof_cpu_mask + +For example + > ls /proc/irq/ + 0 10 12 14 16 18 2 4 6 8 prof_cpu_mask + 1 11 13 15 17 19 3 5 7 9 + > ls /proc/irq/0/ + smp_affinity + +The contents of the prof_cpu_mask file and each smp_affinity file for each IRQ +is the same by default: + + > cat /proc/irq/0/smp_affinity + ffffffff + +It's a bitmask, in wich you can specify wich CPUs can handle the IRQ, you can +set it by doing: + + > echo 1 > /proc/irq/prof_cpu_mask + +This means that only the first CPU will handle the IRQ, but you can also echo 5 +wich means that only the first and fourth CPU can handle the IRQ. + +The way IRQs are routed is handled by the IO-APIC, and it's Round Robin +between all the CPUs which are allowed to handle it. As usual the kernel has +more info than you and does a better job than you, so the defaults are the +best choice for almost everyone. There are three more important subdirectories in /proc: net, scsi, and sys. The general rule is that the contents, or even the existence of these @@ -1306,6 +1390,15 @@ TCP settings ------------ + +tcp_ecn +------- + +This file controls the use of the ECN bit in the IPv4 headers, this is a new +feature about Explicit Congestion Notification, but some routers and firewalls +block trafic that has this bit set, so it could be necessary to echo 0 to +/proc/sys/net/ipv4/tcp_ecn, if you want to talk to this sites. For more info +you could read RFC2481. tcp_retrans_collapse -------------------- diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/initrd.txt linux/Documentation/initrd.txt --- v2.4.0-test11/linux/Documentation/initrd.txt Wed Jun 24 14:30:07 1998 +++ linux/Documentation/initrd.txt Sun Dec 3 17:48:18 2000 @@ -1,25 +1,28 @@ Using the initial RAM disk (initrd) =================================== -Written 1996 by Werner Almesberger and - Hans Lermen +Written 1996,2000 by Werner Almesberger and + Hans Lermen -initrd adds the capability to load a RAM disk by the boot loader. This -RAM disk can then be mounted as the root file system and programs can be -run from it. Afterwards, a new root file system can be mounted from a -different device. The previous root (from initrd) is then either moved -to the directory /initrd or it is unmounted. +initrd provides the capability to load a RAM disk by the boot loader. +This RAM disk can then be mounted as the root file system and programs +can be run from it. Afterwards, a new root file system can be mounted +from a different device. The previous root (from initrd) is then moved +to a directory and can be subsequently unmounted. initrd is mainly designed to allow system startup to occur in two phases, where the kernel comes up with a minimum set of compiled-in drivers, and where additional modules are loaded from initrd. +This document gives a brief overview of the use of initrd. A more detailed +discussion of the boot process can be found in [1]. + Operation --------- -When using initrd, the system boots as follows: +When using initrd, the system typically boots as follows: 1) the boot loader loads the kernel and the initial RAM disk 2) the kernel converts initrd into a "normal" RAM disk and @@ -28,28 +31,17 @@ 4) /linuxrc is executed (this can be any valid executable, including shell scripts; it is run with uid 0 and can do basically everything init can do) - 5) when linuxrc terminates, the "real" root file system is mounted - 6) if a directory /initrd exists, the initrd is moved there - otherwise, initrd is unmounted + 5) linuxrc mounts the "real" root file system + 6) linuxrc places the root file system at the root directory using the + pivot_root system call 7) the usual boot sequence (e.g. invocation of /sbin/init) is performed on the root file system + 8) the initrd file system is removed -Note that moving initrd from / to /initrd does not involve unmounting it. -It is therefore possible to leave processes running on initrd (or leave -file systems mounted, but see below) during that procedure. However, if -/initrd doesn't exist, initrd can only be unmounted if it is not used by -anything. If it can't be unmounted, it will stay in memory. - -Also note that file systems mounted under initrd continue to be accessible, -but their /proc/mounts entries are not updated. Also, if /initrd doesn't -exist, initrd can't be unmounted and will "disappear" and take those file -systems with it, thereby preventing them from being re-mounted. It is -therefore strongly suggested to generally unmount all file systems (except -of course for the root file system, but including /proc) before switching -from initrd to the "normal" root file system. - -In order to deallocate the memory used for the initial RAM disk, you have -to execute freeramdisk (see 'Resources' below) after unmounting /initrd. +Note that changing the root directory does not involve unmounting it. +It is therefore possible to leave processes running on initrd during that +procedure. Also note that file systems mounted under initrd continue to +be accessible. Boot command-line options @@ -57,7 +49,7 @@ initrd adds the following new options: - initrd= (LOADLIN only) + initrd= (e.g. LOADLIN) Loads the specified file as the initial RAM disk. When using LILO, you have to specify the RAM disk image file in /etc/lilo.conf, using the @@ -71,40 +63,38 @@ in this case and doesn't necessarily have to be a file system image. This option is used mainly for debugging. - Note that /dev/initrd is read-only and that it can only be used once. - As soon as the last process has closed it, all data is freed and - /dev/initrd can't be opened any longer. - - root=/dev/ram - - initrd is mounted as root, and /linuxrc is started. If no /linuxrc - exists, the normal boot procedure is followed, with the RAM disk - still mounted as root. This option is mainly useful when booting from - a floppy disk. Compared to directly mounting an on-disk file system, - the intermediate step of going via initrd adds a little speed - advantage and it allows the use of a compressed file system. - Also, together with LOADLIN you may load the RAM disk directly from - CDROM or disk, hence having a floppyless boot from CD, - e.g.: E:\loadlin E:\bzImage root=/dev/ram initrd=E:\rdimage + Note: /dev/initrd is read-only and it can only be used once. As soon + as the last process has closed it, all data is freed and /dev/initrd + can't be opened anymore. + + root=/dev/ram0 (without devfs) + root=/dev/rd/0 (with devfs) + + initrd is mounted as root, and the normal boot procedure is followed, + with the RAM disk still mounted as root. Installation ------------ -First, the "normal" root file system has to be prepared as follows: +First, a directory for the initrd file system has to be created on the +"normal" root file system, e.g. -# mknod /dev/initrd b 1 250 -# chmod 400 /dev/initrd # mkdir /initrd +The name is not relevant. More details can be found on the pivot_root(2) +man page. + If the root file system is created during the boot procedure (i.e. if -you're creating an install floppy), the root file system creation -procedure should perform these operations. +you're building an install floppy), the root file system creation +procedure should create the /initrd directory. -Note that neither /dev/initrd nor /initrd are strictly required for -correct operation of initrd, but it is a lot easier to experiment with -initrd if you have them, and you may also want to use /initrd to pass -data to the "real" system. +If initrd will not be mounted in some cases, its content is still +accessible if the following device has been created (note that this +does not work if using devfs): + +# mknod /dev/initrd b 1 250 +# chmod 400 /dev/initrd Second, the kernel has to be compiled with RAM disk support and with support for the initial RAM disk enabled. Also, at least all components @@ -112,100 +102,148 @@ system) must be compiled into the kernel. Third, you have to create the RAM disk image. This is done by creating a -file system on a block device and then by copying files to it as needed. -With recent kernels, at least three types of devices are suitable for -that: +file system on a block device, copying files to it as needed, and then +copying the content of the block device to the initrd file. With recent +kernels, at least three types of devices are suitable for that: - a floppy disk (works everywhere but it's painfully slow) - a RAM disk (fast, but allocates physical memory) - - a loopback device (the most elegant solution, but currently requires a - modified mount) + - a loopback device (the most elegant solution) -We'll describe the RAM disk method: +We'll describe the loopback device method: - 1) make sure you have a RAM disk device /dev/ram (block, major 1, minor 0) + 1) make sure loopback block devices are configured into the kernel 2) create an empty file system of the appropriate size, e.g. - # mke2fs -m0 /dev/ram 300 + # dd if=/dev/zero of=initrd bs=300k count=1 + # mke2fs -F -m0 initrd (if space is critical, you may want to use the Minix FS instead of Ext2) - 3) mount the file system on an appropriate directory, e.g. - # mount -t ext2 /dev/ram /mnt - 4) create the console device: + 3) mount the file system, e.g. + # mount -t ext2 -o loop initrd /mnt + 4) create the console device (not necessary if using devfs, but it can't + hurt to do it anyway): # mkdir /mnt/dev - # mknod /mnt/dev/tty1 c 4 1 + # mknod /mnt/dev/console c 5 1 5) copy all the files that are needed to properly use the initrd environment. Don't forget the most important file, /linuxrc Note that /linuxrc's permissions must include "x" (execute). - 6) unmount the RAM disk - # umount /dev/ram - 7) copy the image to a file - # dd if=/dev/ram bs=1k count=300 of=/boot/initrd - 8) deallocate the RAM disk - # freeramdisk /dev/ram - -For experimenting with initrd, you may want to take a rescue floppy (e.g. -rescue.gz from Slackware) and only add a symbolic link from /linuxrc to -/bin/sh, e.g. - - # gunzip /dev/ram - # mount -t minix /dev/ram /mnt - # ln -s /bin/sh /mnt/linuxrc - # umount /dev/ram - # dd if=/dev/ram bs=1k count=1440 of=/boot/initrd - # freeramdisk /dev/ram - -Finally, you have to boot the kernel and load initrd. Currently, -preliminary versions of LOADLIN 1.6 and LILO 18 support initrd (see -below for where to get them). With LOADLIN, you simply execute + 6) correct operation the initrd environment can frequently be tested + even without rebooting with the command + # chroot /mnt /linuxrc + This is of course limited to initrds that do not interfere with the + general system state (e.g. by reconfiguring network interfaces, + overwriting mounted devices, trying to start already running demons, + etc. Note however that it is usually possible to use pivot_root in + such a chroot'ed initrd environment.) + 7) unmount the file system + # umount /mnt + 8) the initrd is now in the file "initrd". Optionally, it can now be + compressed + # gzip -9 initrd + +For experimenting with initrd, you may want to take a rescue floppy and +only add a symbolic link from /linuxrc to /bin/sh. Alternatively, you +can try the experimental newlib environment [2] to create a small +initrd. + +Finally, you have to boot the kernel and load initrd. Almost all Linux +boot loaders support initrd. Since the boot process is still compatible +with an older mechanism, the following boot command line parameters +have to be given: + + root=/dev/ram0 init=/linuxrc rw + +if not using devfs, or + + root=/dev/rd/0 init=/linuxrc rw + +if using devfs. (rw is only necessary if writing to the initrd file +system.) + +With LOADLIN, you simply execute LOADLIN initrd= -e.g. LOADLIN C:\LINUX\VMLINUZ initrd=C:\LINUX\INITRD +e.g. LOADLIN C:\LINUX\BZIMAGE initrd=C:\LINUX\INITRD.GZ root=/dev/ram0 + init=/linuxrc rw With LILO, you add the option INITRD= to either the global section -or to the section of the respective kernel in /etc/lilo.conf, e.g. +or to the section of the respective kernel in /etc/lilo.conf, and pass +the options using APPEND, e.g. - image = /vmlinuz - initrd = /boot/initrd + image = /bzImage + initrd = /boot/initrd.gz + append = "root=/dev/ram0 init=/linuxrc rw" and run /sbin/lilo -Now you can boot and enjoy using initrd. - +For other boot loaders, please refer to the respective documentation. -Setting the root device ------------------------ +Now you can boot and enjoy using initrd. -By default, the standard settings in the kernel are used for the root -device, i.e. the default compiled in or set with rdev, or what was passed -with root=xxx on the command line, or, with LILO, what was specified in -/etc/lilo.conf It is also possible to use initrd with an NFS-mounted -root; you have to use the nfs_root_name and nfs_root_addrs boot options -for this. - -It is also possible to change the root device from within the initrd -environment. In order to do so, /proc has to be mounted. Then, the -following files are available: - - /proc/sys/kernel/real-root-dev - /proc/sys/kernel/nfs-root-name - /proc/sys/kernel/nfs-root-addrs -real-root-dev can be changed by writing the number of the new root FS -device to it, e.g. +Changing the root device +------------------------ - # echo 0x301 >/proc/sys/kernel/real-root-dev +When finished with its duties, linuxrc typically changes the root device +and proceeds with starting the Linux system on the "real" root device. -for /dev/hda1. When using an NFS-mounted root, nfs-root-name and -nfs-root-addrs have to be set accordingly and then real-root-dev has to -be set to 0xff, e.g. - - # echo /var/nfsroot >/proc/sys/kernel/nfs-root-name - # echo 193.8.232.2:193.8.232.7::255.255.255.0:idefix \ - >/proc/sys/kernel/nfs-root-addrs - # echo 255 >/proc/sys/kernel/real-root-dev - -If the root device is set to the RAM disk, the root file system is not -moved to /initrd, but the boot procedure is simply continued by starting -init on the initial RAM disk. +The procedure involves the following steps: + - mounting the new root file system + - turning it into the root file system + - removing all accesses to the old (initrd) root file system + - unmounting the initrd file system and de-allocating the RAM disk + +Mounting the new root file system is easy: it just needs to be mounted on +a directory under the current root. Example: + +# mkdir /new-root +# mount -o ro /dev/hda1 /new-root + +The root change is accomplished with the pivot_root system call, which +is also available via the pivot_root utility (see pivot_root(8) man +page; pivot_root is distributed with util-linux version 2.10h or higher +[3]). pivot_root moves the current root to a directory under the new +root, and puts the new root at its place. The directory for the old root +must exist before calling pivot_root. Example: + +# cd /new-root +# mkdir initrd +# pivot_root . initrd + +Now, the linuxrc process may still access the old root via its +executable, shared libraries, standard input/output/error, and its +current root directory. All these references are dropped by the +following command: + +# exec chroot . what-follows dev/console 2>&1 + +Where what-follows is a program under the new root, e.g. /sbin/init +If the new root file system will be used with devfs and has no valid +/dev directory, devfs must be mounted before invoking chroot in order to +provide /dev/console. + +Note: implementation details of pivot_root may change with time. In order +to ensure compatibility, the following points should be observed: + + - before calling pivot_root, the current directory of the invoking + process should point to the new root directory + - use . as the first argument, and the _relative_ path of the directory + for the old root as the second argument + - a chroot program must be available under the old and the new root + - chroot to the new root afterwards + - use relative paths for dev/console in the exec command + +Now, the initrd can be unmounted and the memory allocated by the RAM +disk can be freed: + +# umount /initrd +# blockdev --flushbufs /dev/ram0 # /dev/rd/0 if using devfs + +It is also possible to use initrd with an NFS-mounted root, see the +pivot_root(8) man page for details. + +Note: if linuxrc or any program exec'ed from it terminates for some +reason, the old change_root mechanism is invoked (see section "Obsolete +root change mechanism"). Usage scenarios @@ -215,32 +253,30 @@ kernel configuration at system installation. The procedure would work as follows: - 1) systems boots from floppy or other media with a minimal kernel - (e.g. support for RAM disks, initrd, a.out, and the ext2 FS) and + 1) system boots from floppy or other media with a minimal kernel + (e.g. support for RAM disks, initrd, a.out, and the Ext2 FS) and loads initrd 2) /linuxrc determines what is needed to (1) mount the "real" root FS (i.e. device type, device drivers, file system) and (2) the distribution media (e.g. CD-ROM, network, tape, ...). This can be done by asking the user, by auto-probing, or by using a hybrid approach. - 3) /linuxrc loads the necessary modules + 3) /linuxrc loads the necessary kernel modules 4) /linuxrc creates and populates the root file system (this doesn't have to be a very usable system yet) - 5) /linuxrc unmounts the root file system and possibly any other file - systems it has mounted, sets /proc/sys/kernel/..., and terminates - 6) the root file system is mounted - 7) now that we're sure that the file system is accessible and intact, - the boot loader can be installed - 8) the boot loader is configured to load an initrd with the set of + 5) /linuxrc invokes pivot_root to change the root file system and + execs - via chroot - a program that continues the installation + 6) the boot loader is installed + 7) the boot loader is configured to load an initrd with the set of modules that was used to bring up the system (e.g. /initrd can be modified, then unmounted, and finally, the image is written from - /dev/ram to a file) - 9) now the system is bootable and additional installation tasks can be + /dev/ram0 or /dev/rd/0 to a file) + 8) now the system is bootable and additional installation tasks can be performed The key role of initrd here is to re-use the configuration data during normal system operation without requiring the use of a bloated "generic" -kernel or re-compilation or re-linking of the kernel. +kernel or re-compiling or re-linking the kernel. A second scenario is for installations where Linux runs on systems with different hardware configurations in a single administrative domain. In @@ -252,35 +288,53 @@ A third scenario are more convenient recovery disks, because information like the location of the root FS partition doesn't have to be provided at -boot time, but the system loaded from initrd can use a user-friendly +boot time, but the system loaded from initrd can invoke a user-friendly dialog and it can also perform some sanity checks (or even some form of auto-detection). -Last not least, CDROM distributors may use it for better installation from CD, -either using a LILO boot floppy and bootstrapping a bigger RAM disk via -initrd from CD, or using LOADLIN to directly load the RAM disk from CD -without need of floppies. +Last not least, CD-ROM distributors may use it for better installation +from CD, e.g. by using a boot floppy and bootstrapping a bigger RAM disk +via initrd from CD; or by booting via a loader like LOADLIN or directly +from the CD-ROM, and loading the RAM disk from CD without need of +floppies. + + +Obsolete root change mechanism +------------------------------ + +The following mechanism was used before the introduction of pivot_root. +Current kernels still support it, but you should _not_ rely on its +continued availability. + +It works by mounting the "real" root device (i.e. the one set with rdev +in the kernel image or with root=... at the boot command line) as the +root file system when linuxrc exits. The initrd file system is then +unmounted, or, if it is still busy, moved to a directory /initrd, if +such a directory exists on the new root file system. + +In order to use this mechanism, you do not have to specify the boot +command options root, init, or rw. (If specified, they will affect +the real root file system, not the initrd environment.) + +If /proc is mounted, the "real" root device can be changed from within +linuxrc by writing the number of the new root FS device to the special +file /proc/sys/kernel/real-root-dev, e.g. + + # echo 0x301 >/proc/sys/kernel/real-root-dev + +Note that the mechanism is incompatible with NFS and similar file +systems. -Since initrd is a fairly generic mechanism, it is likely that additional -uses will be found. +This old, deprecated mechanism is commonly called "change_root", while +the new, supported mechanism is called "pivot_root". Resources --------- -The bzImage+initrd patch (bzImage is an extension to load kernels directly -above 1 MB, which allows kernels sizes of up to approximately 2 MB) can be -found at -ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/bzImage+initrd-1.3.71.patch.gz -and -ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/bzImage+initrd-1.3.71.patch.gz - -A preliminary version of LOADLIN 1.6 is available on -ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/loadlin-1.6-pre8-bin.tgz - -A preliminary version of LILO 18 is available on -ftp://lrcftp.epfl.ch/pub/people/almesber/lilo/lilo.18dev3.tar.gz - -A very simple example for building an image for initrd, also including -the program 'freeramdisk', can be found on -ftp://elserv.ffm.fgan.de/pub/linux/loadlin-1.6/initrd-example.tgz +[1] Almesberger, Werner; "Booting Linux: The History and the Future" + ftp://icaftp.epfl.ch/pub/people/almesber/booting/bootinglinux-current.ps.gz +[2] newlib package (experimental), with initrd example + ftp://icaftp.epfl.ch/pub/people/almesber/misc/newlib-linux/ +[3] Brouwer, Andries; "util-linux: Miscellaneous utilities for Linux" + ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/ diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt --- v2.4.0-test11/linux/Documentation/ioctl-number.txt Mon Jun 19 12:56:07 2000 +++ linux/Documentation/ioctl-number.txt Mon Dec 11 13:42:08 2000 @@ -74,8 +74,8 @@ 0x22 all scsi/sg.h '1' 00-1F PPS kit from Ulrich Windl -'6' 00-10 Intel P6 microcode update driver - +'6' 00-10 Intel IA32 microcode update driver + '8' all SNP8023 advanced NIC card 'A' 00-1F linux/apm_bios.h diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/isdn/INTERFACE.fax linux/Documentation/isdn/INTERFACE.fax --- v2.4.0-test11/linux/Documentation/isdn/INTERFACE.fax Fri Jul 28 12:50:51 2000 +++ linux/Documentation/isdn/INTERFACE.fax Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -$Id: INTERFACE.fax,v 1.1 1999/08/11 20:30:28 armin Exp $ +$Id: INTERFACE.fax,v 1.2 2000/08/06 09:22:50 armin Exp $ Description of the fax-subinterface between linklevel and hardwarelevel of diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax --- v2.4.0-test11/linux/Documentation/isdn/README.HiSax Mon Aug 21 07:49:02 2000 +++ linux/Documentation/isdn/README.HiSax Tue Nov 28 21:43:13 2000 @@ -54,6 +54,7 @@ USR Sportster internal TA (compatible Stollmann tina-pp V3) ith Kommunikationstechnik GmbH MIC 16 ISA card Traverse Technologie NETjet PCI S0 card and NETspider U card +Ovislink ISDN sc100-p card (NETjet driver) Dr. Neuhaus Niccy PnP/PCI Siemens I-Surf 1.0 Siemens I-Surf 2.0 (with IPAC, try type 12 asuscom) @@ -191,8 +192,9 @@ 34 Gazel ISDN cards (PCI) none 35 HFC 2BDS0 PCI none 36 W6692 based PCI cards none - 37 HFC 2BDS0 S+, SP/PCMCIA irq,io (pcmcia must be set with cardmgr) + 37 HFC 2BDS0 S+, SP irq,io 38 NETspider U PCI card none + 39 HFC 2BDS0 SP/PCMCIA irq,io (set with cardmgr) At the moment IRQ sharing is only possible with PCI cards. Please make sure that your IRQ is free and enabled for ISA use. diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/kbuild/makefiles.txt linux/Documentation/kbuild/makefiles.txt --- v2.4.0-test11/linux/Documentation/kbuild/makefiles.txt Sun Nov 19 18:44:01 2000 +++ linux/Documentation/kbuild/makefiles.txt Mon Dec 11 13:19:35 2000 @@ -32,6 +32,8 @@ 7.6 Compilation flags 7.7 Miscellaneous variables 8 New-style variables + 8.1 New variables + 8.2 Converting to old-style 9 Compatibility with Linux Kernel 2.2 10 Credits @@ -521,6 +523,8 @@ old-style variables. This is because Rules.make processes only the old-style variables. +See section 8.2 ("Converting to old-style") for examples. + --- 6.4 Rules.make section @@ -679,6 +683,25 @@ options still control whether or not its $(O_TARGET) goes into vmlinux. See the $(M_OBJS) example below. + Sometimes the ordering of all $(OX_OBJS) files before all + $(O_OBJS) files can be a problem, particularly if both + $(O_OBJS) files and $(OX_OBJS) files contain __initcall + declarations where order is important. To avoid this imposed + ordering, the use of $(OX_OBJS) can be dropped altogether and + $(MIX_OBJS) used instead. + + If this approach is used, then: + - All objects to be linked into vmlinux should be listed in + $(O_OBJS) in the desired order. + - All objects to be created as modules should be listed in + $(M_OBJS) + - All objects that export symbols should also be listed in + $(MIX_OBJS). + + This has the same effect as maintaining the + exported/non-exported split, except that there is more control + over the ordering of object files in vmlinux. + --- 7.3 Library file goals @@ -865,6 +888,14 @@ $(LD) -r -o $@ $(sb-objs) + As is mentioned in section 7.2 ("Object file goals"), + $(MIX_OBJS) can also be used simply to list all objects that + export any symbols. If this approach is taken, then + $(O_OBJS), $(L_OBJS), $(M_OBJS) and $(MI_OBJS) should simply + lists all of the vmlinux object files, library object files, + module object files and intermediate module files + respectively. Duplication between $(MI_OBJS) and $(MIX_OBJS) + is not a problem. --- 7.6 Compilation flags @@ -993,6 +1024,8 @@ people define most variables using "new style" but then fall back to "old style" for a few lines. +--- 8.1 New variables + obj-y obj-m obj-n obj- These variables replace $(O_OBJS), $(OX_OBJS), $(M_OBJS), @@ -1184,6 +1217,41 @@ This means nls should be added to (subdir-y) and $(subdir-m) if CONFIG_NFS = y. +--- 8.2 Converting to old-style + + The following example is taken from drivers/usb/Makefile. + Note that this uses MIX_OBJS to avoid the need for OX_OBJS and + MX_OBJS and thus to maintain the ordering of objects in $(obj-y) + + # Translate to Rules.make lists. + multi-used := $(filter $(list-multi), $(obj-y) $(obj-m)) + multi-objs := $(foreach m, $(multi-used), $($(basename $(m))-objs)) + active-objs := $(sort $(multi-objs) $(obj-y) $(obj-m)) + + O_OBJS := $(obj-y) + M_OBJS := $(obj-m) + MIX_OBJS := $(filter $(export-objs), $(active-objs)) + + An example for libraries from drivers/acorn/scsi/Makefile: + + # Translate to Rules.make lists. + + L_OBJS := $(filter-out $(export-objs), $(obj-y)) + LX_OBJS := $(filter $(export-objs), $(obj-y)) + M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) + MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) + + As ordering is not so important in libraries, this still uses + LX_OBJS and MX_OBJS, though (presumably) it could be changed to + use MIX_OBJS as follows: + + active-objs := $(sort $(obj-y) $(obj-m)) + L_OBJS := $(obj-y) + M_OBJS := $(obj-m) + MIX_OBJS := $(filter $(export-objs), $(active-objs)) + + + which is clearly shorted and arguably clearer. === 9 Compatibility with Linux Kernel 2.2 diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/networking/irda.txt linux/Documentation/networking/irda.txt --- v2.4.0-test11/linux/Documentation/networking/irda.txt Tue Sep 7 10:14:36 1999 +++ linux/Documentation/networking/irda.txt Mon Nov 27 18:07:31 2000 @@ -1,10 +1,10 @@ To use the IrDA protocols within Linux you will need to get a suitable copy of the IrDA Utilities. More detailed information about these and associated -programs can be found on http://www.cs.uit.no/linux-irda/ +programs can be found on http://irda.sourceforge.net/ For more information about how to use the IrDA protocol stack, see the -IR-HOWTO (http://www.snafu.de/~wehe/IR-HOWTO.html) written by Werner Heuser - +IR-HOWTO (http://www.mobilix.org/Infrared-HOWTO/Infrared-HOWTO.html) written by Werner Heuser + There is an active mailing list for discussing Linux-IrDA matters called linux-irda. To subscribe to it, visit: diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/parisc/00-INDEX linux/Documentation/parisc/00-INDEX --- v2.4.0-test11/linux/Documentation/parisc/00-INDEX Wed Dec 31 16:00:00 1969 +++ linux/Documentation/parisc/00-INDEX Tue Dec 5 12:29:38 2000 @@ -0,0 +1,10 @@ +00-INDEX + - this file. +IODC.txt + - Documentation IODC +debugging + - some debugging hints for real-mode code +mm + - Documentation on parisc mm status +registers + - current/planned usage of registers diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/parisc/IODC.txt linux/Documentation/parisc/IODC.txt --- v2.4.0-test11/linux/Documentation/parisc/IODC.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/parisc/IODC.txt Tue Dec 5 12:29:38 2000 @@ -0,0 +1,68 @@ +Some notes on IODC, its general brokenness, and how to work around it. + +Short Version + +IODC is HP's pre-PCI standard for device identification (a la PCI vendor, +device IDs), detection, configuration, initialization and so on. + +It also can provide firmware function to do the actual IO, which are slow, +not really defined for runtime usage and generally not desirable. (There +are other firmware standards, such as STI, to do real IO). + +Usually, there are two parts to IODC. The actual ROMs, which are laid out, +detected aso in a bus-specific manner (IO_DC_ADDRESS / IO_DC_DATA on +GSC/Runway, PCI spec - compliant ROMs for PCI, God-only-knows how on EISA), +and the slightly cooked data read by PDC_IODC. + +The ROM layout is generally icky (only one byte out of every 4-byte-word +might be valid, and many devices don't implement required options), so +using PDC_IODC is highly recommended. (In fact, you should use the device +lists set up by the kernel proper instead of calling PDC_IODC yourself). + +Now, let's have a look at what the cooked ROM looks like (see iodc.pdf for +the details, this is the simplified version). + +Basically, the first 8 bytes of IODC contain two 32-bit ids called HVERSION +and SVERSION. Those are further split up into bit fields, and +unfortunately just ignoring this split up isn't an option. + +SVERSION consists of a 4-bit revision field, a 20-bit model field and a +8-bit opt field. Now, forget the revision and opt fields exist. Basically, +the model field is equivalent to a PCI device id (there is no vendor id. +this is proprietary hardware we're talking about). That is, all your +driver cares for, in 90 % of the cases, is to find all devices that match +the model field. + +The rev field is - you guessed it - roughly equivalent to the revision +byte for PCI, with the exception that higher revisions should be strict +supersets of lower revisions. + +The last byte of HVERSION, "type", and the last byte of SVERSION, "opt", +belong together; type gives a very rough indication of what the device +is supposed to do, and opt contains some type-specific information. (For +example, the "bus converter" (ie bus bridge) type encodes the kind of +bus behind the bridge in the opt field. + +The rest of HVERSION contains, in most cases, a number identifying the +machine the chip was used in, or a revision indicator that just fixed +bugs and didn't add any features (or was done in a shrinked process or +whatever). + +So, here's the interface you actually should use to find your devices: + + +/* Find a device, matching the model field of sversion only (from=NULL + * for the first call */ +struct iodc_dev *iodc_find_device(u32 sversion, struct iodc_dev *from); + + +Here's a function you should use if you have special requirements, such +as finding devices by type rather than by model. Generally, if you're +using this, you should be me). + +/* Find a device, masking out bits as specified */ +struct iodc_dev *iodc_find_device_mask(u32 hversion, u32 sversion, + u32 hversion_mask, u32 sversion_mask, struct iodc_dev *from); + + + Philipp Rumpf diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/parisc/debugging linux/Documentation/parisc/debugging --- v2.4.0-test11/linux/Documentation/parisc/debugging Wed Dec 31 16:00:00 1969 +++ linux/Documentation/parisc/debugging Tue Dec 5 12:29:38 2000 @@ -0,0 +1,39 @@ +okay, here are some hints for debugging the lower-level parts of +linux/parisc. + + +1. Absolute addresses + +A lot of the assembly code currently runs in real mode, which means +absolute addresses are used instead of virtual addresses as in the +rest of the kernel. To translate an absolute address to a virtual +address you can lookup in System.map, add __PAGE_OFFSET (0xc0000000 +currently). + + +2. HPMCs + +When real-mode code tries to access non-existent memory, you'll get +an HPMC instead of a kernel oops. To debug an HPMC, try to find +the System Responder/Requestor addresses. The System Requestor +address should match (one of the) processor HPAs (high addresses in +the I/O range); the System Responder address is the address real-mode +code tried to access. + +Typical values for the System Responder address are addresses larger +than __PAGE_OFFSET (0xc0000000) which mean a virtual address didn't +get translated to a physical address before real-mode code tried to +access it. + + +3. Q bit fun + +Certain, very critical code has to clear the Q bit in the PSW. What +happens when the Q bit is cleared is the CPU does not update the +registers interruption handlers read to find out where the machine +was interrupted - so if you get an interruption between the instruction +that clears the Q bit and the RFI that sets it again you don't know +where exactly it happened. If you're lucky the IAOQ will point to the +instrucion that cleared the Q bit, if you're not it points anywhere +at all. Usually Q bit problems will show themselves in unexplainable +system hangs or running off the end of physical memory. diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/parisc/mm linux/Documentation/parisc/mm --- v2.4.0-test11/linux/Documentation/parisc/mm Wed Dec 31 16:00:00 1969 +++ linux/Documentation/parisc/mm Tue Dec 5 12:29:38 2000 @@ -0,0 +1,31 @@ + +The current state of Linux/PA-RISC mm is BROKEN. + +Someone needs to sit down and thoroughly rewrite all the cache flushing +macro definitions. Here are some of the problems, followed by what I +think needs to be done about them. + +(1) We're using fdce / fice everywhere. This has to stop (except in +the routines which flush the entire cache). The right instructions to +be using are fdc/fic. + +(2) fdc/fic will throw exceptions if the address they reference isn't +mapped. Therefore we need to check the page is mapped before flushing +(we're guaranteed not to have the page dirty if we don't have a software +mapping for it any longer, right?) + +(3) the flush macros are right now tunnelled down to one routine to flush +the data cache and one routine to flush the insn cache. this is wrong. +we should take hints from how we're called and optimise our routines +accordingly. + +(4) fdc/fic actually take space register arguments. fic takes an 3-bit sr +argument and fdc takes a 2-bit sr argument. right now, there's a lot of +pissing about with %sr1 and all the macros use %sr1. This is crazy. We +normally _know_ what's being referred to, and it's the current task. So +if we want to flush that, just use %sr3. If it happens to be kernel, +use %sr0 for fdc and %sr4 for fic. + +(5) we need to write flush_kernel_dcache_range and use it on kernel +addresses. all the macros are defined to work on the _current task's_ +virtual address space. diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/parisc/registers linux/Documentation/parisc/registers --- v2.4.0-test11/linux/Documentation/parisc/registers Wed Dec 31 16:00:00 1969 +++ linux/Documentation/parisc/registers Tue Dec 5 12:29:38 2000 @@ -0,0 +1,126 @@ +Register Usage for Linux/PA-RISC + +[ an asterisk is used for planned usage which is currently unimplemented ] + + General Registers as specified by ABI + + FPU Registers must not be used in kernel mode + + Control Registers + +CR 0 (Recovery Counter) used for ptrace +CR 1-CR 7(undefined) unused +CR 8 (Protection ID) per-process value* +CR 9, 12, 13 (PIDS) unused +CR10 (CCR) lazy FPU saving* +CR11 as specified by ABI +CR14 (interruption vector) initialized to fault_vector +CR15 (EIEM) initialized to all ones* +CR16 (Interval Timer) timer interrupt +CR17-CR22 interruption parameters +CR23 (EIRR) read for pending interrupts +CR24 (TR 0) Kernel Space Page Directory Pointer +CR25 (TR 1) User Space Page Directory Pointer +CR26 (TR 2) +CR27 (TR 3) +CR28 (TR 4) used by interruption handlers +CR29 (TR 5) used by interruption handlers +CR30 (TR 6) current / 0 +CR31 (TR 7) used by interruption handlers + + Space Registers (kernel mode) + +SR0 temporary space register +SR4-SR7 set to 0 +SR1 temporary space register +SR2 unused +SR3 used for userspace accesses (current process)* + + Space Registers (user mode) + +SR0 temporary space register +SR1 temporary space register +SR2 holds space of linux gateway page +SR3 holds user address space value while in kernel +SR4-SR7 Defines short address space for user/kernel + + + Processor Status Word + +W (64-bit addresses) 0 +E (Little-endian) 0 +S (Secure Interval Timer) 0 +T (Taken Branch Trap) 0 +H (Higher-privilege trap) 0 +L (Lower-privilege trap) 0 +N (Nullify next instruction) used by C code +X (Data memory break disable) 0 +B (Taken Branch) used by C code +C (code address translation) 1, 0 while executing real-mode code +V (divide step correction) used by C code +M (HPMC mask) 0, 1 while executing HPMC handler* +C/B (carry/borrow bits) used by C code +O (ordered references) 1* +F (performance monitor) 0 +R (Recovery Counter trap) 0 +Q (collect interruption state) 1 (0 in code directly preceding an rfi) +P (Protection Identifiers) 1* +D (Data address translation) 1, 0 while executing real-mode code +I (external interrupt mask) used by cli()/sti() macros + + "Invisible" Registers + +PSW default W value 0 +PSW default E value 0 +Shadow Registers used by interruption handler code +TOC enable bit 1 + +========================================================================= +Info from John Marvin: + +From: "John Marvin" +To: randolf@tausq.org +Subject: Re: parisc asm questions + +[...] + +For the general registers: + +r1,r2,r19-r26,r28,r29 & r31 can be used without saving them first. And of +course, you need to save them if you care about them, before calling +another procedure. Some of the above registers do have special meanings +that you should be aware of: + + r1: The addil instruction is hardwired to place its result in r1, + so if you use that instruction be aware of that. + + r2: This is the return pointer. In general you don't want to + use this, since you need the pointer to get back to your + caller. However, it is grouped with this set of registers + since the caller can't rely on the value being the same + when you return, i.e. you can copy r2 to another register + and return through that register after trashing r2, and + that should not cause a problem for the calling routine. + + r19-r22: these are generally regarded as temporary registers. + Note that in 64 bit they are arg7-arg4. + + r23-r26: these are arg3-arg0, i.e. you can use them if you + don't care about the values that were passed in anymore. + + r28,r29: are ret0 and ret1. They are what you pass return values + in. r28 is the primary return. I'm not sure I remember + under what circumstances stuff is returned in r29 (millicode + perhaps). + + r31: the ble instruction puts the return pointer in here. + + +r3-r18,r27,r30 need to be saved and restored. r3-r18 are just + general purpose registers. r27 is the data pointer, and is + used to make references to global variables easier. r30 is + the stack pointer. + +John + + diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/sound/CMI8330 linux/Documentation/sound/CMI8330 --- v2.4.0-test11/linux/Documentation/sound/CMI8330 Mon Mar 27 11:02:54 2000 +++ linux/Documentation/sound/CMI8330 Sun Dec 3 17:48:18 2000 @@ -57,7 +57,7 @@ ------------------------------------------ Stefan Laudat -[Note: The CMI 8338 is unrelated and right now unsupported] +[Note: The CMI 8338 is unrelated and is supported by cmpci.o] In order to use CMI8330 under Linux you just have to use a proper isapnp.conf, a good isapnp and a little bit of patience. I use isapnp 1.17, but diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/usb/URB.txt linux/Documentation/usb/URB.txt --- v2.4.0-test11/linux/Documentation/usb/URB.txt Sun Oct 8 10:50:04 2000 +++ linux/Documentation/usb/URB.txt Tue Dec 5 23:15:11 2000 @@ -1,3 +1,5 @@ +Revised: 2000-Dec-05. + 1. Specification of the API 1.1. Basic concept or 'What is an URB?' @@ -8,16 +10,16 @@ - An URB consists of all relevant information to execute any USB transaction and deliver the data and status back. -- Execution of an URB is an inherently asynchronous operation, i.e. the -submit_urb(urb) call returns immediately after it has successfully queued +- Execution of an URB is inherently an asynchronous operation, i.e. the +usb_submit_urb(urb) call returns immediately after it has successfully queued the requested action. - Ongoing transfers for one URB (e.g. ISO) can simply be canceled with -unlink_urb(urb) at any time. +usb_unlink_urb(urb) at any time. - Each URB has a completion handler, which is called after the action has been successfully completed or canceled (INT transfers behave a bit -different, see below). The URB also contains a context-pointer for free +differently, see below). The URB also contains a context-pointer for free usage and information passing to the completion handler. - URBs can be linked. After completing one URB, the next one can be @@ -31,6 +33,8 @@ typedef struct urb { + spinlock_t lock; // lock for the URB + // ignore, for host controller/URB machine internal use void *hcpriv; // private data for host controller struct list_head urb_list; // list pointer to all active urbs @@ -39,12 +43,12 @@ struct urb* next; // pointer to next URB struct usb_device *dev; // pointer to associated USB device -// pipe is assembled by the various well known pipe-macros in usb.h +// pipe is assembled by the various well-known pipe macros in usb.h unsigned int pipe; // pipe information // status after each completion int status; // returned status - unsigned int transfer_flags; // ASAP, SP_OK, etc. + unsigned int transfer_flags; // ASAP, DISABLE_SPD, etc. // for data stage (CTRL), BULK, INT and ISO void *transfer_buffer; // associated data buffer @@ -55,7 +59,7 @@ // setup stage for CTRL (always 8 bytes!) unsigned char* setup_packet; // setup packet (control only) - + // with ASAP, start_frame is set to the determined frame int start_frame; // start frame (iso/irq) int number_of_packets; // # of packets (iso/int) @@ -66,7 +70,7 @@ usb_complete_t complete; // pointer to completion routine // // specification of the requested data offsets and length for ISO - iso_packet_descriptor_t iso_frame_desc[0]; + iso_packet_descriptor_t iso_frame_desc[0]; } urb_t, *purb_t; @@ -74,7 +78,7 @@ URBs are allocated with the following call - purb_t alloc_urb(int isoframes) + purb_t usb_alloc_urb(int isoframes) Return value is a pointer to the allocated URB, 0 if allocation failed. The parameter isoframes specifies the number of isochronous transfer frames @@ -82,7 +86,7 @@ To free an URB, use - void free_urb(purb_t purb) + void usb_free_urb(purb_t purb) This call also may free internal (host controller specific) memory in the future. @@ -91,12 +95,13 @@ 1.4. What has to be filled in? Depending on the type of transaction, there are some macros -(FILL_CONTROL_URB, FILL_BULK_URB, and FILL_INT_URB, defined in uhci.h) +(FILL_CONTROL_URB, FILL_CONTROL_URB_TO, FILL_BULK_URB, +FILL_BULK_URB_TO, and FILL_INT_URB, defined in usb.h) that simplify the URB creation. In general, all macros need the usb -device pointer, the pipe (usual format), the transfer buffer, the -desired transfer length, the completion handler, and its context. -Take a look at the uhci_control_msg-function that convert the old API -into an URB. +device pointer, the pipe (usual format from usb.h), the transfer buffer, +the desired transfer length, the completion handler, and its context. +Take a look at the usb_control_msg function that converts the old API +into the URB API. Flags: For ISO there are two startup behaviors: Specified start_frame or ASAP. @@ -114,7 +119,7 @@ Just call - int submit_urb(purb_t purb) + int usb_submit_urb(purb_t purb) It immediately returns, either with status 0 (request queued) or some error code, usually caused by the following: @@ -128,7 +133,7 @@ - Invalid INT interval (-EINVAL) - More than one packet for INT (-EINVAL) -After submission, urb->status is USB_ST_URB_PENDING. +After submission, urb->status is USB_ST_URB_PENDING (-EINPROGRESS). For isochronous endpoints, subsequent submitting of URBs to the same endpoint with the ASAP flag result in a seamless ISO streaming. Exception: The @@ -142,18 +147,18 @@ For an URB which you've submitted, but which hasn't been returned to your driver by the host controller, call - int unlink_urb(purb_t purb) + int usb_unlink_urb(purb_t purb) It removes the urb from the internal list and frees all allocated HW descriptors. The status is changed to USB_ST_URB_KILLED. After -unlink_urb() returns, you can safely free the URB with free_urb(urb) +usb_unlink_urb() returns, you can safely free the URB with usb_free_urb(urb) and all other possibly associated data (urb->context etc.) There is also an asynchronous unlink mode. To use this, set the the USB_ASYNC_UNLINK flag in urb->transfer flags before calling usb_unlink_urb(). When using async unlinking, the URB will not -normally be unlinked when unlink_urb() returns. Instead, wait for -the completion handler to be called. +normally be unlinked when usb_unlink_urb() returns. Instead, wait +for the completion handler to be called. 1.7. What about the completion handler? @@ -187,13 +192,13 @@ 1.8. How to do isochronous (ISO) transfers? For ISO transfers you have to append the iso_packet_descriptor_t structure -to the URB for each frame you want to schedule. When using alloc_urb(n) -(recommended), the isoframe-parameter n can be used to allocate the -structures for n frames. +to the URB for each frame you want to schedule. When using usb_alloc_urb(n) +(recommended), the iso_packets parameter can be used to allocate the +structures for iso_packets frames. For each entry you have to specify the data offset for this frame (base is transfer_buffer), and the length you want to write/expect to read. -After completion, actual_length contains the actual transfered length and +After completion, actual_length contains the actual transferred length and status contains the resulting USB-status for the ISO transfer for this frame. It is allowed to specify a varying length from frame to frame (e.g. for audio synchronisation/adaptive transfer rates). You can also use the length @@ -217,7 +222,7 @@ calling the completion handler, that URB is recycled by the host controller driver (HCD). With the submission of one URB, the interrupt is scheduled until it is -canceled by unlink_urb. - -The submit_urb()-call modifies urb->interval to the rounded value. +canceled by usb_unlink_urb. +The usb_submit_urb() call modifies urb->interval to the implemented interval +value that is less than or equal to the requested interval value. diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/usb/error-codes.txt linux/Documentation/usb/error-codes.txt --- v2.4.0-test11/linux/Documentation/usb/error-codes.txt Sun Oct 8 10:50:04 2000 +++ linux/Documentation/usb/error-codes.txt Thu Dec 7 16:13:38 2000 @@ -1,12 +1,12 @@ -$Id: README.error-codes,v 1.1 1999/12/14 14:03:02 fliegl Exp $ +Revised: 2000-Dec-05. This is the documentation of (hopefully) all possible error codes (and -their interpretation) that can be returned from the hostcontroller driver +their interpretation) that can be returned from the host controller drivers and from usbcore. NOTE: -The USB_ST_* codes are deferred and are only listed for compatibility, new -software should use only -E* instead! +The USB_ST_* codes are deprecated and are only listed for compatibility; +new software should use only -E* instead! @@ -25,12 +25,16 @@ -ENODEV specified USB-device or bus doesn't exist --ENXIO specified endpoint doesn't exist on the device +USB_ST_REQUEST_ERROR +-ENXIO a control or interrupt URB is already queued to this endpoint; or + a bulk URB is already queued to this endpoint and + USB_QUEUE_BULK wasn't used (UHCI HCDs only) USB_ST_URB_INVALID_ERROR -EINVAL a) Invalid transfer type specified (or not supported) b) Invalid interrupt interval (0<=n<256) c) more than one interrupt packet requested + d) ISO: number_of_packets is < 0 -EAGAIN a) specified ISO start frame too early b) (using ISO-ASAP) too much scheduled for the future @@ -38,6 +42,7 @@ -EFBIG too much ISO frames requested (currently uhci>900) +USB_ST_STALL -EPIPE specified pipe-handle is already stalled -EMSGSIZE endpoint message size is zero, do interface/alternate setting @@ -59,7 +64,7 @@ 0 Transfer completed successfully USB_ST_URB_KILLED --ENOENT URB was canceled by unlink_urb +-ENOENT URB was canceled by usb_unlink_urb USB_ST_URB_PENDING -EINPROGRESS URB still pending, no results yet @@ -73,12 +78,28 @@ USB_ST_CRC -EILSEQ CRC mismatch +USB_ST_STALL -EPIPE a) babble detect b) endpoint stalled -USB_ST_BUFFERUNDERRUN --ENOST buffer error +USB_ST_BUFFEROVERRUN +-ECOMM During an IN transfer, the host controller + received data from an endpoint faster than it + could be written to system memory +USB_ST_BUFFERUNDERRUN +-ENOSR During an OUT transfer, the host controller + could not retrieve data from system memory fast + enough to keep up with the USB data rate + +USB_ST_DATAOVERRUN +-EOVERFLOW The amount of data returned by the endpoint was + greater than either the max packet size of the + endpoint or the remaining buffer size + +USB_ST_DATAUNDERRUN +-EREMOTEIO The endpoint returned less than max packet size + and that amount did not fill the specified buffer USB_ST_NORESPONSE USB_ST_TIMEOUT -ETIMEDOUT transfer timed out, NAK @@ -104,14 +125,7 @@ ************************************************************************** usb_register(): -USB_ST_NOTSUPPORTED -EINVAL error during registering new driver -usb_terminate_bulk(): -USB_ST_REMOVED --ENODEV urb already removed - usb_get_*/usb_set_*(): All USB errors (submit/status) can occur - - diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/usb/usb-help.txt linux/Documentation/usb/usb-help.txt --- v2.4.0-test11/linux/Documentation/usb/usb-help.txt Wed Jul 12 20:07:39 2000 +++ linux/Documentation/usb/usb-help.txt Tue Dec 5 23:15:12 2000 @@ -7,6 +7,7 @@ Linux-USB project: http://www.linux-usb.org mirrors at http://www.suse.cz/development/linux-usb/ and http://usb.in.tum.de/linux-usb/ + and http://it.linux-usb.org Linux USB Guide: http://linux-usb.sourceforge.net Linux-USB device overview (working devices and drivers): http://www.qbik.ch/usb/devices/ diff -u --recursive --new-file v2.4.0-test11/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- v2.4.0-test11/linux/Documentation/usb/usb-serial.txt Sun Nov 19 18:44:01 2000 +++ linux/Documentation/usb/usb-serial.txt Thu Dec 7 16:13:38 2000 @@ -139,6 +139,9 @@ (plus a parallel port) and 4 port USB serial converters. The driver does NOT yet support the Digi AccelePort USB 8. + This driver works under SMP with the usb-uhci driver. It does not + work under SMP with the uhci driver. + The driver is generally working, though we still have a few more ioctls to implement and final testing and debugging to do. The paralled port on the USB 2 is supported as a serial to parallel converter; in other @@ -180,6 +183,33 @@ -- Add error reporting back to application for UART error conditions. -- Add support for flush ioctls. -- Add everything else that is missing :) + + +Empeg empeg-car Mark I/II Driver (empeg.c) + + This is an experimental driver to provide connectivity support for the + client synchronization tools for an Empeg empeg-car mp3 player. + + Tips: + + * Don't forget to create the device nodes for ttyUSB{0,1,2,...} + * modprobe empeg (modprobe is your friend) + * emptool --usb /dev/ttyUSB0 (or whatever you named your device node) + + The driver is still pretty new, so some testing 'in the wild' would be + helpful. :) + + +MCT USB Single Port Serial Adapter U232 + + This driver is for the MCT USB-RS232 Converter (25 pin, Model No. + U232-P25) from Magic Control Technology Corp. (there is also a 9 pin + Model No. U232-P9). More information about this device can be found + at the manufacture's web-site: http://www.mct.com.tw. + + The driver is generally working, though it still needs some more + testing. It is derived from the Belkin USB Serial Adapter F5U103 + driver and its TODO list is valid for this driver as well. Generic Serial driver diff -u --recursive --new-file v2.4.0-test11/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.0-test11/linux/MAINTAINERS Sun Nov 19 18:44:02 2000 +++ linux/MAINTAINERS Mon Dec 11 13:42:08 2000 @@ -216,6 +216,13 @@ L: linux-fbdev@vuser.vu.union.edu S: Odd Fixes +CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER +P: Cirrus Logic Corporation (kernel 2.2 driver) +M: Cirrus Logic Corporation, Thomas Woller +P: Nils Faerber (port to kernel 2.4) +M: Nils Faerber +S: Maintained + COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA P: Amy Vanzant-Hodge M: Amy Vanzant-Hodge (fibrechannel@compaq.com) @@ -393,7 +400,7 @@ EATA ISA/EISA/PCI SCSI DRIVER P: Dario Ballabio -M: dario@milano.europe.dg.com +M: ballabio_dario@emc.com L: linux-scsi@vger.kernel.org S: Maintained @@ -633,7 +640,7 @@ W: http://sourceforge.net/projects/gkernel/ S: Maintained -INTEL P6 MICROCODE UPDATE SUPPORT +INTEL IA32 MICROCODE UPDATE SUPPORT P: Tigran Aivazian M: tigran@veritas.com S: Maintained @@ -651,9 +658,9 @@ IRDA SUBSYSTEM P: Dag Brattli -M: Dag Brattli +M: Dag Brattli L: linux-irda@pasta.cs.uit.no -W: http://www.cs.uit.no/linux-irda/ +W: http://irda.sourceforge.net/ S: Maintained ISAPNP @@ -1223,7 +1230,7 @@ U14-34F SCSI DRIVER P: Dario Ballabio -M: dario@milano.europe.dg.com +M: ballabio_dario@emc.com L: linux-scsi@vger.kernel.org S: Maintained @@ -1325,7 +1332,7 @@ M: alborchers@steinerpoint.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net -S: Supported +S: Maintained USB SERIAL KEYSPAN DRIVER P: Hugh Blemings @@ -1347,6 +1354,13 @@ P: William Greathouse M: wgreathouse@smva.com M: wgreathouse@myfavoritei.com +L: linux-usb-users@lists.sourceforge.net +L: linux-usb-devel@lists.sourceforge.net +S: Maintained + +USB SERIAL EMPEG EMPEG-CAR MARK I/II DRIVER +P: Gary Brubaker +M: xavyer@ix.netcom.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net S: Maintained diff -u --recursive --new-file v2.4.0-test11/linux/Makefile linux/Makefile --- v2.4.0-test11/linux/Makefile Sun Nov 19 18:44:02 2000 +++ linux/Makefile Wed Nov 29 10:11:38 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test11 +EXTRAVERSION = -test12 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -206,7 +206,6 @@ drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h \ drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h \ drivers/net/hamradio/soundmodem/gentbl \ - drivers/char/hfmodem/gentbl drivers/char/hfmodem/tables.h \ drivers/sound/*_boot.h drivers/sound/.*.boot \ drivers/sound/msndinit.c \ drivers/sound/msndperm.c \ diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/Makefile linux/arch/alpha/Makefile --- v2.4.0-test11/linux/arch/alpha/Makefile Sun Oct 8 10:50:04 2000 +++ linux/arch/alpha/Makefile Sun Dec 3 17:45:20 2000 @@ -36,6 +36,10 @@ CFLAGS := $(CFLAGS) -mcpu=ev5 mcpu_done := y endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_SX164)$(have_mcpu_pca56),nyy) + CFLAGS := $(CFLAGS) -mcpu=pca56 + mcpu_done := y + endif ifeq ($(mcpu_done)$(CONFIG_ALPHA_PYXIS),ny) CFLAGS := $(CFLAGS) -mcpu=ev56 mcpu_done := y @@ -48,12 +52,12 @@ endif mcpu_done := y endif - ifeq ($(mcpu_done)$(CONFIG_ALPHA_NAUTILUS)$(have_mcpu_ev67),nyy) - CFLAGS := $(CFLAGS) -mcpu=ev67 - mcpu_done := y - endif ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV4),ny) CFLAGS := $(CFLAGS) -mcpu=ev4 + mcpu_done := y + endif + ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV67)$(have_mcpu_ev67),nyy) + CFLAGS := $(CFLAGS) -mcpu=ev67 mcpu_done := y endif ifeq ($(mcpu_done)$(CONFIG_ALPHA_EV6),ny) diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.4.0-test11/linux/arch/alpha/config.in Sun Nov 19 18:44:02 2000 +++ linux/arch/alpha/config.in Sun Dec 3 17:45:20 2000 @@ -56,7 +56,7 @@ Wildfire CONFIG_ALPHA_WILDFIRE" Generic # clear all implied options (don't want default values for those): -unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 +unset CONFIG_ALPHA_EV4 CONFIG_ALPHA_EV5 CONFIG_ALPHA_EV6 CONFIG_ALPHA_EV67 unset CONFIG_ALPHA_EISA unset CONFIG_ALPHA_LCA CONFIG_ALPHA_APECS CONFIG_ALPHA_CIA unset CONFIG_ALPHA_T2 CONFIG_ALPHA_PYXIS CONFIG_ALPHA_POLARIS @@ -138,16 +138,12 @@ then define_bool CONFIG_ALPHA_EV6 y define_bool CONFIG_ALPHA_TSUNAMI y + bool 'EV67 (or later) CPU (speed > 600MHz)?' CONFIG_ALPHA_EV67 fi -if [ "$CONFIG_ALPHA_WILDFIRE" = "y" ] +if [ "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ] then - define_bool CONFIG_PCI y - define_bool CONFIG_ALPHA_EV6 y -fi -if [ "$CONFIG_ALPHA_TITAN" = "y" ] -then - define_bool CONFIG_PCI y define_bool CONFIG_ALPHA_EV6 y + define_bool CONFIG_ALPHA_EV67 y fi if [ "$CONFIG_ALPHA_RAWHIDE" = "y" ] then @@ -165,8 +161,9 @@ fi if [ "$CONFIG_ALPHA_NAUTILUS" = "y" ] then - define_bool CONFIG_ALPHA_EV6 y define_bool CONFIG_ALPHA_IRONGATE y + define_bool CONFIG_ALPHA_EV6 y + define_bool CONFIG_ALPHA_EV67 y fi if [ "$CONFIG_ALPHA_JENSEN" = "y" -o "$CONFIG_ALPHA_MIKASA" = "y" \ diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/kernel/core_cia.c linux/arch/alpha/kernel/core_cia.c --- v2.4.0-test11/linux/arch/alpha/kernel/core_cia.c Tue Oct 31 12:42:25 2000 +++ linux/arch/alpha/kernel/core_cia.c Mon Dec 11 13:46:26 2000 @@ -119,6 +119,7 @@ stat0 = *(vip)CIA_IOC_CIA_ERR; *(vip)CIA_IOC_CIA_ERR = stat0; mb(); + *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */ /* If Type1 access, must set CIA CFG. */ if (type1) { @@ -128,6 +129,7 @@ *(vip)CIA_IOC_CFG; } + mb(); draina(); mcheck_expected(0) = 1; mcheck_taken(0) = 0; @@ -171,6 +173,7 @@ stat0 = *(vip)CIA_IOC_CIA_ERR; *(vip)CIA_IOC_CIA_ERR = stat0; mb(); + *(vip)CIA_IOC_CIA_ERR; /* re-read to force write */ /* If Type1 access, must set CIA CFG. */ if (type1) { @@ -180,6 +183,7 @@ *(vip)CIA_IOC_CFG; } + mb(); draina(); mcheck_expected(0) = 1; mcheck_taken(0) = 0; @@ -188,7 +192,7 @@ /* Access configuration space. */ *(vip)addr = value; mb(); - mb(); /* magic */ + *(vip)addr; /* read back to force the write */ mcheck_expected(0) = 0; mb(); @@ -606,7 +610,8 @@ *(vip)CIA_IOC_ERR_MASK = temp; /* Clear all currently pending errors. */ - *(vip)CIA_IOC_CIA_ERR = 0; + temp = *(vip)CIA_IOC_CIA_ERR; + *(vip)CIA_IOC_CIA_ERR = temp; /* Turn on mchecks. */ temp = *(vip)CIA_IOC_CIA_CTRL; @@ -695,11 +700,11 @@ *(vip)CIA_IOC_PCI_W1_BASE = 0x40000000 | 1; *(vip)CIA_IOC_PCI_W1_MASK = (0x40000000 - 1) & 0xfff00000; - *(vip)CIA_IOC_PCI_T1_BASE = 0; + *(vip)CIA_IOC_PCI_T1_BASE = 0 >> 2; *(vip)CIA_IOC_PCI_W2_BASE = 0x80000000 | 1; *(vip)CIA_IOC_PCI_W2_MASK = (0x40000000 - 1) & 0xfff00000; - *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000; + *(vip)CIA_IOC_PCI_T2_BASE = 0x40000000 >> 2; *(vip)CIA_IOC_PCI_W3_BASE = 0; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c --- v2.4.0-test11/linux/arch/alpha/kernel/pci.c Mon Aug 7 14:31:40 2000 +++ linux/arch/alpha/kernel/pci.c Mon Dec 11 13:46:26 2000 @@ -8,6 +8,11 @@ /* 2.3.x PCI/resources, 1999 Andrea Arcangeli */ +/* + * Nov 2000, Ivan Kokshaysky + * PCI-PCI bridges cleanup + */ + #include #include #include @@ -51,13 +56,13 @@ static void __init quirk_eisa_bridge(struct pci_dev *dev) { - dev->class = PCI_CLASS_BRIDGE_EISA; + dev->class = PCI_CLASS_BRIDGE_EISA << 8; } static void __init quirk_isa_bridge(struct pci_dev *dev) { - dev->class = PCI_CLASS_BRIDGE_ISA; + dev->class = PCI_CLASS_BRIDGE_ISA << 8; } static void __init @@ -71,6 +76,24 @@ dev->resource[3].end = dev->resource[3].start + 7; } +/* + * Notorious Cy82C693 chip. One of its numerous bugs: although + * Cypress IDE controller doesn't support native mode, it has + * programmable addresses of IDE command/control registers. + * This violates PCI specifications, confuses IDE subsystem + * and causes resource conflict between primary HD_CMD register + * and floppy controller. Ugh. + * Fix that. + */ +static void __init +quirk_cypress_ide_ports(struct pci_dev *dev) +{ + if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE) + return; + dev->resource[0].flags = 0; + dev->resource[1].flags = 0; +} + static void __init quirk_vga_enable_rom(struct pci_dev *dev) { @@ -78,7 +101,6 @@ But if its a Cirrus 543x/544x DISABLE it, since enabling ROM disables the memory... */ if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA && - /* But if its a Cirrus 543x/544x DISABLE it */ (dev->vendor != PCI_VENDOR_ID_CIRRUS || (dev->device < 0x00a0) || (dev->device > 0x00ac))) { @@ -98,6 +120,8 @@ quirk_isa_bridge }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229, quirk_ali_ide_ports }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693, + quirk_cypress_ide_ports }, { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom }, { 0 } }; @@ -122,18 +146,12 @@ start = PCIBIOS_MIN_IO + hose->io_space->start; /* - * Aligning to 0x800 rather than the minimum base of - * 0x400 is an attempt to avoid having devices in - * any 0x?C?? range, which is where the de4x5 driver - * probes for EISA cards. - * - * Adaptecs, especially, resent such intrusions. - * - * The de4x5 driver has the eisa probe conditionalized - * out for Alpha, so lower the minimum base back to 0x400. + * Put everything into 0x00-0xff region modulo 0x400 */ - alignto = MAX(0x400, size); - start = ALIGN(start, alignto); + if (start & 0x300) { + start = (start + 0x3ff) & ~0x3ff; + res->start = start; + } } else if (res->flags & IORESOURCE_MEM) { /* Make sure we start at our min on all hoses */ @@ -181,44 +199,6 @@ #undef MB #undef GB -/* - * Pre-layout host-independant device initialization. - */ - -static void __init -pcibios_assign_special(struct pci_dev * dev) -{ - int i; - - /* The first three resources of an IDE controler are often magic, - so leave them unchanged. This is true, for instance, of the - Contaq 82C693 as seen on SX164 and DP264. */ - - if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) { - /* Resource 1 of IDE controller is the address of HD_CMD - register which actually occupies a single byte (0x3f6 - for ide0) in reported 0x3f4-3f7 range. We have to fix - that to avoid resource conflict with AT-style floppy - controller. */ - dev->resource[1].start += 2; - dev->resource[1].end = dev->resource[1].start; - for (i = 0; i < PCI_NUM_RESOURCES; i++) - if (dev->resource[i].flags && dev->resource[i].start) - pci_claim_resource(dev, i); - } - /* - * We don't have code that will init the CYPRESS bridge correctly - * so we do the next best thing, and depend on the previous - * console code to do the right thing, and ignore it here... :-\ - */ - else if (dev->vendor == PCI_VENDOR_ID_CONTAQ && - dev->device == PCI_DEVICE_ID_CONTAQ_82C693) - for (i = 0; i < PCI_NUM_RESOURCES; i++) - if (dev->resource[i].flags && dev->resource[i].start) - pci_claim_resource(dev, i); -} - - void __init pcibios_init(void) { @@ -257,7 +237,6 @@ pcibios_fixup_resource(&dev->resource[i], hose->mem_space); } - pcibios_assign_special(dev); } void __init @@ -265,17 +244,33 @@ { /* Propogate hose info into the subordinate devices. */ - struct pci_controler *hose = (struct pci_controler *) bus->sysdata; + struct pci_controler *hose = bus->sysdata; struct list_head *ln; + struct pci_dev *dev = bus->self; - /* ???? */ - bus->resource[0] = hose->io_space; - bus->resource[1] = hose->mem_space; - - /* If this is a bridge, get the current bases */ - if (bus->self) { - pci_read_bridge_bases(bus); - pcibios_fixup_device_resources(bus->self, bus->parent); + if (!dev) { + /* Root bus */ + bus->resource[0] = hose->io_space; + bus->resource[1] = hose->mem_space; + } else { + /* This is a bridge. Do not care how it's initialized, + just link its resources to the bus ones */ + int i; + + for(i=0; i<3; i++) { + bus->resource[i] = + &dev->resource[PCI_BRIDGE_RESOURCES+i]; + bus->resource[i]->name = bus->name; + } + bus->resource[0]->flags |= pci_bridge_check_io(dev); + bus->resource[1]->flags |= IORESOURCE_MEM; + /* For now, propogate hose limits to the bus; + we'll adjust them later. */ + bus->resource[0]->end = hose->io_space->end; + bus->resource[1]->end = hose->mem_space->end; + /* Turn off downstream PF memory address range by default */ + bus->resource[2]->start = 1024*1024; + bus->resource[2]->end = bus->resource[2]->start - 1; } for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) { @@ -285,7 +280,7 @@ } } -void __init +void pcibios_update_resource(struct pci_dev *dev, struct resource *root, struct resource *res, int resource) { @@ -385,99 +380,6 @@ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); } -#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) - -static void __init -pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer) -{ - struct pbus_set_ranges_data inner; - struct pci_dev *dev; - struct pci_dev *bridge = bus->self; - struct pci_controler *hose = bus->sysdata; - struct list_head *ln; - - if (!bridge) - return; /* host bridge, nothing to do */ - - /* set reasonable default locations for pcibios_align_resource */ - inner.io_start = hose->io_space->start + PCIBIOS_MIN_IO; - inner.mem_start = hose->mem_space->start + PCIBIOS_MIN_MEM; - inner.io_end = inner.io_start; - inner.mem_end = inner.mem_start; - - /* Collect information about how our direct children are layed out. */ - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - int i; - dev = pci_dev_b(ln); - - /* Skip bridges for now */ - if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) - continue; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource res; - unsigned long size; - - memcpy(&res, &dev->resource[i], sizeof(res)); - size = res.end - res.start + 1; - - if (res.flags & IORESOURCE_IO) { - res.start = inner.io_end; - pcibios_align_resource(dev, &res, size); - inner.io_end = res.start + size; - } else if (res.flags & IORESOURCE_MEM) { - res.start = inner.mem_end; - pcibios_align_resource(dev, &res, size); - inner.mem_end = res.start + size; - } - } - } - - /* And for all of the subordinate busses. */ - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pcibios_size_bridge(pci_bus_b(ln), &inner); - - /* turn the ending locations into sizes (subtract start) */ - inner.io_end -= inner.io_start; - inner.mem_end -= inner.mem_start; - - /* Align the sizes up by bridge rules */ - inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1; - inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1; - - /* Adjust the bridge's allocation requirements */ - bridge->resource[0].end = bridge->resource[0].start + inner.io_end; - bridge->resource[1].end = bridge->resource[1].start + inner.mem_end; - - bridge->resource[PCI_BRIDGE_RESOURCES].end = - bridge->resource[PCI_BRIDGE_RESOURCES].start + inner.io_end; - bridge->resource[PCI_BRIDGE_RESOURCES+1].end = - bridge->resource[PCI_BRIDGE_RESOURCES+1].start + inner.mem_end; - - /* adjust parent's resource requirements */ - if (outer) { - outer->io_end = ROUND_UP(outer->io_end, 4*1024); - outer->io_end += inner.io_end; - - outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024); - outer->mem_end += inner.mem_end; - } -} - -#undef ROUND_UP - -static void __init -pcibios_size_bridges(void) -{ - struct list_head *ln1, *ln2; - - for(ln1=pci_root_buses.next; ln1 != &pci_root_buses; ln1=ln1->next) - for(ln2 = pci_bus_b(ln1)->children.next; - ln2 != &pci_bus_b(ln1)->children; - ln2 = ln2->next) - pcibios_size_bridge(pci_bus_b(ln2), NULL); -} - void __init common_init_pci(void) { @@ -495,10 +397,8 @@ next_busno += 1; } - pcibios_size_bridges(); pci_assign_unassigned_resources(); pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq); - pci_set_bus_ranges(); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/kernel/pci_iommu.c linux/arch/alpha/kernel/pci_iommu.c --- v2.4.0-test11/linux/arch/alpha/kernel/pci_iommu.c Sun Oct 8 10:50:04 2000 +++ linux/arch/alpha/kernel/pci_iommu.c Mon Dec 11 13:46:26 2000 @@ -613,10 +613,10 @@ /* Check that we have a scatter-gather arena that fits. */ hose = pdev ? pdev->sysdata : pci_isa_hose; arena = hose->sg_isa; - if (arena && arena->dma_base + arena->size <= mask) + if (arena && arena->dma_base + arena->size - 1 <= mask) return 1; arena = hose->sg_pci; - if (arena && arena->dma_base + arena->size <= mask) + if (arena && arena->dma_base + arena->size - 1 <= mask) return 1; return 0; diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c --- v2.4.0-test11/linux/arch/alpha/kernel/sys_ruffian.c Tue Oct 31 12:42:25 2000 +++ linux/arch/alpha/kernel/sys_ruffian.c Mon Nov 27 17:50:12 2000 @@ -56,9 +56,9 @@ init_i8259a_irqs(); - /* Not interested in the bogus interrupts (0,3,4,6), + /* Not interested in the bogus interrupts (0,3,6), NMI (1), HALT (2), flash (5), or 21142 (8). */ - init_pyxis_irqs(0x17f0000); + init_pyxis_irqs(0x16f0000); common_init_isa_dma(); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile --- v2.4.0-test11/linux/arch/alpha/lib/Makefile Sun Nov 19 18:44:02 2000 +++ linux/arch/alpha/lib/Makefile Mon Dec 11 13:46:26 2000 @@ -3,32 +3,63 @@ # .S.s: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $< + $(CPP) -D__ASSEMBLY__ $(CFLAGS) -o $*.s $< .S.o: - $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $< + $(CC) -D__ASSEMBLY__ $(CFLAGS) -c -o $*.o $< -OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \ - checksum.o csum_partial_copy.o strlen.o \ - strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \ - strchr.o strrchr.o memchr.o \ - copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \ - csum_ipv6_magic.o strcasecmp.o fpreg.o \ +# Many of these routines have implementations tuned for ev6. +# Choose them iff we're targeting ev6 specifically. +ev6 := +ifeq ($(CONFIG_ALPHA_EV6),y) + ev6 := ev6- +endif + +# Several make use of the cttz instruction introduced in ev67. +ev67 := +ifeq ($(CONFIG_ALPHA_EV67),y) + ev67 := ev67- +endif + +OBJS = __divqu.o __remqu.o __divlu.o __remlu.o \ + $(ev6)memset.o \ + $(ev6)memcpy.o \ + memmove.o \ + io.o \ + checksum.o \ + csum_partial_copy.o \ + $(ev67)strlen.o \ + $(ev67)strcat.o \ + strcpy.o \ + $(ev67)strncat.o \ + strncpy.o \ + $(ev6)stxcpy.o \ + $(ev6)stxncpy.o \ + $(ev67)strchr.o \ + strrchr.o \ + $(ev6)memchr.o \ + $(ev6)copy_user.o \ + $(ev6)clear_user.o \ + $(ev6)strncpy_from_user.o \ + $(ev67)strlen_user.o \ + $(ev6)csum_ipv6_magic.o \ + strcasecmp.o \ + fpreg.o \ callback_srm.o srm_puts.o srm_printk.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) -__divqu.o: divide.S - $(CC) $(AFLAGS) -DDIV -c -o __divqu.o divide.S +__divqu.o: $(ev6)divide.S + $(CC) $(AFLAGS) -DDIV -c -o __divqu.o $(ev6)divide.S -__remqu.o: divide.S - $(CC) $(AFLAGS) -DREM -c -o __remqu.o divide.S +__remqu.o: $(ev6)divide.S + $(CC) $(AFLAGS) -DREM -c -o __remqu.o $(ev6)divide.S -__divlu.o: divide.S - $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o divide.S +__divlu.o: $(ev6)divide.S + $(CC) $(AFLAGS) -DDIV -DINTSIZE -c -o __divlu.o $(ev6)divide.S -__remlu.o: divide.S - $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o divide.S +__remlu.o: $(ev6)divide.S + $(CC) $(AFLAGS) -DREM -DINTSIZE -c -o __remlu.o $(ev6)divide.S dep: diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/checksum.c linux/arch/alpha/lib/checksum.c --- v2.4.0-test11/linux/arch/alpha/lib/checksum.c Tue Apr 28 22:28:10 1998 +++ linux/arch/alpha/lib/checksum.c Mon Dec 11 13:46:26 2000 @@ -3,6 +3,10 @@ * * This file contains network checksum routines that are better done * in an architecture-specific manner due to speed.. + * Comments in other versions indicate that the algorithms are from RFC1071 + * + * accellerated versions (and 21264 assembly versions ) contributed by + * Rick Gorton */ #include @@ -11,15 +15,25 @@ static inline unsigned short from64to16(unsigned long x) { - /* add up 32-bit words for 33 bits */ - x = (x & 0xffffffff) + (x >> 32); - /* add up 16-bit and 17-bit words for 17+c bits */ - x = (x & 0xffff) + (x >> 16); - /* add up 16-bit and 2-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; + /* Using extract instructions is a bit more efficient + than the original shift/bitmask version. */ + + union { + unsigned long ul; + unsigned int ui[2]; + unsigned short us[4]; + } in_v, tmp_v, out_v; + + in_v.ul = x; + tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1]; + + /* Since the bits of tmp_v.sh[3] are going to always be zero, + we don't have to bother to add that in. */ + out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1] + + (unsigned long) tmp_v.us[2]; + + /* Similarly, out_v.us[2] is always zero for the final add. */ + return out_v.us[0] + out_v.us[1]; } /* diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/csum_partial_copy.c linux/arch/alpha/lib/csum_partial_copy.c --- v2.4.0-test11/linux/arch/alpha/lib/csum_partial_copy.c Wed Jul 26 09:09:32 2000 +++ linux/arch/alpha/lib/csum_partial_copy.c Mon Dec 11 13:46:26 2000 @@ -2,6 +2,8 @@ * csum_partial_copy - do IP checksumming and copy * * (C) Copyright 1996 Linus Torvalds + * accellerated versions (and 21264 assembly versions ) contributed by + * Rick Gorton * * Don't look at this too closely - you'll go mad. The things * we do for performance.. @@ -68,6 +70,31 @@ }) +static inline unsigned short from64to16(unsigned long x) +{ + /* Using extract instructions is a bit more efficient + than the original shift/bitmask version. */ + + union { + unsigned long ul; + unsigned int ui[2]; + unsigned short us[4]; + } in_v, tmp_v, out_v; + + in_v.ul = x; + tmp_v.ul = (unsigned long) in_v.ui[0] + (unsigned long) in_v.ui[1]; + + /* Since the bits of tmp_v.sh[3] are going to always be zero, + we don't have to bother to add that in. */ + out_v.ul = (unsigned long) tmp_v.us[0] + (unsigned long) tmp_v.us[1] + + (unsigned long) tmp_v.us[2]; + + /* Similarly, out_v.us[2] is always zero for the final add. */ + return out_v.us[0] + out_v.us[1]; +} + + + /* * Ok. This isn't fun, but this is the EASY case. */ @@ -335,13 +362,7 @@ soff, doff, len-8, checksum, partial_dest, errp); } - /* 64 -> 33 bits */ - checksum = (checksum & 0xffffffff) + (checksum >> 32); - /* 33 -> < 32 bits */ - checksum = (checksum & 0xffff) + (checksum >> 16); - /* 32 -> 16 bits */ - checksum = (checksum & 0xffff) + (checksum >> 16); - checksum = (checksum & 0xffff) + (checksum >> 16); + checksum = from64to16 (checksum); } return checksum; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-clear_user.S linux/arch/alpha/lib/ev6-clear_user.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-clear_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-clear_user.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,228 @@ +/* + * arch/alpha/lib/ev6-clear_user.S + * 21264 version contributed by Rick Gorton + * + * Zero user space, handling exceptions as we go. + * + * We have to make sure that $0 is always up-to-date and contains the + * right "bytes left to zero" value (and that it is updated only _after_ + * a successful copy). There is also some rather minor exception setup + * stuff. + * + * NOTE! This is not directly C-callable, because the calling semantics + * are different: + * + * Inputs: + * length in $0 + * destination address in $6 + * exception pointer in $7 + * return address in $28 (exceptions expect it there) + * + * Outputs: + * bytes left to copy in $0 + * + * Clobbers: + * $1,$2,$3,$4,$5,$6 + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + * Determining actual stalls (other than slotting) doesn't appear to be easy to do. + * From perusing the source code context where this routine is called, it is + * a fair assumption that significant fractions of entire pages are zeroed, so + * it's going to be worth the effort to hand-unroll a big loop, and use wh64. + * ASSUMPTION: + * The believed purpose of only updating $0 after a store is that a signal + * may come along during the execution of this chunk of code, and we don't + * want to leave a hole (and we also want to avoid repeating lots of work) + */ + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .gprel32 99b; \ + lda $31, $exception-99b($31); \ + .previous + + .set noat + .set noreorder + .align 4 + + .globl __do_clear_user + .ent __do_clear_user + .frame $30, 0, $28 + .prologue 0 + + # Pipeline info : Slotting & Comments +__do_clear_user: + ldgp $29,0($27) # we do exceptions -- we need the gp. + # Macro instruction becomes ldah/lda + # .. .. E E : + and $6, 7, $4 # .. E .. .. : find dest head misalignment + beq $0, $zerolength # U .. .. .. : U L U L + + addq $0, $4, $1 # .. .. .. E : bias counter + and $1, 7, $2 # .. .. E .. : number of misaligned bytes in tail +# Note - we never actually use $2, so this is a moot computation +# and we can rewrite this later... + srl $1, 3, $1 # .. E .. .. : number of quadwords to clear + beq $4, $headalign # U .. .. .. : U L U L + +/* + * Head is not aligned. Write (8 - $4) bytes to head of destination + * This means $6 is known to be misaligned + */ + EX( ldq_u $5, 0($6) ) # .. .. .. L : load dst word to mask back in + beq $1, $onebyte # .. .. U .. : sub-word store? + mskql $5, $6, $5 # .. U .. .. : take care of misaligned head + addq $6, 8, $6 # E .. .. .. : L U U L + + EX( stq_u $5, -8($6) ) # .. .. .. L : + subq $1, 1, $1 # .. .. E .. : + addq $0, $4, $0 # .. E .. .. : bytes left -= 8 - misalignment + subq $0, 8, $0 # E .. .. .. : U L U L + + .align 4 +/* + * (The .align directive ought to be a moot point) + * values upon initial entry to the loop + * $1 is number of quadwords to clear (zero is a valid value) + * $2 is number of trailing bytes (0..7) ($2 never used...) + * $6 is known to be aligned 0mod8 + */ +$headalign: + subq $1, 16, $4 # .. .. .. E : If < 16, we can not use the huge loop + and $6, 0x3f, $2 # .. .. E .. : Forward work for huge loop + subq $2, 0x40, $3 # .. E .. .. : bias counter (huge loop) + blt $4, $trailquad # U .. .. .. : U L U L + +/* + * We know that we're going to do at least 16 quads, which means we are + * going to be able to use the large block clear loop at least once. + * Figure out how many quads we need to clear before we are 0mod64 aligned + * so we can use the wh64 instruction. + */ + + nop # .. .. .. E + nop # .. .. E .. + nop # .. E .. .. + beq $3, $bigalign # U .. .. .. : U L U L : Aligned 0mod64 + +$alignmod64: + EX( stq_u $31, 0($6) ) # .. .. .. L + addq $3, 8, $3 # .. .. E .. + subq $0, 8, $0 # .. E .. .. + nop # E .. .. .. : U L U L + + nop # .. .. .. E + subq $1, 1, $1 # .. .. E .. + addq $6, 8, $6 # .. E .. .. + blt $3, $alignmod64 # U .. .. .. : U L U L + +$bigalign: +/* + * $0 is the number of bytes left + * $1 is the number of quads left + * $6 is aligned 0mod64 + * we know that we'll be taking a minimum of one trip through + * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle + * We are _not_ going to update $0 after every single store. That + * would be silly, because there will be cross-cluster dependencies + * no matter how the code is scheduled. By doing it in slightly + * staggered fashion, we can still do this loop in 5 fetches + * The worse case will be doing two extra quads in some future execution, + * in the event of an interrupted clear. + * Assumes the wh64 needs to be for 2 trips through the loop in the future + * The wh64 is issued on for the starting destination address for trip +2 + * through the loop, and if there are less than two trips left, the target + * address will be for the current trip. + */ + nop # E : + nop # E : + nop # E : + bis $6,$6,$3 # E : U L U L : Initial wh64 address is dest + /* This might actually help for the current trip... */ + +$do_wh64: + wh64 ($3) # .. .. .. L1 : memory subsystem hint + subq $1, 16, $4 # .. .. E .. : Forward calculation - repeat the loop? + EX( stq_u $31, 0($6) ) # .. L .. .. + subq $0, 8, $0 # E .. .. .. : U L U L + + addq $6, 128, $3 # E : Target address of wh64 + EX( stq_u $31, 8($6) ) # L : + EX( stq_u $31, 16($6) ) # L : + subq $0, 16, $0 # E : U L L U + + nop # E : + EX( stq_u $31, 24($6) ) # L : + EX( stq_u $31, 32($6) ) # L : + subq $0, 168, $5 # E : U L L U : two trips through the loop left? + /* 168 = 192 - 24, since we've already completed some stores */ + + subq $0, 16, $0 # E : + EX( stq_u $31, 40($6) ) # L : + EX( stq_u $31, 48($6) ) # L : + cmovlt $5, $6, $3 # E : U L L U : Latency 2, extra mapping cycle + + subq $1, 8, $1 # E : + subq $0, 16, $0 # E : + EX( stq_u $31, 56($6) ) # L : + nop # E : U L U L + + nop # E : + subq $0, 8, $0 # E : + addq $6, 64, $6 # E : + bge $4, $do_wh64 # U : U L U L + +$trailquad: + # zero to 16 quadwords left to store, plus any trailing bytes + # $1 is the number of quadwords left to go. + # + nop # .. .. .. E + nop # .. .. E .. + nop # .. E .. .. + beq $1, $trailbytes # U .. .. .. : U L U L : Only 0..7 bytes to go + +$onequad: + EX( stq_u $31, 0($6) ) # .. .. .. L + subq $1, 1, $1 # .. .. E .. + subq $0, 8, $0 # .. E .. .. + nop # E .. .. .. : U L U L + + nop # .. .. .. E + nop # .. .. E .. + addq $6, 8, $6 # .. E .. .. + bgt $1, $onequad # U .. .. .. : U L U L + + # We have an unknown number of bytes left to go. +$trailbytes: + nop # .. .. .. E + nop # .. .. E .. + nop # .. E .. .. + beq $0, $zerolength # U .. .. .. : U L U L + + # $0 contains the number of bytes left to copy (0..31) + # so we will use $0 as the loop counter + # We know for a fact that $0 > 0 zero due to previous context +$onebyte: + EX( stb $31, 0($6) ) # .. .. .. L + subq $0, 1, $0 # .. .. E .. : + addq $6, 1, $6 # .. E .. .. : + bgt $0, $onebyte # U .. .. .. : U L U L + +$zerolength: +$exception: # Destination for exception recovery(?) + nop # .. .. .. E : + nop # .. .. E .. : + nop # .. E .. .. : + ret $31, ($28), 1 # L0 .. .. .. : L U L U + .end __do_clear_user + diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-copy_user.S linux/arch/alpha/lib/ev6-copy_user.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-copy_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-copy_user.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,262 @@ +/* + * arch/alpha/lib/ev6-copy_user.S + * + * 21264 version contributed by Rick Gorton + * + * Copy to/from user space, handling exceptions as we go.. This + * isn't exactly pretty. + * + * This is essentially the same as "memcpy()", but with a few twists. + * Notably, we have to make sure that $0 is always up-to-date and + * contains the right "bytes left to copy" value (and that it is updated + * only _after_ a successful copy). There is also some rather minor + * exception setup stuff.. + * + * NOTE! This is not directly C-callable, because the calling semantics are + * different: + * + * Inputs: + * length in $0 + * destination address in $6 + * source address in $7 + * return address in $28 + * + * Outputs: + * bytes left to copy in $0 + * + * Clobbers: + * $1,$2,$3,$4,$5,$6,$7 + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + */ + +/* Allow an exception for an insn; exit if we get one. */ +#define EXI(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .gprel32 99b; \ + lda $31, $exitin-99b($31); \ + .previous + +#define EXO(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .gprel32 99b; \ + lda $31, $exitout-99b($31); \ + .previous + + .set noat + .align 4 + .globl __copy_user + .ent __copy_user + # Pipeline info: Slotting & Comments +__copy_user: + ldgp $29,0($27) # we do exceptions -- we need the gp. + # Macro instruction becomes ldah/lda + # .. .. E E + .prologue 1 + subq $0, 32, $1 # .. E .. .. : Is this going to be a small copy? + beq $0, $zerolength # U .. .. .. : U L U L + + and $6,7,$3 # .. .. .. E : is leading dest misalignment + ble $1, $onebyteloop # .. .. U .. : 1st branch : small amount of data + beq $3, $destaligned # .. U .. .. : 2nd (one cycle fetcher stall) + subq $3, 8, $3 # E .. .. .. : L U U L : trip counter +/* + * The fetcher stall also hides the 1 cycle cross-cluster stall for $3 (L --> U) + * This loop aligns the destination a byte at a time + * We know we have at least one trip through this loop + */ +$aligndest: + EXI( ldbu $1,0($7) ) # .. .. .. L : Keep loads separate from stores + addq $6,1,$6 # .. .. E .. : Section 3.8 in the CWG + addq $3,1,$3 # .. E .. .. : + nop # E .. .. .. : U L U L + +/* + * the -1 is to compensate for the inc($6) done in a previous quadpack + * which allows us zero dependencies within either quadpack in the loop + */ + EXO( stb $1,-1($6) ) # .. .. .. L : + addq $7,1,$7 # .. .. E .. : Section 3.8 in the CWG + subq $0,1,$0 # .. E .. .. : + bne $3, $aligndest # U .. .. .. : U L U L + +/* + * If we fell through into here, we have a minimum of 33 - 7 bytes + * If we arrived via branch, we have a minimum of 32 bytes + */ +$destaligned: + and $7,7,$1 # .. .. .. E : Check _current_ source alignment + bic $0,7,$4 # .. .. E .. : number bytes as a quadword loop + EXI( ldq_u $3,0($7) ) # .. L .. .. : Forward fetch for fallthrough code + beq $1,$quadaligned # U .. .. .. : U L U L + +/* + * In the worst case, we've just executed an ldq_u here from 0($7) + * and we'll repeat it once if we take the branch + */ + +/* Misaligned quadword loop - not unrolled. Leave it that way. */ +$misquad: + EXI( ldq_u $2,8($7) ) # .. .. .. L : + subq $4,8,$4 # .. .. E .. : + extql $3,$7,$3 # .. U .. .. : + extqh $2,$7,$1 # U .. .. .. : U U L L + + bis $3,$1,$1 # .. .. .. E : + EXO( stq $1,0($6) ) # .. .. L .. : + addq $7,8,$7 # .. E .. .. : + subq $0,8,$0 # E .. .. .. : U L L U + + addq $6,8,$6 # .. .. .. E : + bis $2,$2,$3 # .. .. E .. : + nop # .. E .. .. : + bne $4,$misquad # U .. .. .. : U L U L + + nop # .. .. .. E + nop # .. .. E .. + nop # .. E .. .. + beq $0,$zerolength # U .. .. .. : U L U L + +/* We know we have at least one trip through the byte loop */ + EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad + addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG) + nop # .. E .. .. : + br $31, $dirtyentry # L0 .. .. .. : L U U L +/* Do the trailing byte loop load, then hop into the store part of the loop */ + +/* + * A minimum of (33 - 7) bytes to do a quad at a time. + * Based upon the usage context, it's worth the effort to unroll this loop + * $0 - number of bytes to be moved + * $4 - number of bytes to move as quadwords + * $6 is current destination address + * $7 is current source address + */ +$quadaligned: + subq $4, 32, $2 # .. .. .. E : do not unroll for small stuff + nop # .. .. E .. + nop # .. E .. .. + blt $2, $onequad # U .. .. .. : U L U L + +/* + * There is a significant assumption here that the source and destination + * addresses differ by more than 32 bytes. In this particular case, a + * sparsity of registers further bounds this to be a minimum of 8 bytes. + * But if this isn't met, then the output result will be incorrect. + * Furthermore, due to a lack of available registers, we really can't + * unroll this to be an 8x loop (which would enable us to use the wh64 + * instruction memory hint instruction). + */ +$unroll4: + EXI( ldq $1,0($7) ) # .. .. .. L + EXI( ldq $2,8($7) ) # .. .. L .. + subq $4,32,$4 # .. E .. .. + nop # E .. .. .. : U U L L + + addq $7,16,$7 # .. .. .. E + EXO( stq $1,0($6) ) # .. .. L .. + EXO( stq $2,8($6) ) # .. L .. .. + subq $0,16,$0 # E .. .. .. : U L L U + + addq $6,16,$6 # .. .. .. E + EXI( ldq $1,0($7) ) # .. .. L .. + EXI( ldq $2,8($7) ) # .. L .. .. + subq $4, 32, $3 # E .. .. .. : U U L L : is there enough for another trip? + + EXO( stq $1,0($6) ) # .. .. .. L + EXO( stq $2,8($6) ) # .. .. L .. + subq $0,16,$0 # .. E .. .. + addq $7,16,$7 # E .. .. .. : U L L U + + nop # .. .. .. E + nop # .. .. E .. + addq $6,16,$6 # .. E .. .. + bgt $3,$unroll4 # U .. .. .. : U L U L + + nop + nop + nop + beq $4, $noquads + +$onequad: + EXI( ldq $1,0($7) ) + subq $4,8,$4 + addq $7,8,$7 + nop + + EXO( stq $1,0($6) ) + subq $0,8,$0 + addq $6,8,$6 + bne $4,$onequad + +$noquads: + nop + nop + nop + beq $0,$zerolength + +/* + * For small copies (or the tail of a larger copy), do a very simple byte loop. + * There's no point in doing a lot of complex alignment calculations to try to + * to quadword stuff for a small amount of data. + * $0 - remaining number of bytes left to copy + * $6 - current dest addr + * $7 - current source addr + */ + +$onebyteloop: + EXI ( ldbu $2,0($7) ) # .. .. .. L : No loads in the same quad + addq $6,1,$6 # .. .. E .. : as the store (Section 3.8 in CWG) + nop # .. E .. .. : + nop # E .. .. .. : U L U L + +$dirtyentry: +/* + * the -1 is to compensate for the inc($6) done in a previous quadpack + * which allows us zero dependencies within either quadpack in the loop + */ + EXO ( stb $2,-1($6) ) # .. .. .. L : + addq $7,1,$7 # .. .. E .. : quadpack as the load + subq $0,1,$0 # .. E .. .. : change count _after_ copy + bgt $0,$onebyteloop # U .. .. .. : U L U L + +$zerolength: +$exitout: # Destination for exception recovery(?) + nop # .. .. .. E + nop # .. .. E .. + nop # .. E .. .. + ret $31,($28),1 # L0 .. .. .. : L U L U + +$exitin: + + /* A stupid byte-by-byte zeroing of the rest of the output + buffer. This cures security holes by never leaving + random kernel data around to be copied elsewhere. */ + + nop + nop + nop + mov $0,$1 + +$101: + EXO ( stb $31,0($6) ) # L + subq $1,1,$1 # E + addq $6,1,$6 # E + bgt $1,$101 # U + + nop + nop + nop + ret $31,($28),1 # L0 + + .end __copy_user + diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-csum_ipv6_magic.S linux/arch/alpha/lib/ev6-csum_ipv6_magic.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-csum_ipv6_magic.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-csum_ipv6_magic.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,126 @@ +/* + * arch/alpha/lib/ev6-csum_ipv6_magic.S + * 21264 version contributed by Rick Gorton + * + * unsigned short csum_ipv6_magic(struct in6_addr *saddr, + * struct in6_addr *daddr, + * __u32 len, + * unsigned short proto, + * unsigned int csum); + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + * Determining actual stalls (other than slotting) doesn't appear to be easy to do. + * + * unsigned short csum_ipv6_magic(struct in6_addr *saddr, + * struct in6_addr *daddr, + * __u32 len, + * unsigned short proto, + * unsigned int csum); + * + * Swap (takes form 0xaabb) + * Then shift it left by 48, so result is: + * 0xbbaa0000 00000000 + * Then turn it back into a sign extended 32-bit item + * 0xbbaa0000 + * + * Swap (an unsigned int) using Mike Burrows' 7-instruction sequence + * (we can't hide the 3-cycle latency of the unpkbw in the 6-instruction sequence) + * Assume input takes form 0xAABBCCDD + * + * Finally, original 'folding' approach is to split the long into 4 unsigned shorts + * add 4 ushorts, resulting in ushort/carry + * add carry bits + ushort --> ushort + * add carry bits + ushort --> ushort (in case the carry results in an overflow) + * Truncate to a ushort. (took 13 instructions) + * From doing some testing, using the approach in checksum.c:from64to16() + * results in the same outcome: + * split into 2 uints, add those, generating a ulong + * add the 3 low ushorts together, generating a uint + * a final add of the 2 lower ushorts + * truncating the result. + */ + + .globl csum_ipv6_magic + .align 4 + .ent csum_ipv6_magic + .frame $30,0,$26,0 +csum_ipv6_magic: + .prologue 0 + + ldq $0,0($16) # L : Latency: 3 + inslh $18,7,$4 # U : 0000000000AABBCC + ldq $1,8($16) # L : Latency: 3 + sll $19,8,$7 # U : U L U L : 0x00000000 00aabb00 + + zapnot $20,15,$20 # U : zero extend incoming csum + ldq $2,0($17) # L : Latency: 3 + sll $19,24,$19 # U : U L L U : 0x000000aa bb000000 + inswl $18,3,$18 # U : 000000CCDD000000 + + ldq $3,8($17) # L : Latency: 3 + bis $18,$4,$18 # E : 000000CCDDAABBCC + addl $19,$7,$19 # E : bbaabb00 + nop # E : U L U L + + addq $20,$0,$20 # E : begin summing the words + srl $18,16,$4 # U : 0000000000CCDDAA + zap $19,0x3,$19 # U : bbaa0000 + nop # E : L U U L + + cmpult $20,$0,$0 # E : + addq $20,$1,$20 # E : + zapnot $18,0xa,$18 # U : 00000000DD00BB00 + zap $4,0xa,$4 # U : U U L L : 0000000000CC00AA + + or $18,$4,$18 # E : 00000000DDCCBBAA + nop # E : + cmpult $20,$1,$1 # E : + addq $20,$2,$20 # E : U L U L + + cmpult $20,$2,$2 # E : + addq $20,$3,$20 # E : + cmpult $20,$3,$3 # E : (1 cycle stall on $20) + addq $20,$18,$20 # E : U L U L (1 cycle stall on $20) + + cmpult $20,$18,$18 # E : + addq $20,$19,$20 # E : (1 cycle stall on $20) + addq $0,$1,$0 # E : merge the carries back into the csum + addq $2,$3,$2 # E : + + cmpult $20,$19,$19 # E : + addq $18,$19,$18 # E : (1 cycle stall on $19) + addq $0,$2,$0 # E : + addq $20,$18,$20 # E : U L U L : + /* (1 cycle stall on $18, 2 cycles on $20) */ + + addq $0,$20,$0 # E : + zapnot $0,15,$1 # U : Start folding output (1 cycle stall on $0) + nop # E : + srl $0,32,$0 # U : U L U L : (1 cycle stall on $0) + + addq $1,$0,$1 # E : Finished generating ulong + extwl $1,2,$2 # U : ushort[1] (1 cycle stall on $1) + zapnot $1,3,$0 # U : ushort[0] (1 cycle stall on $1) + extwl $1,4,$1 # U : ushort[2] (1 cycle stall on $1) + + addq $0,$2,$0 # E + addq $0,$1,$3 # E : Finished generating uint + /* (1 cycle stall on $0) */ + extwl $3,2,$1 # U : ushort[1] (1 cycle stall on $3) + nop # E : L U L U + + addq $1,$3,$0 # E : Final carry + not $0,$4 # E : complement (1 cycle stall on $0) + zapnot $4,3,$0 # U : clear upper garbage bits + /* (1 cycle stall on $4) */ + ret # L0 : L U L U + + .end csum_ipv6_magic diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-divide.S linux/arch/alpha/lib/ev6-divide.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-divide.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-divide.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,259 @@ +/* + * arch/alpha/lib/ev6-divide.S + * + * 21264 version contributed by Rick Gorton + * + * Alpha division.. + */ + +/* + * The alpha chip doesn't provide hardware division, so we have to do it + * by hand. The compiler expects the functions + * + * __divqu: 64-bit unsigned long divide + * __remqu: 64-bit unsigned long remainder + * __divqs/__remqs: signed 64-bit + * __divlu/__remlu: unsigned 32-bit + * __divls/__remls: signed 32-bit + * + * These are not normal C functions: instead of the normal + * calling sequence, these expect their arguments in registers + * $24 and $25, and return the result in $27. Register $28 may + * be clobbered (assembly temporary), anything else must be saved. + * + * In short: painful. + * + * This is a rather simple bit-at-a-time algorithm: it's very good + * at dividing random 64-bit numbers, but the more usual case where + * the divisor is small is handled better by the DEC algorithm + * using lookup tables. This uses much less memory, though, and is + * nicer on the cache.. Besides, I don't know the copyright status + * of the DEC code. + */ + +/* + * My temporaries: + * $0 - current bit + * $1 - shifted divisor + * $2 - modulus/quotient + * + * $23 - return address + * $24 - dividend + * $25 - divisor + * + * $27 - quotient/modulus + * $28 - compare status + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + +#define halt .long 0 + +/* + * Select function type and registers + */ +#define mask $0 +#define divisor $1 +#define compare $28 +#define tmp1 $3 +#define tmp2 $4 + +#ifdef DIV +#define DIV_ONLY(x,y...) x,##y +#define MOD_ONLY(x,y...) +#define func(x) __div##x +#define modulus $2 +#define quotient $27 +#define GETSIGN(x) xor $24,$25,x +#define STACK 48 +#else +#define DIV_ONLY(x,y...) +#define MOD_ONLY(x,y...) x,##y +#define func(x) __rem##x +#define modulus $27 +#define quotient $2 +#define GETSIGN(x) bis $24,$24,x +#define STACK 32 +#endif + +/* + * For 32-bit operations, we need to extend to 64-bit + */ +#ifdef INTSIZE +#define ufunction func(lu) +#define sfunction func(l) +#define LONGIFY(x) zapnot x,15,x +#define SLONGIFY(x) addl x,0,x +#else +#define ufunction func(qu) +#define sfunction func(q) +#define LONGIFY(x) +#define SLONGIFY(x) +#endif + +.set noat +.align 4 +.globl ufunction +.ent ufunction +ufunction: + subq $30,STACK,$30 # E : + .frame $30,STACK,$23 + .prologue 0 + +7: stq $1, 0($30) # L : + bis $25,$25,divisor # E : + stq $2, 8($30) # L : L U L U + + bis $24,$24,modulus # E : + stq $0,16($30) # L : + bis $31,$31,quotient # E : + LONGIFY(divisor) # E : U L L U + + stq tmp1,24($30) # L : + LONGIFY(modulus) # E : + bis $31,1,mask # E : + DIV_ONLY(stq tmp2,32($30)) # L : L U U L + + beq divisor, 9f /* div by zero */ + /* + * In spite of the DIV_ONLY being either a non-instruction + * or an actual stq, the addition of the .align directive + * below ensures that label 1 is going to be nicely aligned + */ + + .align 4 +#ifdef INTSIZE + /* + * shift divisor left, using 3-bit shifts for + * 32-bit divides as we can't overflow. Three-bit + * shifts will result in looping three times less + * here, but can result in two loops more later. + * Thus using a large shift isn't worth it (and + * s8add pairs better than a sll..) + */ +1: cmpult divisor,modulus,compare # E : + s8addq divisor,$31,divisor # E : + s8addq mask,$31,mask # E : + bne compare,1b # U : U L U L +#else +1: cmpult divisor,modulus,compare # E : + nop # E : + nop # E : + blt divisor, 2f # U : U L U L + + addq divisor,divisor,divisor # E : + addq mask,mask,mask # E : + unop # E : + bne compare,1b # U : U L U L +#endif + + /* ok, start to go right again.. */ +2: + /* + * Keep things nicely bundled... use a nop instead of not + * having an instruction for DIV_ONLY + */ +#ifdef DIV + DIV_ONLY(addq quotient,mask,tmp2) # E : +#else + nop # E : +#endif + srl mask,1,mask # U : + cmpule divisor,modulus,compare # E : + subq modulus,divisor,tmp1 # E : + +#ifdef DIV + DIV_ONLY(cmovne compare,tmp2,quotient) # E : Latency 2, extra map slot + nop # E : as part of the cmovne + srl divisor,1,divisor # U : + nop # E : L U L U + + nop # E : + cmovne compare,tmp1,modulus # E : Latency 2, extra map slot + nop # E : as part of the cmovne + bne mask,2b # U : U L U L +#else + srl divisor,1,divisor # U : + cmovne compare,tmp1,modulus # E : Latency 2, extra map slot + nop # E : as part of the cmovne + bne mask,2b # U : U L L U +#endif + +9: ldq $1, 0($30) # L : + ldq $2, 8($30) # L : + nop # E : + nop # E : U U L L + + ldq $0,16($30) # L : + ldq tmp1,24($30) # L : + nop # E : + nop # E : + +#ifdef DIV + DIV_ONLY(ldq tmp2,32($30)) # L : +#else + nop # E : +#endif + addq $30,STACK,$30 # E : + ret $31,($23),1 # L0 : L U U L + .end ufunction + +/* + * Uhh.. Ugly signed division. I'd rather not have it at all, but + * it's needed in some circumstances. There are different ways to + * handle this, really. This does: + * -a / b = a / -b = -(a / b) + * -a % b = -(a % b) + * a % -b = a % b + * which is probably not the best solution, but at least should + * have the property that (x/y)*y + (x%y) = x. + */ +.align 4 +.globl sfunction +.ent sfunction +sfunction: + subq $30,STACK,$30 # E : + .frame $30,STACK,$23 + .prologue 0 + bis $24,$25,$28 # E : + SLONGIFY($28) # E : + bge $28,7b # U : + + stq $24,0($30) # L : + subq $31,$24,$28 # E : + stq $25,8($30) # L : + nop # E : U L U L + + cmovlt $24,$28,$24 /* abs($24) */ # E : Latency 2, extra map slot + nop # E : as part of the cmov + stq $23,16($30) # L : + subq $31,$25,$28 # E : U L U L + + stq tmp1,24($30) # L : + cmovlt $25,$28,$25 /* abs($25) */ # E : Latency 2, extra map slot + nop # E : + bsr $23,ufunction # L0: L U L U + + ldq $24,0($30) # L : + ldq $25,8($30) # L : + GETSIGN($28) # E : + subq $31,$27,tmp1 # E : U U L L + + SLONGIFY($28) # E : + ldq $23,16($30) # L : + cmovlt $28,tmp1,$27 # E : Latency 2, extra map slot + nop # E : U L L U : as part of the cmov + + ldq tmp1,24($30) # L : + nop # E : as part of the cmov + addq $30,STACK,$30 # E : + ret $31,($23),1 # L0 : L U U L + .end sfunction diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-memchr.S linux/arch/alpha/lib/ev6-memchr.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-memchr.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-memchr.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,191 @@ +/* + * arch/alpha/lib/ev6-memchr.S + * + * 21264 version contributed by Rick Gorton + * + * Finds characters in a memory area. Optimized for the Alpha: + * + * - memory accessed as aligned quadwords only + * - uses cmpbge to compare 8 bytes in parallel + * - does binary search to find 0 byte in last + * quadword (HAKMEM needed 12 instructions to + * do this instead of the 9 instructions that + * binary search needs). + * + * For correctness consider that: + * + * - only minimum number of quadwords may be accessed + * - the third argument is an unsigned long + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + + .set noreorder + .set noat + + .align 4 + .globl memchr + .ent memchr +memchr: + .frame $30,0,$26,0 + .prologue 0 + + # Hack -- if someone passes in (size_t)-1, hoping to just + # search til the end of the address space, we will overflow + # below when we find the address of the last byte. Given + # that we will never have a 56-bit address space, cropping + # the length is the easiest way to avoid trouble. + zap $18, 0x80, $5 # U : Bound length + beq $18, $not_found # U : + ldq_u $1, 0($16) # L : load first quadword Latency=3 + and $17, 0xff, $17 # E : L L U U : 00000000000000ch + + insbl $17, 1, $2 # U : 000000000000ch00 + cmpult $18, 9, $4 # E : small (< 1 quad) string? + or $2, $17, $17 # E : 000000000000chch + lda $3, -1($31) # E : U L L U + + sll $17, 16, $2 # U : 00000000chch0000 + addq $16, $5, $5 # E : Max search address + or $2, $17, $17 # E : 00000000chchchch + sll $17, 32, $2 # U : U L L U : chchchch00000000 + + or $2, $17, $17 # E : chchchchchchchch + extql $1, $16, $7 # U : $7 is upper bits + beq $4, $first_quad # U : + ldq_u $6, -1($5) # L : L U U L : eight or less bytes to search Latency=3 + + extqh $6, $16, $6 # U : 2 cycle stall for $6 + mov $16, $0 # E : + nop # E : + or $7, $6, $1 # E : L U L U $1 = quadword starting at $16 + + # Deal with the case where at most 8 bytes remain to be searched + # in $1. E.g.: + # $18 = 6 + # $1 = ????c6c5c4c3c2c1 +$last_quad: + negq $18, $6 # E : + xor $17, $1, $1 # E : + srl $3, $6, $6 # U : $6 = mask of $18 bits set + cmpbge $31, $1, $2 # E : L U L U + + nop + nop + and $2, $6, $2 # E : + beq $2, $not_found # U : U L U L + +$found_it: +#if defined(__alpha_fix__) && defined(__alpha_cix__) + /* + * Since we are guaranteed to have set one of the bits, we don't + * have to worry about coming back with a 0x40 out of cttz... + */ + cttz $2, $3 # U0 : + addq $0, $3, $0 # E : All done + nop # E : + ret # L0 : L U L U +#else + /* + * Slow and clunky. It can probably be improved. + * An exercise left for others. + */ + negq $2, $3 # E : + and $2, $3, $2 # E : + and $2, 0x0f, $1 # E : + addq $0, 4, $3 # E : + + cmoveq $1, $3, $0 # E : Latency 2, extra map cycle + nop # E : keep with cmov + and $2, 0x33, $1 # E : + addq $0, 2, $3 # E : U L U L : 2 cycle stall on $0 + + cmoveq $1, $3, $0 # E : Latency 2, extra map cycle + nop # E : keep with cmov + and $2, 0x55, $1 # E : + addq $0, 1, $3 # E : U L U L : 2 cycle stall on $0 + + cmoveq $1, $3, $0 # E : Latency 2, extra map cycle + nop + nop + ret # L0 : L U L U +#endif + + # Deal with the case where $18 > 8 bytes remain to be + # searched. $16 may not be aligned. + .align 4 +$first_quad: + andnot $16, 0x7, $0 # E : + insqh $3, $16, $2 # U : $2 = 0000ffffffffffff ($16<0:2> ff) + xor $1, $17, $1 # E : + or $1, $2, $1 # E : U L U L $1 = ====ffffffffffff + + cmpbge $31, $1, $2 # E : + bne $2, $found_it # U : + # At least one byte left to process. + ldq $1, 8($0) # L : + subq $5, 1, $18 # E : U L U L + + addq $0, 8, $0 # E : + # Make $18 point to last quad to be accessed (the + # last quad may or may not be partial). + andnot $18, 0x7, $18 # E : + cmpult $0, $18, $2 # E : + beq $2, $final # U : U L U L + + # At least two quads remain to be accessed. + + subq $18, $0, $4 # E : $4 <- nr quads to be processed + and $4, 8, $4 # E : odd number of quads? + bne $4, $odd_quad_count # U : + # At least three quads remain to be accessed + mov $1, $4 # E : L U L U : move prefetched value to correct reg + + .align 4 +$unrolled_loop: + ldq $1, 8($0) # L : prefetch $1 + xor $17, $4, $2 # E : + cmpbge $31, $2, $2 # E : + bne $2, $found_it # U : U L U L + + addq $0, 8, $0 # E : + nop # E : + nop # E : + nop # E : + +$odd_quad_count: + xor $17, $1, $2 # E : + ldq $4, 8($0) # L : prefetch $4 + cmpbge $31, $2, $2 # E : + addq $0, 8, $6 # E : + + bne $2, $found_it # U : + cmpult $6, $18, $6 # E : + addq $0, 8, $0 # E : + nop # E : + + bne $6, $unrolled_loop # U : + mov $4, $1 # E : move prefetched value into $1 + nop # E : + nop # E : + +$final: subq $5, $0, $18 # E : $18 <- number of bytes left to do + nop # E : + nop # E : + bne $18, $last_quad # U : + +$not_found: + mov $31, $0 # E : + nop # E : + nop # E : + ret # L0 : + + .end memchr diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-memcpy.S linux/arch/alpha/lib/ev6-memcpy.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-memcpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-memcpy.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,248 @@ +/* + * arch/alpha/lib/ev6-memcpy.S + * 21264 version by Rick Gorton + * + * Reasonably optimized memcpy() routine for the Alpha 21264 + * + * - memory accessed as aligned quadwords only + * - uses bcmpge to compare 8 bytes in parallel + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * + * Temp usage notes: + * $1,$2, - scratch + */ + + .set noreorder + .set noat + + .align 4 + .globl memcpy + .ent memcpy +memcpy: + .frame $30,0,$26,0 + .prologue 0 + + mov $16, $0 # E : copy dest to return + ble $18, $nomoredata # U : done with the copy? + xor $16, $17, $1 # E : are source and dest alignments the same? + and $1, 7, $1 # E : are they the same mod 8? + + bne $1, $misaligned # U : Nope - gotta do this the slow way + /* source and dest are same mod 8 address */ + and $16, 7, $1 # E : Are both 0mod8? + beq $1, $both_0mod8 # U : Yes + nop # E : + + /* + * source and dest are same misalignment. move a byte at a time + * until a 0mod8 alignment for both is reached. + * At least one byte more to move + */ + +$head_align: + ldbu $1, 0($17) # L : grab a byte + subq $18, 1, $18 # E : count-- + addq $17, 1, $17 # E : src++ + stb $1, 0($16) # L : + addq $16, 1, $16 # E : dest++ + and $16, 7, $1 # E : Are we at 0mod8 yet? + ble $18, $nomoredata # U : done with the copy? + bne $1, $head_align # U : + +$both_0mod8: + cmple $18, 127, $1 # E : Can we unroll the loop? + bne $1, $no_unroll # U : + and $16, 63, $1 # E : get mod64 alignment + beq $1, $do_unroll # U : no single quads to fiddle + +$single_head_quad: + ldq $1, 0($17) # L : get 8 bytes + subq $18, 8, $18 # E : count -= 8 + addq $17, 8, $17 # E : src += 8 + nop # E : + + stq $1, 0($16) # L : store + addq $16, 8, $16 # E : dest += 8 + and $16, 63, $1 # E : get mod64 alignment + bne $1, $single_head_quad # U : still not fully aligned + +$do_unroll: + addq $16, 64, $7 # E : Initial (+1 trip) wh64 address + cmple $18, 63, $1 # E : Can we go through the unrolled loop? + bne $1, $tail_quads # U : Nope + nop # E : + +$unroll_body: + wh64 ($7) # L1 : memory subsystem hint: 64 bytes at + # ($7) are about to be over-written + ldq $6, 0($17) # L0 : bytes 0..7 + nop # E : + nop # E : + + ldq $4, 8($17) # L : bytes 8..15 + ldq $5, 16($17) # L : bytes 16..23 + addq $7, 64, $7 # E : Update next wh64 address + nop # E : + + ldq $3, 24($17) # L : bytes 24..31 + addq $16, 64, $1 # E : fallback value for wh64 + nop # E : + nop # E : + + addq $17, 32, $17 # E : src += 32 bytes + stq $6, 0($16) # L : bytes 0..7 + nop # E : + nop # E : + + stq $4, 8($16) # L : bytes 8..15 + stq $5, 16($16) # L : bytes 16..23 + subq $18, 192, $2 # E : At least two more trips to go? + nop # E : + + stq $3, 24($16) # L : bytes 24..31 + addq $16, 32, $16 # E : dest += 32 bytes + nop # E : + nop # E : + + ldq $6, 0($17) # L : bytes 0..7 + ldq $4, 8($17) # L : bytes 8..15 + cmovlt $2, $1, $7 # E : Latency 2, extra map slot - Use + # fallback wh64 address if < 2 more trips + nop # E : + + ldq $5, 16($17) # L : bytes 16..23 + ldq $3, 24($17) # L : bytes 24..31 + addq $16, 32, $16 # E : dest += 32 + subq $18, 64, $18 # E : count -= 64 + + addq $17, 32, $17 # E : src += 32 + stq $6, -32($16) # L : bytes 0..7 + stq $4, -24($16) # L : bytes 8..15 + cmple $18, 63, $1 # E : At least one more trip? + + stq $5, -16($16) # L : bytes 16..23 + stq $3, -8($16) # L : bytes 24..31 + nop # E : + beq $1, $unroll_body + +$tail_quads: +$no_unroll: + .align 4 + subq $18, 8, $18 # E : At least a quad left? + blt $18, $less_than_8 # U : Nope + nop # E : + nop # E : + +$move_a_quad: + ldq $1, 0($17) # L : fetch 8 + subq $18, 8, $18 # E : count -= 8 + addq $17, 8, $17 # E : src += 8 + nop # E : + + stq $1, 0($16) # L : store 8 + addq $16, 8, $16 # E : dest += 8 + bge $18, $move_a_quad # U : + nop # E : + +$less_than_8: + .align 4 + addq $18, 8, $18 # E : add back for trailing bytes + ble $18, $nomoredata # U : All-done + nop # E : + nop # E : + + /* Trailing bytes */ +$tail_bytes: + subq $18, 1, $18 # E : count-- + ldbu $1, 0($17) # L : fetch a byte + addq $17, 1, $17 # E : src++ + nop # E : + + stb $1, 0($16) # L : store a byte + addq $16, 1, $16 # E : dest++ + bgt $18, $tail_bytes # U : more to be done? + nop # E : + + /* branching to exit takes 3 extra cycles, so replicate exit here */ + ret $31, ($26), 1 # L0 : + nop # E : + nop # E : + nop # E : + +$misaligned: + mov $0, $4 # E : dest temp + and $0, 7, $1 # E : dest alignment mod8 + beq $1, $dest_0mod8 # U : life doesnt totally suck + nop + +$aligndest: + ble $18, $nomoredata # U : + ldbu $1, 0($17) # L : fetch a byte + subq $18, 1, $18 # E : count-- + addq $17, 1, $17 # E : src++ + + stb $1, 0($4) # L : store it + addq $4, 1, $4 # E : dest++ + and $4, 7, $1 # E : dest 0mod8 yet? + bne $1, $aligndest # U : go until we are aligned. + + /* Source has unknown alignment, but dest is known to be 0mod8 */ +$dest_0mod8: + subq $18, 8, $18 # E : At least a quad left? + blt $18, $misalign_tail # U : Nope + ldq_u $3, 0($17) # L : seed (rotating load) of 8 bytes + nop # E : + +$mis_quad: + ldq_u $16, 8($17) # L : Fetch next 8 + extql $3, $17, $3 # U : masking + extqh $16, $17, $1 # U : masking + bis $3, $1, $1 # E : merged bytes to store + + subq $18, 8, $18 # E : count -= 8 + addq $17, 8, $17 # E : src += 8 + stq $1, 0($4) # L : store 8 (aligned) + mov $16, $3 # E : "rotate" source data + + addq $4, 8, $4 # E : dest += 8 + bge $18, $mis_quad # U : More quads to move + nop + nop + +$misalign_tail: + addq $18, 8, $18 # E : account for tail stuff + ble $18, $nomoredata # U : + nop + nop + +$misalign_byte: + ldbu $1, 0($17) # L : fetch 1 + subq $18, 1, $18 # E : count-- + addq $17, 1, $17 # E : src++ + nop # E : + + stb $1, 0($4) # L : store + addq $4, 1, $4 # E : dest++ + bgt $18, $misalign_byte # U : more to go? + nop + + +$nomoredata: + ret $31, ($26), 1 # L0 : + nop # E : + nop # E : + nop # E : + + .end memcpy + +/* For backwards module compatability. */ +__memcpy = memcpy +.globl __memcpy diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-memset.S linux/arch/alpha/lib/ev6-memset.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-memset.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-memset.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,596 @@ +/* + * arch/alpha/lib/ev6-memset.S + * + * This is an efficient (and relatively small) implementation of the C library + * "memset()" function for the 21264 implementation of Alpha. + * + * 21264 version contributed by Rick Gorton + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * The algorithm for the leading and trailing quadwords remains the same, + * however the loop has been unrolled to enable better memory throughput, + * and the code has been replicated for each of the entry points: __memset + * and __memsetw to permit better scheduling to eliminate the stalling + * encountered during the mask replication. + * A future enhancement might be to put in a byte store loop for really + * small (say < 32 bytes) memset()s. Whether or not that change would be + * a win in the kernel would depend upon the contextual usage. + * WARNING: Maintaining this is going to be more work than the above version, + * as fixes will need to be made in multiple places. The performance gain + * is worth it. + */ + + .set noat + .set noreorder +.text + .globl __memset + .globl __memsetw + .globl __constant_c_memset + .globl memset + + .ent __memset +.align 5 +__memset: +memset: + .frame $30,0,$26,0 + .prologue 0 + + /* + * Serious stalling happens. The only way to mitigate this is to + * undertake a major re-write to interleave the constant materialization + * with other parts of the fall-through code. This is important, even + * though it makes maintenance tougher. + * Do this later. + */ + and $17,255,$1 # E : 00000000000000ch + insbl $17,1,$2 # U : 000000000000ch00 + bis $16,$16,$0 # E : return value + ble $18,end_b # U : zero length requested? + + addq $18,$16,$6 # E : max address to write to + bis $1,$2,$17 # E : 000000000000chch + insbl $1,2,$3 # U : 0000000000ch0000 + insbl $1,3,$4 # U : 00000000ch000000 + + or $3,$4,$3 # E : 00000000chch0000 + inswl $17,4,$5 # U : 0000chch00000000 + xor $16,$6,$1 # E : will complete write be within one quadword? + inswl $17,6,$2 # U : chch000000000000 + + or $17,$3,$17 # E : 00000000chchchch + or $2,$5,$2 # E : chchchch00000000 + bic $1,7,$1 # E : fit within a single quadword? + and $16,7,$3 # E : Target addr misalignment + + or $17,$2,$17 # E : chchchchchchchch + beq $1,within_quad_b # U : + nop # E : + beq $3,aligned_b # U : target is 0mod8 + + /* + * Target address is misaligned, and won't fit within a quadword + */ + ldq_u $4,0($16) # L : Fetch first partial + bis $16,$16,$5 # E : Save the address + insql $17,$16,$2 # U : Insert new bytes + subq $3,8,$3 # E : Invert (for addressing uses) + + addq $18,$3,$18 # E : $18 is new count ($3 is negative) + mskql $4,$16,$4 # U : clear relevant parts of the quad + subq $16,$3,$16 # E : $16 is new aligned destination + bis $2,$4,$1 # E : Final bytes + + nop + stq_u $1,0($5) # L : Store result + nop + nop + +.align 4 +aligned_b: + /* + * We are now guaranteed to be quad aligned, with at least + * one partial quad to write. + */ + + sra $18,3,$3 # U : Number of remaining quads to write + and $18,7,$18 # E : Number of trailing bytes to write + bis $16,$16,$5 # E : Save dest address + beq $3,no_quad_b # U : tail stuff only + + /* + * it's worth the effort to unroll this and use wh64 if possible + * Lifted a bunch of code from clear_user.S + * At this point, entry values are: + * $16 Current destination address + * $5 A copy of $16 + * $6 The max quadword address to write to + * $18 Number trailer bytes + * $3 Number quads to write + */ + + and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop) + subq $3, 16, $4 # E : Only try to unroll if > 128 bytes + subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64) + blt $4, loop_b # U : + + /* + * We know we've got at least 16 quads, minimum of one trip + * through unrolled loop. Do a quad at a time to get us 0mod64 + * aligned. + */ + + nop # E : + nop # E : + nop # E : + beq $1, $bigalign_b # U : + +$alignmod64_b: + stq $17, 0($5) # L : + subq $3, 1, $3 # E : For consistency later + addq $1, 8, $1 # E : Increment towards zero for alignment + addq $5, 8, $4 # E : Initial wh64 address (filler instruction) + + nop + nop + addq $5, 8, $5 # E : Inc address + blt $1, $alignmod64_b # U : + +$bigalign_b: + /* + * $3 - number quads left to go + * $5 - target address (aligned 0mod64) + * $17 - mask of stuff to store + * Scratch registers available: $7, $2, $4, $1 + * we know that we'll be taking a minimum of one trip through + * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle + * Assumes the wh64 needs to be for 2 trips through the loop in the future + * The wh64 is issued on for the starting destination address for trip +2 + * through the loop, and if there are less than two trips left, the target + * address will be for the current trip. + */ + +$do_wh64_b: + wh64 ($4) # L1 : memory subsystem write hint + subq $3, 24, $2 # E : For determining future wh64 addresses + stq $17, 0($5) # L : + nop # E : + + addq $5, 128, $4 # E : speculative target of next wh64 + stq $17, 8($5) # L : + stq $17, 16($5) # L : + addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr) + + stq $17, 24($5) # L : + stq $17, 32($5) # L : + cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle + nop + + stq $17, 40($5) # L : + stq $17, 48($5) # L : + subq $3, 16, $2 # E : Repeat the loop at least once more? + nop + + stq $17, 56($5) # L : + addq $5, 64, $5 # E : + subq $3, 8, $3 # E : + bge $2, $do_wh64_b # U : + + nop + nop + nop + beq $3, no_quad_b # U : Might have finished already + +.align 4 + /* + * Simple loop for trailing quadwords, or for small amounts + * of data (where we can't use an unrolled loop and wh64) + */ +loop_b: + stq $17,0($5) # L : + subq $3,1,$3 # E : Decrement number quads left + addq $5,8,$5 # E : Inc address + bne $3,loop_b # U : more? + +no_quad_b: + /* + * Write 0..7 trailing bytes. + */ + nop # E : + beq $18,end_b # U : All done? + ldq $7,0($5) # L : + mskqh $7,$6,$2 # U : Mask final quad + + insqh $17,$6,$4 # U : New bits + bis $2,$4,$1 # E : Put it all together + stq $1,0($5) # L : And back to memory + ret $31,($26),1 # L0 : + +within_quad_b: + ldq_u $1,0($16) # L : + insql $17,$16,$2 # U : New bits + mskql $1,$16,$4 # U : Clear old + bis $2,$4,$2 # E : New result + + mskql $2,$6,$4 # U : + mskqh $1,$6,$2 # U : + bis $2,$4,$1 # E : + stq_u $1,0($16) # L : + +end_b: + nop + nop + nop + ret $31,($26),1 # L0 : + .end __memset + + /* + * This is the original body of code, prior to replication and + * rescheduling. Leave it here, as there may be calls to this + * entry point. + */ +.align 4 + .ent __memset +__constant_c_memset: + .frame $30,0,$26,0 + .prologue 0 + + addq $18,$16,$6 # E : max address to write to + bis $16,$16,$0 # E : return value + xor $16,$6,$1 # E : will complete write be within one quadword? + ble $18,end # U : zero length requested? + + bic $1,7,$1 # E : fit within a single quadword + beq $1,within_one_quad # U : + and $16,7,$3 # E : Target addr misalignment + beq $3,aligned # U : target is 0mod8 + + /* + * Target address is misaligned, and won't fit within a quadword + */ + ldq_u $4,0($16) # L : Fetch first partial + bis $16,$16,$5 # E : Save the address + insql $17,$16,$2 # U : Insert new bytes + subq $3,8,$3 # E : Invert (for addressing uses) + + addq $18,$3,$18 # E : $18 is new count ($3 is negative) + mskql $4,$16,$4 # U : clear relevant parts of the quad + subq $16,$3,$16 # E : $16 is new aligned destination + bis $2,$4,$1 # E : Final bytes + + nop + stq_u $1,0($5) # L : Store result + nop + nop + +.align 4 +aligned: + /* + * We are now guaranteed to be quad aligned, with at least + * one partial quad to write. + */ + + sra $18,3,$3 # U : Number of remaining quads to write + and $18,7,$18 # E : Number of trailing bytes to write + bis $16,$16,$5 # E : Save dest address + beq $3,no_quad # U : tail stuff only + + /* + * it's worth the effort to unroll this and use wh64 if possible + * Lifted a bunch of code from clear_user.S + * At this point, entry values are: + * $16 Current destination address + * $5 A copy of $16 + * $6 The max quadword address to write to + * $18 Number trailer bytes + * $3 Number quads to write + */ + + and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop) + subq $3, 16, $4 # E : Only try to unroll if > 128 bytes + subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64) + blt $4, loop # U : + + /* + * We know we've got at least 16 quads, minimum of one trip + * through unrolled loop. Do a quad at a time to get us 0mod64 + * aligned. + */ + + nop # E : + nop # E : + nop # E : + beq $1, $bigalign # U : + +$alignmod64: + stq $17, 0($5) # L : + subq $3, 1, $3 # E : For consistency later + addq $1, 8, $1 # E : Increment towards zero for alignment + addq $5, 8, $4 # E : Initial wh64 address (filler instruction) + + nop + nop + addq $5, 8, $5 # E : Inc address + blt $1, $alignmod64 # U : + +$bigalign: + /* + * $3 - number quads left to go + * $5 - target address (aligned 0mod64) + * $17 - mask of stuff to store + * Scratch registers available: $7, $2, $4, $1 + * we know that we'll be taking a minimum of one trip through + * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle + * Assumes the wh64 needs to be for 2 trips through the loop in the future + * The wh64 is issued on for the starting destination address for trip +2 + * through the loop, and if there are less than two trips left, the target + * address will be for the current trip. + */ + +$do_wh64: + wh64 ($4) # L1 : memory subsystem write hint + subq $3, 24, $2 # E : For determining future wh64 addresses + stq $17, 0($5) # L : + nop # E : + + addq $5, 128, $4 # E : speculative target of next wh64 + stq $17, 8($5) # L : + stq $17, 16($5) # L : + addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr) + + stq $17, 24($5) # L : + stq $17, 32($5) # L : + cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle + nop + + stq $17, 40($5) # L : + stq $17, 48($5) # L : + subq $3, 16, $2 # E : Repeat the loop at least once more? + nop + + stq $17, 56($5) # L : + addq $5, 64, $5 # E : + subq $3, 8, $3 # E : + bge $2, $do_wh64 # U : + + nop + nop + nop + beq $3, no_quad # U : Might have finished already + +.align 4 + /* + * Simple loop for trailing quadwords, or for small amounts + * of data (where we can't use an unrolled loop and wh64) + */ +loop: + stq $17,0($5) # L : + subq $3,1,$3 # E : Decrement number quads left + addq $5,8,$5 # E : Inc address + bne $3,loop # U : more? + +no_quad: + /* + * Write 0..7 trailing bytes. + */ + nop # E : + beq $18,end # U : All done? + ldq $7,0($5) # L : + mskqh $7,$6,$2 # U : Mask final quad + + insqh $17,$6,$4 # U : New bits + bis $2,$4,$1 # E : Put it all together + stq $1,0($5) # L : And back to memory + ret $31,($26),1 # L0 : + +within_one_quad: + ldq_u $1,0($16) # L : + insql $17,$16,$2 # U : New bits + mskql $1,$16,$4 # U : Clear old + bis $2,$4,$2 # E : New result + + mskql $2,$6,$4 # U : + mskqh $1,$6,$2 # U : + bis $2,$4,$1 # E : + stq_u $1,0($16) # L : + +end: + nop + nop + nop + ret $31,($26),1 # L0 : + .end __constant_c_memset + + /* + * This is a replicant of the __constant_c_memset code, rescheduled + * to mask stalls. Note that entry point names also had to change + */ + .align 5 + .ent __memsetw + +__memsetw: + .frame $30,0,$26,0 + .prologue 0 + + inswl $17,0,$5 # U : 000000000000c1c2 + inswl $17,2,$2 # U : 00000000c1c20000 + bis $16,$16,$0 # E : return value + addq $18,$16,$6 # E : max address to write to + + ble $18, end_w # U : zero length requested? + inswl $17,4,$3 # U : 0000c1c200000000 + inswl $17,6,$4 # U : c1c2000000000000 + xor $16,$6,$1 # E : will complete write be within one quadword? + + or $2,$5,$2 # E : 00000000c1c2c1c2 + or $3,$4,$17 # E : c1c2c1c200000000 + bic $1,7,$1 # E : fit within a single quadword + and $16,7,$3 # E : Target addr misalignment + + or $17,$2,$17 # E : c1c2c1c2c1c2c1c2 + beq $1,within_quad_w # U : + nop + beq $3,aligned_w # U : target is 0mod8 + + /* + * Target address is misaligned, and won't fit within a quadword + */ + ldq_u $4,0($16) # L : Fetch first partial + bis $16,$16,$5 # E : Save the address + insql $17,$16,$2 # U : Insert new bytes + subq $3,8,$3 # E : Invert (for addressing uses) + + addq $18,$3,$18 # E : $18 is new count ($3 is negative) + mskql $4,$16,$4 # U : clear relevant parts of the quad + subq $16,$3,$16 # E : $16 is new aligned destination + bis $2,$4,$1 # E : Final bytes + + nop + stq_u $1,0($5) # L : Store result + nop + nop + +.align 4 +aligned_w: + /* + * We are now guaranteed to be quad aligned, with at least + * one partial quad to write. + */ + + sra $18,3,$3 # U : Number of remaining quads to write + and $18,7,$18 # E : Number of trailing bytes to write + bis $16,$16,$5 # E : Save dest address + beq $3,no_quad_w # U : tail stuff only + + /* + * it's worth the effort to unroll this and use wh64 if possible + * Lifted a bunch of code from clear_user.S + * At this point, entry values are: + * $16 Current destination address + * $5 A copy of $16 + * $6 The max quadword address to write to + * $18 Number trailer bytes + * $3 Number quads to write + */ + + and $16, 0x3f, $2 # E : Forward work (only useful for unrolled loop) + subq $3, 16, $4 # E : Only try to unroll if > 128 bytes + subq $2, 0x40, $1 # E : bias counter (aligning stuff 0mod64) + blt $4, loop_w # U : + + /* + * We know we've got at least 16 quads, minimum of one trip + * through unrolled loop. Do a quad at a time to get us 0mod64 + * aligned. + */ + + nop # E : + nop # E : + nop # E : + beq $1, $bigalign_w # U : + +$alignmod64_w: + stq $17, 0($5) # L : + subq $3, 1, $3 # E : For consistency later + addq $1, 8, $1 # E : Increment towards zero for alignment + addq $5, 8, $4 # E : Initial wh64 address (filler instruction) + + nop + nop + addq $5, 8, $5 # E : Inc address + blt $1, $alignmod64_w # U : + +$bigalign_w: + /* + * $3 - number quads left to go + * $5 - target address (aligned 0mod64) + * $17 - mask of stuff to store + * Scratch registers available: $7, $2, $4, $1 + * we know that we'll be taking a minimum of one trip through + * CWG Section 3.7.6: do not expect a sustained store rate of > 1/cycle + * Assumes the wh64 needs to be for 2 trips through the loop in the future + * The wh64 is issued on for the starting destination address for trip +2 + * through the loop, and if there are less than two trips left, the target + * address will be for the current trip. + */ + +$do_wh64_w: + wh64 ($4) # L1 : memory subsystem write hint + subq $3, 24, $2 # E : For determining future wh64 addresses + stq $17, 0($5) # L : + nop # E : + + addq $5, 128, $4 # E : speculative target of next wh64 + stq $17, 8($5) # L : + stq $17, 16($5) # L : + addq $5, 64, $7 # E : Fallback address for wh64 (== next trip addr) + + stq $17, 24($5) # L : + stq $17, 32($5) # L : + cmovlt $2, $7, $4 # E : Latency 2, extra mapping cycle + nop + + stq $17, 40($5) # L : + stq $17, 48($5) # L : + subq $3, 16, $2 # E : Repeat the loop at least once more? + nop + + stq $17, 56($5) # L : + addq $5, 64, $5 # E : + subq $3, 8, $3 # E : + bge $2, $do_wh64_w # U : + + nop + nop + nop + beq $3, no_quad_w # U : Might have finished already + +.align 4 + /* + * Simple loop for trailing quadwords, or for small amounts + * of data (where we can't use an unrolled loop and wh64) + */ +loop_w: + stq $17,0($5) # L : + subq $3,1,$3 # E : Decrement number quads left + addq $5,8,$5 # E : Inc address + bne $3,loop_w # U : more? + +no_quad_w: + /* + * Write 0..7 trailing bytes. + */ + nop # E : + beq $18,end_w # U : All done? + ldq $7,0($5) # L : + mskqh $7,$6,$2 # U : Mask final quad + + insqh $17,$6,$4 # U : New bits + bis $2,$4,$1 # E : Put it all together + stq $1,0($5) # L : And back to memory + ret $31,($26),1 # L0 : + +within_quad_w: + ldq_u $1,0($16) # L : + insql $17,$16,$2 # U : New bits + mskql $1,$16,$4 # U : Clear old + bis $2,$4,$2 # E : New result + + mskql $2,$6,$4 # U : + mskqh $1,$6,$2 # U : + bis $2,$4,$1 # E : + stq_u $1,0($16) # L : + +end_w: + nop + nop + nop + ret $31,($26),1 # L0 : + + .end __memsetw diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-strncpy_from_user.S linux/arch/alpha/lib/ev6-strncpy_from_user.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-strncpy_from_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-strncpy_from_user.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,425 @@ +/* + * arch/alpha/lib/ev6-strncpy_from_user.S + * 21264 version contributed by Rick Gorton + * + * Just like strncpy except in the return value: + * + * -EFAULT if an exception occurs before the terminator is copied. + * N if the buffer filled. + * + * Otherwise the length of the string is returned. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * A bunch of instructions got moved and temp registers were changed + * to aid in scheduling. Control flow was also re-arranged to eliminate + * branches, and to provide longer code sequences to enable better scheduling. + * A total rewrite (using byte load/stores for start & tail sequences) + * is desirable, but very difficult to do without a from-scratch rewrite. + * Save that for the future. + */ + + +#include +#include + + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .gprel32 99b; \ + lda $31, $exception-99b($0); \ + .previous + + + .set noat + .set noreorder + .text + + .globl __strncpy_from_user + .ent __strncpy_from_user + .frame $30, 0, $26 + .prologue 1 + + .align 4 +__strncpy_from_user: + ldgp $29, 0($27) # E E : becomes 2 instructions (for exceptions) + and a0, 7, t3 # E : find dest misalignment + beq a2, $zerolength # U : + + /* Are source and destination co-aligned? */ + mov a0, v0 # E : save the string start + xor a0, a1, t4 # E : + EX( ldq_u t1, 0(a1) ) # L : Latency=3 load first quadword + ldq_u t0, 0(a0) # L : load first (partial) aligned dest quadword + + addq a2, t3, a2 # E : bias count by dest misalignment + subq a2, 1, a3 # E : + addq zero, 1, t10 # E : + and t4, 7, t4 # E : misalignment between the two + + and a3, 7, t6 # E : number of tail bytes + sll t10, t6, t10 # E : t10 = bitmask of last count byte + bne t4, $unaligned # U : + lda t2, -1 # E : build a mask against false zero + + /* + * We are co-aligned; take care of a partial first word. + * On entry to this basic block: + * t0 == the first destination word for masking back in + * t1 == the first source word. + */ + + srl a3, 3, a2 # E : a2 = loop counter = (count - 1)/8 + addq a1, 8, a1 # E : + mskqh t2, a1, t2 # U : detection in the src word + nop + + /* Create the 1st output word and detect 0's in the 1st input word. */ + mskqh t1, a1, t3 # U : + mskql t0, a1, t0 # U : assemble the first output word + ornot t1, t2, t2 # E : + nop + + cmpbge zero, t2, t8 # E : bits set iff null found + or t0, t3, t0 # E : + beq a2, $a_eoc # U : + bne t8, $a_eos # U : 2nd branch in a quad. Bad. + + /* On entry to this basic block: + * t0 == a source quad not containing a null. + * a0 - current aligned destination address + * a1 - current aligned source address + * a2 - count of quadwords to move. + * NOTE: Loop improvement - unrolling this is going to be + * a huge win, since we're going to stall otherwise. + * Fix this later. For _really_ large copies, look + * at using wh64 on a look-ahead basis. See the code + * in clear_user.S and copy_user.S. + * Presumably, since (a0) and (a1) do not overlap (by C definition) + * Lots of nops here: + * - Separate loads from stores + * - Keep it to 1 branch/quadpack so the branch predictor + * can train. + */ +$a_loop: + stq_u t0, 0(a0) # L : + addq a0, 8, a0 # E : + nop + subq a2, 1, a2 # E : + + EX( ldq_u t0, 0(a1) ) # L : + addq a1, 8, a1 # E : + cmpbge zero, t0, t8 # E : Stall 2 cycles on t0 + beq a2, $a_eoc # U : + + beq t8, $a_loop # U : + nop + nop + nop + + /* Take care of the final (partial) word store. At this point + * the end-of-count bit is set in t8 iff it applies. + * + * On entry to this basic block we have: + * t0 == the source word containing the null + * t8 == the cmpbge mask that found it. + */ +$a_eos: + negq t8, t12 # E : find low bit set + and t8, t12, t12 # E : + + /* We're doing a partial word store and so need to combine + our source and original destination words. */ + ldq_u t1, 0(a0) # L : + subq t12, 1, t6 # E : + + or t12, t6, t8 # E : + zapnot t0, t8, t0 # U : clear src bytes > null + zap t1, t8, t1 # U : clear dst bytes <= null + or t0, t1, t0 # E : + + stq_u t0, 0(a0) # L : + br $finish_up # L0 : + nop + nop + + /* Add the end-of-count bit to the eos detection bitmask. */ + .align 4 +$a_eoc: + or t10, t8, t8 + br $a_eos + nop + nop + + +/* The source and destination are not co-aligned. Align the destination + and cope. We have to be very careful about not reading too much and + causing a SEGV. */ + + .align 4 +$u_head: + /* We know just enough now to be able to assemble the first + full source word. We can still find a zero at the end of it + that prevents us from outputting the whole thing. + + On entry to this basic block: + t0 == the first dest word, unmasked + t1 == the shifted low bits of the first source word + t6 == bytemask that is -1 in dest word bytes */ + + EX( ldq_u t2, 8(a1) ) # L : load second src word + addq a1, 8, a1 # E : + mskql t0, a0, t0 # U : mask trailing garbage in dst + extqh t2, a1, t4 # U : + + or t1, t4, t1 # E : first aligned src word complete + mskqh t1, a0, t1 # U : mask leading garbage in src + or t0, t1, t0 # E : first output word complete + or t0, t6, t6 # E : mask original data for zero test + + cmpbge zero, t6, t8 # E : + beq a2, $u_eocfin # U : + bne t8, $u_final # U : bad news - 2nd branch in a quad + lda t6, -1 # E : mask out the bits we have + + mskql t6, a1, t6 # U : already seen + stq_u t0, 0(a0) # L : store first output word + or t6, t2, t2 # E : + cmpbge zero, t2, t8 # E : find nulls in second partial + + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + bne t8, $u_late_head_exit # U : + nop + + /* Finally, we've got all the stupid leading edge cases taken care + of and we can set up to enter the main loop. */ + + extql t2, a1, t1 # U : position hi-bits of lo word + EX( ldq_u t2, 8(a1) ) # L : read next high-order source word + addq a1, 8, a1 # E : + cmpbge zero, t2, t8 # E : + + beq a2, $u_eoc # U : + bne t8, $u_eos # U : + nop + nop + + /* Unaligned copy main loop. In order to avoid reading too much, + the loop is structured to detect zeros in aligned source words. + This has, unfortunately, effectively pulled half of a loop + iteration out into the head and half into the tail, but it does + prevent nastiness from accumulating in the very thing we want + to run as fast as possible. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word + + We further know that t2 does not contain a null terminator. */ + + /* + * Extra nops here: + * separate load quads from store quads + * only one branch/quad to permit predictor training + */ + + .align 4 +$u_loop: + extqh t2, a1, t0 # U : extract high bits for current word + addq a1, 8, a1 # E : + extql t2, a1, t3 # U : extract low bits for next time + addq a0, 8, a0 # E : + + or t0, t1, t0 # E : current dst word now complete + EX( ldq_u t2, 0(a1) ) # L : load high word for next time + subq a2, 1, a2 # E : + nop + + stq_u t0, -8(a0) # L : save the current word + mov t3, t1 # E : + cmpbge zero, t2, t8 # E : test new word for eos + beq a2, $u_eoc # U : + + beq t8, $u_loop # U : + nop + nop + nop + + /* We've found a zero somewhere in the source word we just read. + If it resides in the lower half, we have one (probably partial) + word to write out, and if it resides in the upper half, we + have one full and one partial word left to write out. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word. */ + .align 4 +$u_eos: + extqh t2, a1, t0 # U : + or t0, t1, t0 # E : first (partial) source word complete + cmpbge zero, t0, t8 # E : is the null in this first bit? + nop + + bne t8, $u_final # U : + stq_u t0, 0(a0) # L : the null was in the high-order bits + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + + .align 4 +$u_late_head_exit: + extql t2, a1, t0 # U : + cmpbge zero, t0, t8 # E : + or t8, t10, t6 # E : + cmoveq a2, t6, t8 # E : + + /* Take care of a final (probably partial) result word. + On entry to this basic block: + t0 == assembled source word + t8 == cmpbge mask that found the null. */ + .align 4 +$u_final: + negq t8, t6 # E : isolate low bit set + and t6, t8, t12 # E : + ldq_u t1, 0(a0) # L : + subq t12, 1, t6 # E : + + or t6, t12, t8 # E : + zapnot t0, t8, t0 # U : kill source bytes > null + zap t1, t8, t1 # U : kill dest bytes <= null + or t0, t1, t0 # E : + + stq_u t0, 0(a0) # E : + br $finish_up # U : + nop + nop + + .align 4 +$u_eoc: # end-of-count + extqh t2, a1, t0 # U : + or t0, t1, t0 # E : + cmpbge zero, t0, t8 # E : + nop + + .align 4 +$u_eocfin: # end-of-count, final word + or t10, t8, t8 # E : + br $u_final # U : + nop + nop + + /* Unaligned copy entry point. */ + .align 4 +$unaligned: + + srl a3, 3, a2 # U : a2 = loop counter = (count - 1)/8 + and a0, 7, t4 # E : find dest misalignment + and a1, 7, t5 # E : find src misalignment + mov zero, t0 # E : + + /* Conditionally load the first destination word and a bytemask + with 0xff indicating that the destination byte is sacrosanct. */ + + mov zero, t6 # E : + beq t4, 1f # U : + ldq_u t0, 0(a0) # L : + lda t6, -1 # E : + + mskql t6, a0, t6 # E : + nop + nop + nop + + .align 4 +1: + subq a1, t4, a1 # E : sub dest misalignment from src addr + /* If source misalignment is larger than dest misalignment, we need + extra startup checks to avoid SEGV. */ + cmplt t4, t5, t12 # E : + extql t1, a1, t1 # U : shift src into place + lda t2, -1 # E : for creating masks later + + beq t12, $u_head # U : + mskqh t2, t5, t2 # U : begin src byte validity mask + cmpbge zero, t1, t8 # E : is there a zero? + nop + + extql t2, a1, t2 # U : + or t8, t10, t5 # E : test for end-of-count too + cmpbge zero, t2, t3 # E : + cmoveq a2, t5, t8 # E : Latency=2, extra map slot + + nop # E : goes with cmov + andnot t8, t3, t8 # E : + beq t8, $u_head # U : + nop + + /* At this point we've found a zero in the first partial word of + the source. We need to isolate the valid source data and mask + it into the original destination data. (Incidentally, we know + that we'll need at least one byte of that original dest word.) */ + + ldq_u t0, 0(a0) # L : + negq t8, t6 # E : build bitmask of bytes <= zero + mskqh t1, t4, t1 # U : + and t6, t8, t12 # E : + + subq t12, 1, t6 # E : + or t6, t12, t8 # E : + zapnot t2, t8, t2 # U : prepare source word; mirror changes + zapnot t1, t8, t1 # U : to source validity mask + + andnot t0, t2, t0 # E : zero place for source to reside + or t0, t1, t0 # E : and put it there + stq_u t0, 0(a0) # L : + nop + + .align 4 +$finish_up: + zapnot t0, t12, t4 # U : was last byte written null? + and t12, 0xf0, t3 # E : binary search for the address of the + cmovne t4, 1, t4 # E : Latency=2, extra map slot + nop # E : with cmovne + + and t12, 0xcc, t2 # E : last byte written + and t12, 0xaa, t1 # E : + cmovne t3, 4, t3 # E : Latency=2, extra map slot + nop # E : with cmovne + + bic a0, 7, t0 + cmovne t2, 2, t2 # E : Latency=2, extra map slot + nop # E : with cmovne + nop + + cmovne t1, 1, t1 # E : Latency=2, extra map slot + nop # E : with cmovne + addq t0, t3, t0 # E : + addq t1, t2, t1 # E : + + addq t0, t1, t0 # E : + addq t0, t4, t0 # add one if we filled the buffer + subq t0, v0, v0 # find string length + ret # L0 : + + .align 4 +$zerolength: + nop + nop + nop + clr v0 + +$exception: + nop + nop + nop + ret + + .end __strncpy_from_user diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-stxcpy.S linux/arch/alpha/lib/ev6-stxcpy.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-stxcpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-stxcpy.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,321 @@ +/* + * arch/alpha/lib/ev6-stxcpy.S + * 21264 version contributed by Rick Gorton + * + * Copy a null-terminated string from SRC to DST. + * + * This is an internal routine used by strcpy, stpcpy, and strcat. + * As such, it uses special linkage conventions to make implementation + * of these public functions more efficient. + * + * On input: + * t9 = return address + * a0 = DST + * a1 = SRC + * + * On output: + * t12 = bitmask (with one bit set) indicating the last byte written + * a0 = unaligned address of the last *word* written + * + * Furthermore, v0, a3-a5, t11, and t12 are untouched. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + +#include + + .set noat + .set noreorder + + .text + +/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that + doesn't like putting the entry point for a procedure somewhere in the + middle of the procedure descriptor. Work around this by putting the + aligned copy in its own procedure descriptor */ + + + .ent stxcpy_aligned + .align 4 +stxcpy_aligned: + .frame sp, 0, t9 + .prologue 0 + + /* On entry to this basic block: + t0 == the first destination word for masking back in + t1 == the first source word. */ + + /* Create the 1st output word and detect 0's in the 1st input word. */ + lda t2, -1 # E : build a mask against false zero + mskqh t2, a1, t2 # U : detection in the src word (stall) + mskqh t1, a1, t3 # U : + ornot t1, t2, t2 # E : (stall) + + mskql t0, a1, t0 # U : assemble the first output word + cmpbge zero, t2, t8 # E : bits set iff null found + or t0, t3, t1 # E : (stall) + bne t8, $a_eos # U : (stall) + + /* On entry to this basic block: + t0 == the first destination word for masking back in + t1 == a source word not containing a null. */ + /* Nops here to separate store quads from load quads */ + +$a_loop: + stq_u t1, 0(a0) # L : + addq a0, 8, a0 # E : + nop + nop + + ldq_u t1, 0(a1) # L : Latency=3 + addq a1, 8, a1 # E : + cmpbge zero, t1, t8 # E : (3 cycle stall) + beq t8, $a_loop # U : (stall for t8) + + /* Take care of the final (partial) word store. + On entry to this basic block we have: + t1 == the source word containing the null + t8 == the cmpbge mask that found it. */ +$a_eos: + negq t8, t6 # E : find low bit set + and t8, t6, t12 # E : (stall) + /* For the sake of the cache, don't read a destination word + if we're not going to need it. */ + and t12, 0x80, t6 # E : (stall) + bne t6, 1f # U : (stall) + + /* We're doing a partial word store and so need to combine + our source and original destination words. */ + ldq_u t0, 0(a0) # L : Latency=3 + subq t12, 1, t6 # E : + zapnot t1, t6, t1 # U : clear src bytes >= null (stall) + or t12, t6, t8 # E : (stall) + + zap t0, t8, t0 # E : clear dst bytes <= null + or t0, t1, t1 # E : (stall) + nop + nop + +1: stq_u t1, 0(a0) # L : + ret (t9) # L0 : Latency=3 + nop + nop + + .end stxcpy_aligned + + .align 4 + .ent __stxcpy + .globl __stxcpy +__stxcpy: + .frame sp, 0, t9 + .prologue 0 + + /* Are source and destination co-aligned? */ + xor a0, a1, t0 # E : + unop # E : + and t0, 7, t0 # E : (stall) + bne t0, $unaligned # U : (stall) + + /* We are co-aligned; take care of a partial first word. */ + ldq_u t1, 0(a1) # L : load first src word + and a0, 7, t0 # E : take care not to load a word ... + addq a1, 8, a1 # E : + beq t0, stxcpy_aligned # U : ... if we wont need it (stall) + + ldq_u t0, 0(a0) # L : + br stxcpy_aligned # L0 : Latency=3 + nop + nop + + +/* The source and destination are not co-aligned. Align the destination + and cope. We have to be very careful about not reading too much and + causing a SEGV. */ + + .align 4 +$u_head: + /* We know just enough now to be able to assemble the first + full source word. We can still find a zero at the end of it + that prevents us from outputting the whole thing. + + On entry to this basic block: + t0 == the first dest word, for masking back in, if needed else 0 + t1 == the low bits of the first source word + t6 == bytemask that is -1 in dest word bytes */ + + ldq_u t2, 8(a1) # L : + addq a1, 8, a1 # E : + extql t1, a1, t1 # U : (stall on a1) + extqh t2, a1, t4 # U : (stall on a1) + + mskql t0, a0, t0 # U : + or t1, t4, t1 # E : + mskqh t1, a0, t1 # U : (stall on t1) + or t0, t1, t1 # E : (stall on t1) + + or t1, t6, t6 # E : + cmpbge zero, t6, t8 # E : (stall) + lda t6, -1 # E : for masking just below + bne t8, $u_final # U : (stall) + + mskql t6, a1, t6 # U : mask out the bits we have + or t6, t2, t2 # E : already extracted before (stall) + cmpbge zero, t2, t8 # E : testing eos (stall) + bne t8, $u_late_head_exit # U : (stall) + + /* Finally, we've got all the stupid leading edge cases taken care + of and we can set up to enter the main loop. */ + + stq_u t1, 0(a0) # L : store first output word + addq a0, 8, a0 # E : + extql t2, a1, t0 # U : position ho-bits of lo word + ldq_u t2, 8(a1) # U : read next high-order source word + + addq a1, 8, a1 # E : + cmpbge zero, t2, t8 # E : (stall for t2) + nop # E : + bne t8, $u_eos # U : (stall) + + /* Unaligned copy main loop. In order to avoid reading too much, + the loop is structured to detect zeros in aligned source words. + This has, unfortunately, effectively pulled half of a loop + iteration out into the head and half into the tail, but it does + prevent nastiness from accumulating in the very thing we want + to run as fast as possible. + + On entry to this basic block: + t0 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word + + We further know that t2 does not contain a null terminator. */ + + .align 3 +$u_loop: + extqh t2, a1, t1 # U : extract high bits for current word + addq a1, 8, a1 # E : (stall) + extql t2, a1, t3 # U : extract low bits for next time (stall) + addq a0, 8, a0 # E : + + or t0, t1, t1 # E : current dst word now complete + ldq_u t2, 0(a1) # L : Latency=3 load high word for next time + stq_u t1, -8(a0) # L : save the current word (stall) + mov t3, t0 # E : + + cmpbge zero, t2, t8 # E : test new word for eos + beq t8, $u_loop # U : (stall) + nop + nop + + /* We've found a zero somewhere in the source word we just read. + If it resides in the lower half, we have one (probably partial) + word to write out, and if it resides in the upper half, we + have one full and one partial word left to write out. + + On entry to this basic block: + t0 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word. */ +$u_eos: + extqh t2, a1, t1 # U : + or t0, t1, t1 # E : first (partial) source word complete (stall) + cmpbge zero, t1, t8 # E : is the null in this first bit? (stall) + bne t8, $u_final # U : (stall) + +$u_late_head_exit: + stq_u t1, 0(a0) # L : the null was in the high-order bits + addq a0, 8, a0 # E : + extql t2, a1, t1 # U : + cmpbge zero, t1, t8 # E : (stall) + + /* Take care of a final (probably partial) result word. + On entry to this basic block: + t1 == assembled source word + t8 == cmpbge mask that found the null. */ +$u_final: + negq t8, t6 # E : isolate low bit set + and t6, t8, t12 # E : (stall) + and t12, 0x80, t6 # E : avoid dest word load if we can (stall) + bne t6, 1f # U : (stall) + + ldq_u t0, 0(a0) # E : + subq t12, 1, t6 # E : + or t6, t12, t8 # E : (stall) + zapnot t1, t6, t1 # U : kill source bytes >= null (stall) + + zap t0, t8, t0 # U : kill dest bytes <= null (2 cycle data stall) + or t0, t1, t1 # E : (stall) + nop + nop + +1: stq_u t1, 0(a0) # L : + ret (t9) # L0 : Latency=3 + nop + nop + + /* Unaligned copy entry point. */ + .align 4 +$unaligned: + + ldq_u t1, 0(a1) # L : load first source word + and a0, 7, t4 # E : find dest misalignment + and a1, 7, t5 # E : find src misalignment + /* Conditionally load the first destination word and a bytemask + with 0xff indicating that the destination byte is sacrosanct. */ + mov zero, t0 # E : + + mov zero, t6 # E : + beq t4, 1f # U : + ldq_u t0, 0(a0) # L : + lda t6, -1 # E : + + mskql t6, a0, t6 # U : + nop + nop + nop +1: + subq a1, t4, a1 # E : sub dest misalignment from src addr + /* If source misalignment is larger than dest misalignment, we need + extra startup checks to avoid SEGV. */ + cmplt t4, t5, t12 # E : + beq t12, $u_head # U : + lda t2, -1 # E : mask out leading garbage in source + + mskqh t2, t5, t2 # U : + ornot t1, t2, t3 # E : (stall) + cmpbge zero, t3, t8 # E : is there a zero? (stall) + beq t8, $u_head # U : (stall) + + /* At this point we've found a zero in the first partial word of + the source. We need to isolate the valid source data and mask + it into the original destination data. (Incidentally, we know + that we'll need at least one byte of that original dest word.) */ + + ldq_u t0, 0(a0) # L : + negq t8, t6 # E : build bitmask of bytes <= zero + and t6, t8, t12 # E : (stall) + and a1, 7, t5 # E : + + subq t12, 1, t6 # E : + or t6, t12, t8 # E : (stall) + srl t12, t5, t12 # U : adjust final null return value + zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall) + + and t1, t2, t1 # E : to source validity mask + extql t2, a1, t2 # U : + extql t1, a1, t1 # U : (stall) + andnot t0, t2, t0 # .. e1 : zero place for source to reside (stall) + + or t0, t1, t1 # e1 : and put it there + stq_u t1, 0(a0) # .. e0 : (stall) + ret (t9) # e1 : + nop + + .end __stxcpy + diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev6-stxncpy.S linux/arch/alpha/lib/ev6-stxncpy.S --- v2.4.0-test11/linux/arch/alpha/lib/ev6-stxncpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev6-stxncpy.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,399 @@ +/* + * arch/alpha/lib/ev6-stxncpy.S + * 21264 version contributed by Rick Gorton + * + * Copy no more than COUNT bytes of the null-terminated string from + * SRC to DST. + * + * This is an internal routine used by strncpy, stpncpy, and strncat. + * As such, it uses special linkage conventions to make implementation + * of these public functions more efficient. + * + * On input: + * t9 = return address + * a0 = DST + * a1 = SRC + * a2 = COUNT + * + * Furthermore, COUNT may not be zero. + * + * On output: + * t0 = last word written + * t10 = bitmask (with one bit set) indicating the byte position of + * the end of the range specified by COUNT + * t12 = bitmask (with one bit set) indicating the last byte written + * a0 = unaligned address of the last *word* written + * a2 = the number of full words left in COUNT + * + * Furthermore, v0, a3-a5, t11, t12, and $at are untouched. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + +#include + + .set noat + .set noreorder + + .text + +/* There is a problem with either gdb (as of 4.16) or gas (as of 2.7) that + doesn't like putting the entry point for a procedure somewhere in the + middle of the procedure descriptor. Work around this by putting the + aligned copy in its own procedure descriptor */ + + + .ent stxncpy_aligned + .align 4 +stxncpy_aligned: + .frame sp, 0, t9, 0 + .prologue 0 + + /* On entry to this basic block: + t0 == the first destination word for masking back in + t1 == the first source word. */ + + /* Create the 1st output word and detect 0's in the 1st input word. */ + lda t2, -1 # E : build a mask against false zero + mskqh t2, a1, t2 # U : detection in the src word (stall) + mskqh t1, a1, t3 # U : + ornot t1, t2, t2 # E : (stall) + + mskql t0, a1, t0 # U : assemble the first output word + cmpbge zero, t2, t8 # E : bits set iff null found + or t0, t3, t0 # E : (stall) + beq a2, $a_eoc # U : + + bne t8, $a_eos # U : + nop + nop + nop + + /* On entry to this basic block: + t0 == a source word not containing a null. */ + + /* + * nops here to: + * separate store quads from load quads + * limit of 1 bcond/quad to permit training + */ +$a_loop: + stq_u t0, 0(a0) # L : + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + nop + + ldq_u t0, 0(a1) # L : + addq a1, 8, a1 # E : + cmpbge zero, t0, t8 # E : + beq a2, $a_eoc # U : + + beq t8, $a_loop # U : + nop + nop + nop + + /* Take care of the final (partial) word store. At this point + the end-of-count bit is set in t8 iff it applies. + + On entry to this basic block we have: + t0 == the source word containing the null + t8 == the cmpbge mask that found it. */ + +$a_eos: + negq t8, t12 # E : find low bit set + and t8, t12, t12 # E : (stall) + /* For the sake of the cache, don't read a destination word + if we're not going to need it. */ + and t12, 0x80, t6 # E : (stall) + bne t6, 1f # U : (stall) + + /* We're doing a partial word store and so need to combine + our source and original destination words. */ + ldq_u t1, 0(a0) # L : + subq t12, 1, t6 # E : + or t12, t6, t8 # E : (stall) + zapnot t0, t8, t0 # U : clear src bytes > null (stall) + + zap t1, t8, t1 # .. e1 : clear dst bytes <= null + or t0, t1, t0 # e1 : (stall) + nop + nop + +1: stq_u t0, 0(a0) # L : + ret (t9) # L0 : Latency=3 + nop + nop + + /* Add the end-of-count bit to the eos detection bitmask. */ +$a_eoc: + or t10, t8, t8 # E : + br $a_eos # L0 : Latency=3 + nop + nop + + .end stxncpy_aligned + + .align 4 + .ent __stxncpy + .globl __stxncpy +__stxncpy: + .frame sp, 0, t9, 0 + .prologue 0 + + /* Are source and destination co-aligned? */ + xor a0, a1, t1 # E : + and a0, 7, t0 # E : find dest misalignment + and t1, 7, t1 # E : (stall) + addq a2, t0, a2 # E : bias count by dest misalignment (stall) + + subq a2, 1, a2 # E : + and a2, 7, t2 # E : (stall) + srl a2, 3, a2 # U : a2 = loop counter = (count - 1)/8 (stall) + addq zero, 1, t10 # E : + + sll t10, t2, t10 # U : t10 = bitmask of last count byte + bne t1, $unaligned # U : + /* We are co-aligned; take care of a partial first word. */ + ldq_u t1, 0(a1) # L : load first src word + addq a1, 8, a1 # E : + + beq t0, stxncpy_aligned # U : avoid loading dest word if not needed + ldq_u t0, 0(a0) # L : + nop + nop + + br stxncpy_aligned # .. e1 : + nop + nop + nop + + + +/* The source and destination are not co-aligned. Align the destination + and cope. We have to be very careful about not reading too much and + causing a SEGV. */ + + .align 4 +$u_head: + /* We know just enough now to be able to assemble the first + full source word. We can still find a zero at the end of it + that prevents us from outputting the whole thing. + + On entry to this basic block: + t0 == the first dest word, unmasked + t1 == the shifted low bits of the first source word + t6 == bytemask that is -1 in dest word bytes */ + + ldq_u t2, 8(a1) # L : Latency=3 load second src word + addq a1, 8, a1 # E : + mskql t0, a0, t0 # U : mask trailing garbage in dst + extqh t2, a1, t4 # U : (3 cycle stall on t2) + + or t1, t4, t1 # E : first aligned src word complete (stall) + mskqh t1, a0, t1 # U : mask leading garbage in src (stall) + or t0, t1, t0 # E : first output word complete (stall) + or t0, t6, t6 # E : mask original data for zero test (stall) + + cmpbge zero, t6, t8 # E : + beq a2, $u_eocfin # U : + nop + nop + + bne t8, $u_final # U : + lda t6, -1 # E : mask out the bits we have + mskql t6, a1, t6 # U : already seen (stall) + stq_u t0, 0(a0) # L : store first output word + + or t6, t2, t2 # E : + cmpbge zero, t2, t8 # E : find nulls in second partial (stall) + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + + bne t8, $u_late_head_exit # U : + /* Finally, we've got all the stupid leading edge cases taken care + of and we can set up to enter the main loop. */ + extql t2, a1, t1 # U : position hi-bits of lo word + ldq_u t2, 8(a1) # L : read next high-order source word + addq a1, 8, a1 # E : + + cmpbge zero, t2, t8 # E : (stall) + beq a2, $u_eoc # U : + nop + nop + + bne t8, $u_eos # e1 : + nop + nop + nop + + /* Unaligned copy main loop. In order to avoid reading too much, + the loop is structured to detect zeros in aligned source words. + This has, unfortunately, effectively pulled half of a loop + iteration out into the head and half into the tail, but it does + prevent nastiness from accumulating in the very thing we want + to run as fast as possible. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word + + We further know that t2 does not contain a null terminator. */ + + .align 4 +$u_loop: + extqh t2, a1, t0 # U : extract high bits for current word + addq a1, 8, a1 # E : + extql t2, a1, t3 # U : extract low bits for next time + addq a0, 8, a0 # E : + + or t0, t1, t0 # E : current dst word now complete + ldq_u t2, 0(a1) # U : Latency=3 load high word for next time + stq_u t0, -8(a0) # U : save the current word (stall) + mov t3, t1 # E : + + subq a2, 1, a2 # E : + cmpbge zero, t2, t8 # E : test new word for eos (2 cycle stall for data) + beq a2, $u_eoc # U : (stall) + nop + + beq t8, $u_loop # U : + nop + nop + nop + + /* We've found a zero somewhere in the source word we just read. + If it resides in the lower half, we have one (probably partial) + word to write out, and if it resides in the upper half, we + have one full and one partial word left to write out. + + On entry to this basic block: + t1 == the shifted high-order bits from the previous source word + t2 == the unshifted current source word. */ +$u_eos: + extqh t2, a1, t0 # U : + or t0, t1, t0 # E : first (partial) source word complete (stall) + cmpbge zero, t0, t8 # E : is the null in this first bit? (stall) + bne t8, $u_final # U : (stall) + + stq_u t0, 0(a0) # L : the null was in the high-order bits + addq a0, 8, a0 # E : + subq a2, 1, a2 # E : + nop + +$u_late_head_exit: + extql t2, a1, t0 # U : + cmpbge zero, t0, t8 # E : + or t8, t10, t6 # E : (stall) + cmoveq a2, t6, t8 # E : Latency=2, extra map slot (stall) + + /* Take care of a final (probably partial) result word. + On entry to this basic block: + t0 == assembled source word + t8 == cmpbge mask that found the null. */ +$u_final: + negq t8, t6 # E : isolate low bit set + and t6, t8, t12 # E : (stall) + and t12, 0x80, t6 # E : avoid dest word load if we can (stall) + bne t6, 1f # U : (stall) + + ldq_u t1, 0(a0) # L : + subq t12, 1, t6 # E : + or t6, t12, t8 # E : (stall) + zapnot t0, t8, t0 # U : kill source bytes > null + + zap t1, t8, t1 # U : kill dest bytes <= null + or t0, t1, t0 # E : (stall) + nop + nop + +1: stq_u t0, 0(a0) # L : + ret (t9) # L0 : Latency=3 + +$u_eoc: # end-of-count + extqh t2, a1, t0 # U : + or t0, t1, t0 # E : (stall) + cmpbge zero, t0, t8 # E : (stall) + nop + +$u_eocfin: # end-of-count, final word + or t10, t8, t8 # E : + br $u_final # L0 : Latency=3 + nop + nop + + /* Unaligned copy entry point. */ + .align 4 +$unaligned: + + ldq_u t1, 0(a1) # L : load first source word + and a0, 7, t4 # E : find dest misalignment + and a1, 7, t5 # E : find src misalignment + /* Conditionally load the first destination word and a bytemask + with 0xff indicating that the destination byte is sacrosanct. */ + mov zero, t0 # E : + + mov zero, t6 # E : + beq t4, 1f # U : + ldq_u t0, 0(a0) # L : + lda t6, -1 # E : + + mskql t6, a0, t6 # U : + nop + nop + nop +1: + subq a1, t4, a1 # E : sub dest misalignment from src addr + + /* If source misalignment is larger than dest misalignment, we need + extra startup checks to avoid SEGV. */ + + cmplt t4, t5, t12 # E : + extql t1, a1, t1 # U : shift src into place + lda t2, -1 # E : for creating masks later + beq t12, $u_head # U : (stall) + + mskqh t2, t5, t2 # U : begin src byte validity mask + cmpbge zero, t1, t8 # E : is there a zero? + extql t2, a1, t2 # U : + or t8, t10, t5 # E : test for end-of-count too + + cmpbge zero, t2, t3 # E : + cmoveq a2, t5, t8 # E : Latency=2, extra map slot + nop # E : keep with cmoveq + andnot t8, t3, t8 # E : (stall) + + beq t8, $u_head # U : + /* At this point we've found a zero in the first partial word of + the source. We need to isolate the valid source data and mask + it into the original destination data. (Incidentally, we know + that we'll need at least one byte of that original dest word.) */ + ldq_u t0, 0(a0) # L : + negq t8, t6 # E : build bitmask of bytes <= zero + mskqh t1, t4, t1 # U : + + and t6, t8, t12 # E : + subq t12, 1, t6 # E : (stall) + or t6, t12, t8 # E : (stall) + zapnot t2, t8, t2 # U : prepare source word; mirror changes (stall) + + zapnot t1, t8, t1 # U : to source validity mask + andnot t0, t2, t0 # E : zero place for source to reside + or t0, t1, t0 # E : and put it there (stall both t0, t1) + stq_u t0, 0(a0) # L : (stall) + + ret (t9) # L0 : Latency=3 + nop + nop + nop + + .end __stxncpy + diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev67-strcat.S linux/arch/alpha/lib/ev67-strcat.S --- v2.4.0-test11/linux/arch/alpha/lib/ev67-strcat.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev67-strcat.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,54 @@ +/* + * arch/alpha/lib/ev67-strcat.S + * 21264 version contributed by Rick Gorton + * + * Append a null-terminated string from SRC to DST. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + * Commentary: It seems bogus to walk the input string twice - once + * to determine the length, and then again while doing the copy. + * A significant (future) enhancement would be to only read the input + * string once. + */ + + + .text + + .align 4 + .globl strcat + .ent strcat +strcat: + .frame $30, 0, $26 + .prologue 0 + + mov $16, $0 # E : set up return value + /* Find the end of the string. */ + ldq_u $1, 0($16) # L : load first quadword (a0 may be misaligned) + lda $2, -1 # E : + insqh $2, $16, $2 # U : + + andnot $16, 7, $16 # E : + or $2, $1, $1 # E : + cmpbge $31, $1, $2 # E : bits set iff byte == 0 + bne $2, $found # U : + +$loop: ldq $1, 8($16) # L : + addq $16, 8, $16 # E : + cmpbge $31, $1, $2 # E : + beq $2, $loop # U : + +$found: cttz $2, $3 # U0 : + addq $16, $3, $16 # E : + /* Now do the append. */ + mov $26, $23 # E : + br __stxcpy # L0 : + + .end strcat diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev67-strchr.S linux/arch/alpha/lib/ev67-strchr.S --- v2.4.0-test11/linux/arch/alpha/lib/ev67-strchr.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev67-strchr.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,88 @@ +/* + * arch/alpha/lib/ev67-strchr.S + * 21264 version contributed by Rick Gorton + * + * Return the address of a given character within a null-terminated + * string, or null if it is not found. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + +#include + + .set noreorder + .set noat + + .align 4 + .globl strchr + .ent strchr +strchr: + .frame sp, 0, ra + .prologue 0 + + ldq_u t0, 0(a0) # L : load first quadword Latency=3 + and a1, 0xff, t3 # E : 00000000000000ch + insbl a1, 1, t5 # U : 000000000000ch00 + insbl a1, 7, a2 # U : ch00000000000000 + + insbl t3, 6, a3 # U : 00ch000000000000 + or t5, t3, a1 # E : 000000000000chch + andnot a0, 7, v0 # E : align our loop pointer + lda t4, -1 # E : build garbage mask + + mskqh t4, a0, t4 # U : only want relevant part of first quad + or a2, a3, a2 # E : chch000000000000 + inswl a1, 2, t5 # E : 00000000chch0000 + inswl a1, 4, a3 # E : 0000chch00000000 + + or a1, a2, a1 # E : chch00000000chch + or a3, t5, t5 # E : 0000chchchch0000 + cmpbge zero, t0, t2 # E : bits set iff byte == zero + cmpbge zero, t4, t4 # E : bits set iff byte is garbage + + /* This quad is _very_ serialized. Lots of stalling happens */ + or t5, a1, a1 # E : chchchchchchchch + xor t0, a1, t1 # E : make bytes == c zero + cmpbge zero, t1, t3 # E : bits set iff byte == c + or t2, t3, t0 # E : bits set iff char match or zero match + + andnot t0, t4, t0 # E : clear garbage bits + cttz t0, a2 # U0 : speculative (in case we get a match) + nop # E : + bne t0, $found # U : + + /* + * Yuk. This loop is going to stall like crazy waiting for the + * data to be loaded. Not much can be done about it unless it's + * unrolled multiple times - is that safe to do in kernel space? + * Or would exception handling recovery code do the trick here? + */ +$loop: ldq t0, 8(v0) # L : Latency=3 + addq v0, 8, v0 # E : + xor t0, a1, t1 # E : + cmpbge zero, t0, t2 # E : bits set iff byte == 0 + + cmpbge zero, t1, t3 # E : bits set iff byte == c + or t2, t3, t0 # E : + cttz t3, a2 # U0 : speculative (in case we get a match) + beq t0, $loop # U : + +$found: negq t0, t1 # E : clear all but least set bit + and t0, t1, t0 # E : + and t0, t3, t1 # E : bit set iff byte was the char + addq v0, a2, v0 # E : Add in the bit number from above + + cmoveq t1, $31, v0 # E : Two mapping slots, latency = 2 + nop + nop + ret # L0 : + + .end strchr diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev67-strlen.S linux/arch/alpha/lib/ev67-strlen.S --- v2.4.0-test11/linux/arch/alpha/lib/ev67-strlen.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev67-strlen.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,49 @@ +/* + * arch/alpha/lib/ev67-strlen.S + * 21264 version by Rick Gorton + * + * Finds length of a 0-terminated string. Optimized for the + * Alpha architecture: + * + * - memory accessed as aligned quadwords only + * - uses bcmpge to compare 8 bytes in parallel + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + */ + + .set noreorder + .set noat + + .globl strlen + .ent strlen + .align 4 +strlen: + ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned) + lda $2, -1($31) # E : + insqh $2, $16, $2 # U : + andnot $16, 7, $0 # E : + + or $2, $1, $1 # E : + cmpbge $31, $1, $2 # E : $2 <- bitmask: bit i == 1 <==> i-th byte == 0 + nop # E : + bne $2, $found # U : + +$loop: ldq $1, 8($0) # L : + addq $0, 8, $0 # E : addr += 8 + cmpbge $31, $1, $2 # E : + beq $2, $loop # U : + +$found: + cttz $2, $3 # U0 : + addq $0, $3, $0 # E : + subq $0, $16, $0 # E : + ret $31, ($26) # L0 : + + .end strlen diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev67-strlen_user.S linux/arch/alpha/lib/ev67-strlen_user.S --- v2.4.0-test11/linux/arch/alpha/lib/ev67-strlen_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev67-strlen_user.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,109 @@ +/* + * arch/alpha/lib/ev67-strlen_user.S + * 21264 version contributed by Rick Gorton + * + * Return the length of the string including the NULL terminator + * (strlen+1) or zero if an error occurred. + * + * In places where it is critical to limit the processing time, + * and the data is not trusted, strnlen_user() should be used. + * It will return a value greater than its second argument if + * that limit would be exceeded. This implementation is allowed + * to access memory beyond the limit, but will not cross a page + * boundary when doing so. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + +#include + + +/* Allow an exception for an insn; exit if we get one. */ +#define EX(x,y...) \ + 99: x,##y; \ + .section __ex_table,"a"; \ + .gprel32 99b; \ + lda v0, $exception-99b(zero); \ + .previous + + + .set noreorder + .set noat + .text + + .globl __strlen_user + .ent __strlen_user + .frame sp, 0, ra + + .align 4 +__strlen_user: + ldah a1, 32767(zero) # do not use plain strlen_user() for strings + # that might be almost 2 GB long; you should + # be using strnlen_user() instead + nop + nop + nop + + .globl __strnlen_user + + .align 4 +__strnlen_user: + ldgp $29,0($27) # E E : we do exceptions -- we need the gp. + /* Decomposes into lda/ldah */ + .prologue 1 + EX( ldq_u t0, 0(a0) ) # L : load first quadword (a0 may be misaligned) + lda t1, -1(zero) # E : + + insqh t1, a0, t1 # U : + andnot a0, 7, v0 # E : + or t1, t0, t0 # E : + subq a0, 1, a0 # E : get our +1 for the return + + cmpbge zero, t0, t1 # E : t1 <- bitmask: bit i == 1 <==> i-th byte == 0 + subq a1, 7, t2 # E : + subq a0, v0, t0 # E : + bne t1, $found # U : + + addq t2, t0, t2 # E : + addq a1, 1, a1 # E : + nop # E : + nop # E : + + .align 4 +$loop: ble t2, $limit # U : + EX( ldq t0, 8(v0) ) # L : + nop # E : + nop # E : + + cmpbge zero, t0, t1 # E : + subq t2, 8, t2 # E : + addq v0, 8, v0 # E : addr += 8 + beq t1, $loop # U : + +$found: cttz t1, t2 # U0 : + addq v0, t2, v0 # E : + subq v0, a0, v0 # E : + ret # L0 : + +$exception: + nop + nop + nop + ret + + .align 4 # currently redundant +$limit: + nop + nop + subq a1, t2, v0 + ret + + .end __strlen_user diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/ev67-strncat.S linux/arch/alpha/lib/ev67-strncat.S --- v2.4.0-test11/linux/arch/alpha/lib/ev67-strncat.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/ev67-strncat.S Sun Dec 3 17:45:20 2000 @@ -0,0 +1,94 @@ +/* + * arch/alpha/lib/ev67-strncat.S + * 21264 version contributed by Rick Gorton + * + * Append no more than COUNT characters from the null-terminated string SRC + * to the null-terminated string DST. Always null-terminate the new DST. + * + * This differs slightly from the semantics in libc in that we never write + * past count, whereas libc may write to count+1. This follows the generic + * implementation in lib/string.c and is, IMHO, more sensible. + * + * Much of the information about 21264 scheduling/coding comes from: + * Compiler Writer's Guide for the Alpha 21264 + * abbreviated as 'CWG' in other comments here + * ftp.digital.com/pub/Digital/info/semiconductor/literature/dsc-library.html + * Scheduling notation: + * E - either cluster + * U - upper subcluster; U0 - subcluster U0; U1 - subcluster U1 + * L - lower subcluster; L0 - subcluster L0; L1 - subcluster L1 + * Try not to change the actual algorithm if possible for consistency. + */ + + + .text + + .align 4 + .globl strncat + .ent strncat +strncat: + .frame $30, 0, $26 + .prologue 0 + + mov $16, $0 # set up return value + beq $18, $zerocount # U : + /* Find the end of the string. */ + ldq_u $1, 0($16) # L : load first quadword ($16 may be misaligned) + lda $2, -1($31) # E : + + insqh $2, $0, $2 # U : + andnot $16, 7, $16 # E : + nop # E : + or $2, $1, $1 # E : + + nop # E : + nop # E : + cmpbge $31, $1, $2 # E : bits set iff byte == 0 + bne $2, $found # U : + +$loop: ldq $1, 8($16) # L : + addq $16, 8, $16 # E : + cmpbge $31, $1, $2 # E : + beq $2, $loop # U : + +$found: cttz $2, $3 # U0 : + addq $16, $3, $16 # E : + nop # E : + bsr $23, __stxncpy # L0 :/* Now do the append. */ + + /* Worry about the null termination. */ + + zapnot $1, $27, $2 # U : was last byte a null? + cmplt $27, $24, $5 # E : did we fill the buffer completely? + bne $2, 0f # U : + ret # L0 : + +0: or $5, $18, $2 # E : + nop + bne $2, 2f # U : + and $24, 0x80, $3 # E : no zero next byte + + nop # E : + bne $3, 1f # U : + /* Here there are bytes left in the current word. Clear one. */ + addq $24, $24, $24 # E : end-of-count bit <<= 1 + nop # E : + +2: zap $1, $24, $1 # U : + nop # E : + stq_u $1, 0($16) # L : + ret # L0 : + +1: /* Here we must clear the first byte of the next DST word */ + stb $31, 8($16) # L : + nop # E : + nop # E : + ret # L0 : + +$zerocount: + nop # E : + nop # E : + nop # E : + ret # L0 : + + .end strncat diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/memcpy.c linux/arch/alpha/lib/memcpy.c --- v2.4.0-test11/linux/arch/alpha/lib/memcpy.c Mon Jun 7 11:37:13 1999 +++ linux/arch/alpha/lib/memcpy.c Mon Dec 11 13:46:26 2000 @@ -161,24 +161,3 @@ /* For backward modules compatibility, define __memcpy. */ asm("__memcpy = memcpy; .globl __memcpy"); - -void *memmove (void *dest, const void *src, size_t n) -{ - if (dest <= src) { - if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) - __memcpy_aligned_up ((unsigned long) dest, - (unsigned long) src, n); - else - __memcpy_unaligned_up ((unsigned long) dest, - (unsigned long) src, n); - } - else { - if (!(((unsigned long) dest ^ (unsigned long) src) & 7)) - __memcpy_aligned_dn ((unsigned long) dest, - (unsigned long) src, n); - else - __memcpy_unaligned_dn ((unsigned long) dest, - (unsigned long) src, n); - } - return dest; -} diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/memmove.S linux/arch/alpha/lib/memmove.S --- v2.4.0-test11/linux/arch/alpha/lib/memmove.S Wed Dec 31 16:00:00 1969 +++ linux/arch/alpha/lib/memmove.S Mon Dec 11 13:46:26 2000 @@ -0,0 +1,103 @@ +/* + * arch/alpha/lib/memmove.S + * + * Barely optimized memmove routine for Alpha EV5. + * + * This is hand-massaged output from the original memcpy.c. We defer to + * memcpy whenever possible; the backwards copy loops are not unrolled. + */ + + .set noat + .set noreorder + .text + + .align 4 + .globl memmove + .ent memmove +memmove: + addq $16,$18,$4 + addq $17,$18,$5 + cmpule $4,$17,$1 /* dest + n <= src */ + cmpule $5,$16,$2 /* dest >= src + n */ + + bis $1,$2,$1 + mov $16,$0 + xor $16,$17,$2 + bne $1,memcpy + + and $2,7,$2 /* Test for src/dest co-alignment. */ + bne $2,$misaligned + + and $4,7,$1 + beq $1,$skip_aligned_byte_loop_head + +$aligned_byte_loop_head: + lda $4,-1($4) + lda $5,-1($5) + unop + ble $18,$egress + + ldq_u $3,0($5) + ldq_u $2,0($4) + lda $18,-1($18) + extbl $3,$5,$1 + + insbl $1,$4,$1 + mskbl $2,$4,$2 + bis $1,$2,$1 + and $4,7,$6 + + stq_u $1,0($4) + bne $6,$aligned_byte_loop_head + +$skip_aligned_byte_loop_head: + lda $18,-8($18) + blt $18,$skip_aligned_word_loop + +$aligned_word_loop: + ldq $1,-8($5) + nop + lda $5,-8($5) + lda $18,-8($18) + + stq $1,-8($4) + nop + lda $4,-8($4) + bge $18,$aligned_word_loop + +$skip_aligned_word_loop: + lda $18,8($18) + bgt $18,$byte_loop_tail + unop + ret $31,($26),1 + + .align 4 +$misaligned: + nop + fnop + unop + beq $18,$egress + +$byte_loop_tail: + ldq_u $3,-1($5) + ldq_u $2,-1($4) + lda $5,-1($5) + lda $4,-1($4) + + lda $18,-1($18) + extbl $3,$5,$1 + insbl $1,$4,$1 + mskbl $2,$4,$2 + + bis $1,$2,$1 + stq_u $1,0($4) + nop + bgt $18,$byte_loop_tail + +$egress: + ret $31,($26),1 + nop + nop + nop + + .end memmove diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/strcpy.S linux/arch/alpha/lib/strcpy.S --- v2.4.0-test11/linux/arch/alpha/lib/strcpy.S Fri Oct 18 01:53:20 1996 +++ linux/arch/alpha/lib/strcpy.S Mon Dec 11 13:46:26 2000 @@ -17,6 +17,7 @@ mov $16, $0 # set up return value mov $26, $23 # set up return address + unop br __stxcpy # do the copy .end strcpy diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/strncpy.S linux/arch/alpha/lib/strncpy.S --- v2.4.0-test11/linux/arch/alpha/lib/strncpy.S Fri Oct 18 01:53:20 1996 +++ linux/arch/alpha/lib/strncpy.S Mon Dec 11 13:46:26 2000 @@ -27,6 +27,10 @@ beq $18, 0f mov $26, $23 # set return address br __stxncpy # do the work of the copy + 0: ret + nop + nop + nop .end strncpy diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/stxcpy.S linux/arch/alpha/lib/stxcpy.S --- v2.4.0-test11/linux/arch/alpha/lib/stxcpy.S Thu Feb 6 04:42:35 1997 +++ linux/arch/alpha/lib/stxcpy.S Mon Dec 11 13:46:26 2000 @@ -1,4 +1,5 @@ -/* stxcpy.S +/* + * arch/alpha/lib/stxcpy.S * Contributed by Richard Henderson (rth@tamu.edu) * * Copy a null-terminated string from SRC to DST. diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/lib/stxncpy.S linux/arch/alpha/lib/stxncpy.S --- v2.4.0-test11/linux/arch/alpha/lib/stxncpy.S Thu Feb 6 04:51:09 1997 +++ linux/arch/alpha/lib/stxncpy.S Mon Dec 11 13:46:26 2000 @@ -1,4 +1,5 @@ -/* stxncpy.S +/* + * arch/alpha/lib/stxncpy.S * Contributed by Richard Henderson (rth@tamu.edu) * * Copy no more than COUNT bytes of the null-terminated string from diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/mm/init.c linux/arch/alpha/mm/init.c --- v2.4.0-test11/linux/arch/alpha/mm/init.c Tue Oct 31 12:42:25 2000 +++ linux/arch/alpha/mm/init.c Tue Nov 28 22:43:39 2000 @@ -185,7 +185,7 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!atomic_read(&mem_map[i].count)) + else if (!page_count(mem_map+i)) free++; else shared += atomic_read(&mem_map[i].count) - 1; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile --- v2.4.0-test11/linux/arch/arm/boot/Makefile Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/boot/Makefile Mon Nov 27 17:07:59 2000 @@ -35,16 +35,21 @@ INITRD_VIRT = 0xc0800000 endif +ifeq ($(CONFIG_ARCH_SHARK),y) +ZTEXTADDR = 0x08508000 +ZRELADDR = 0x08008000 +endif + ifeq ($(CONFIG_FOOTBRIDGE),y) ZTEXTADDR = 0x00008000 -PARAMS = 0x00000100 +PARAMS_PHYS = 0x00000100 INITRD_PHYS = 0x00800000 INITRD_VIRT = 0xc0800000 endif ifeq ($(CONFIG_ARCH_INTEGRATOR),y) ZTEXTADDR = 0x00008000 -PARAMS = 0x00000100 +PARAMS_PHYS = 0x00000100 INITRD_PHYS = 0x00800000 INITRD_VIRT = 0xc0800000 endif @@ -65,6 +70,14 @@ ZBSSADDR = 0xf03e0000 endif +ifeq ($(CONFIG_ARCH_P720T),y) +ZTEXTADDR = 0xc0018000 +ZRELADDR = 0xc0018000 +PARAMS_PHYS = 0xc0000100 +INITRD_PHYS = 0xc0400000 +INITRD_VIRT = 0xc0400000 +endif + ifeq ($(CONFIG_ARCH_SA1100),y) ZTEXTADDR = 0xc0008000 ZRELADDR = 0xc0008000 @@ -72,8 +85,9 @@ ZTEXTADDR = 0x00002000 ZBSSADDR = 0xc0100000 endif -ifeq ($(CONFIG_SA1100_THINCLIENT),y) - ZTEXTADDR = 0xC0200000 +ifeq ($(CONFIG_SA1100_SHERMAN),y) + ZTEXTADDR = 0x00050000 + ZBSSADDR = 0xc0100000 endif ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y) ZTEXTADDR = 0xC0200000 diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile --- v2.4.0-test11/linux/arch/arm/boot/compressed/Makefile Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/boot/compressed/Makefile Mon Nov 27 17:07:59 2000 @@ -18,6 +18,7 @@ # ifeq ($(CONFIG_ARCH_ACORN),y) OBJS += ll_char_wr.o font.o +ZLDFLAGS += -defsym params=$(PARAMS_PHYS) endif ifeq ($(CONFIG_ARCH_NETWINDER),y) @@ -34,6 +35,11 @@ ifeq ($(CONFIG_ARCH_L7200),y) OBJS += head-l7200.o +endif + +ifeq ($(CONFIG_ARCH_P720T),y) +# Borrow this code from SA1100 +OBJS += head-sa1100.o endif ifeq ($(CONFIG_ARCH_SA1100),y) diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/a5k linux/arch/arm/def-configs/a5k --- v2.4.0-test11/linux/arch/arm/def-configs/a5k Mon Jun 19 17:59:33 2000 +++ linux/arch/arm/def-configs/a5k Mon Nov 27 17:07:59 2000 @@ -2,36 +2,72 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +# CONFIG_SBUS is not set +CONFIG_UID16=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_OBSOLETE=y # -# System and processor type +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +CONFIG_ARCH_ARCA5K=y +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Archimedes/A5000 Implementations (select only ONE) # # CONFIG_ARCH_ARC is not set CONFIG_ARCH_A5K=y -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_FOOTBRIDGE is not set + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# CONFIG_ARCH_ACORN=y +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set # CONFIG_CPU_32 is not set CONFIG_CPU_26=y # CONFIG_PAGESIZE_16 is not set -# CONFIG_ISA_DMA is not set # -# Loadable module support +# Processor Type # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_DISCONTIGMEM is not set # # General setup # +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -42,9 +78,15 @@ CONFIG_BINFMT_AOUT=y # CONFIG_BINFMT_ELF is not set # CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set + +# +# Parallel port support +# CONFIG_PARPORT=m CONFIG_PARPORT_PC=m # CONFIG_PARPORT_PC_FIFO is not set +CONFIG_PARPORT_PC_SUPERIO=y # CONFIG_PARPORT_ARC is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set @@ -54,14 +96,9 @@ # CONFIG_PARPORT_1284 is not set # -# I2O device support +# Memory Technology Devices (MTD) # -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +# CONFIG_MTD is not set # # Plug and Play configuration @@ -73,37 +110,16 @@ # Block devices # CONFIG_BLK_DEV_FD=y -CONFIG_BLK_DEV_IDE=y - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -# CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set - -# -# IDE chipset support/bugfixes -# -# CONFIG_BLK_DEV_CMD640 is not set -CONFIG_BLK_DEV_IDE_ICSIDE=y -# CONFIG_BLK_DEV_IDEDMA_ICS is not set -# CONFIG_BLK_DEV_IDE_RAPIDE is not set -# CONFIG_IDE_CHIPSETS is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=m -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set # # Acorn-specific block devices @@ -113,100 +129,6 @@ CONFIG_BLK_DEV_MFM_AUTODETECT=y # -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_ATOMWIDE_SERIAL is not set -# CONFIG_DUALSP_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set -# CONFIG_PRINTER is not set -# CONFIG_PPDEV is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set - -# -# PCMCIA character device support -# -# CONFIG_PCMCIA_SERIAL_CS is not set -# CONFIG_AGP is not set - -# -# Support for USB -# -# CONFIG_USB is not set - -# -# Console drivers -# -CONFIG_FB=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_ACORN=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_MFB=y -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -CONFIG_FONT_ACORN_8x8=y - -# # Networking options # # CONFIG_PACKET is not set @@ -218,16 +140,10 @@ # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -# CONFIG_SKB_LARGE is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -238,9 +154,9 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -253,16 +169,6 @@ # CONFIG_NET_SCHED is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -272,7 +178,9 @@ # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # @@ -286,19 +194,18 @@ # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_RTL8139 is not set -# CONFIG_DM9102 is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # -# CONFIG_YELLOWFIN is not set # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -312,7 +219,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -325,9 +232,62 @@ # CONFIG_WAN is not set # -# PCMCIA network device support +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes # -# CONFIG_NET_PCMCIA is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_IDE_ICSIDE=y +# CONFIG_BLK_DEV_IDEDMA_ICS is not set +# CONFIG_IDEDMA_ICS_AUTO is not set +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_BLK_DEV_IDE_RAPIDE is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # # SCSI support @@ -335,16 +295,90 @@ # CONFIG_SCSI is not set # -# Sound +# I2O device support # -# CONFIG_SOUND is not set +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_ATOMWIDE_SERIAL is not set +# CONFIG_DUALSP_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_PRINTER is not set +# CONFIG_PPDEV is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_CHARDEV=y + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +# CONFIG_PSMOUSE is not set +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set # -# Filesystems +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y CONFIG_ADFS_FS=y +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set @@ -353,37 +387,60 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set CONFIG_ACORN_PARTITION=y CONFIG_ACORN_PARTITION_ADFS=y CONFIG_ACORN_PARTITION_ICS=y @@ -394,6 +451,7 @@ # # Native Language Support # +CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -410,6 +468,10 @@ # CONFIG_NLS_CODEPAGE_866 is not set # CONFIG_NLS_CODEPAGE_869 is not set # CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -422,6 +484,45 @@ # CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_ACORN=y +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/assabet linux/arch/arm/def-configs/assabet --- v2.4.0-test11/linux/arch/arm/def-configs/assabet Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/def-configs/assabet Mon Nov 27 17:07:59 2000 @@ -12,57 +12,75 @@ # CONFIG_OBSOLETE is not set # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# # System Type # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_RPC is not set CONFIG_ARCH_SA1100=y # +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# # SA11x0 Implementations # CONFIG_SA1100_ASSABET=y # CONFIG_ASSABET_NEPONSET is not set # CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set # CONFIG_SA1100_BITSY is not set # CONFIG_SA1100_LART is not set -# CONFIG_SA1100_THINCLIENT is not set # CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_NANOENGINE is not set # CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_SA1100_PANGOLIN is not set CONFIG_ANGELBOOT=y -# CONFIG_SA1100_FREQUENCY_SCALE is not set +CONFIG_SA1100_FREQUENCY_SCALE=y # CONFIG_SA1100_VOLTAGE_SCALE is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_SA1100=y # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set -CONFIG_DISCONTIGMEM=y -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set # -# Loadable module support +# Processor Type # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +CONFIG_DISCONTIGMEM=y # # General setup # +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_PC_KEYMAP=y CONFIG_HOTPLUG=y # -# PC Card support +# PCMCIA/CardBus support # CONFIG_PCMCIA=y # CONFIG_PCMCIA_DEBUG is not set @@ -135,16 +153,10 @@ # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -181,13 +193,13 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set @@ -320,13 +332,14 @@ # CONFIG_VT=y # CONFIG_VT_CONSOLE is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -# CONFIG_TOUCHSCREEN_SA1100 is not set -# CONFIG_TOUCHSCREEN_BITSY is not set # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set # CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=9600 +CONFIG_TOUCHSCREEN_UCB1200=y +# CONFIG_TOUCHSCREEN_BITSY is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=32 @@ -345,6 +358,10 @@ # Joysticks # # CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# # CONFIG_QIC02_TAPE is not set # @@ -354,11 +371,6 @@ # CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -367,10 +379,9 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_AGP is not set # CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_PCMCIA_SERIAL is not set -# CONFIG_AGP is not set # # File systems @@ -451,12 +462,14 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -473,6 +486,10 @@ # CONFIG_NLS_CODEPAGE_866 is not set # CONFIG_NLS_CODEPAGE_869 is not set # CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -485,6 +502,7 @@ # CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set # CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_UTF8 is not set # # Console drivers @@ -497,7 +515,9 @@ # CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_CYBER2000 is not set CONFIG_FB_SA1100=y +# CONFIG_FB_MQ200 is not set # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set CONFIG_FBCON_CFB2=y @@ -517,8 +537,10 @@ # CONFIG_SOUND=y CONFIG_SOUND_UDA1341=y +# CONFIG_SOUND_SA1100_SSP is not set # CONFIG_SOUND_CMPCI is not set # CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set # CONFIG_SOUND_ES1370 is not set # CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ESSSOLO1 is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/brutus linux/arch/arm/def-configs/brutus --- v2.4.0-test11/linux/arch/arm/def-configs/brutus Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/def-configs/brutus Mon Nov 27 17:07:59 2000 @@ -12,10 +12,17 @@ # CONFIG_OBSOLETE is not set # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# # System Type # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -27,33 +34,30 @@ # # CONFIG_SA1100_ASSABET is not set CONFIG_SA1100_BRUTUS=y +# CONFIG_SA1100_CERF is not set # CONFIG_SA1100_BITSY is not set # CONFIG_SA1100_LART is not set # CONFIG_SA1100_THINCLIENT is not set # CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_NANOENGINE is not set # CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set CONFIG_ANGELBOOT=y # CONFIG_SA1100_FREQUENCY_SCALE is not set # CONFIG_SA1100_VOLTAGE_SCALE is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_SA1100=y # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y CONFIG_DISCONTIGMEM=y # CONFIG_PCI is not set # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +CONFIG_PC_KEYMAP=y # # General setup @@ -147,7 +151,7 @@ # CONFIG_VT_CONSOLE is not set CONFIG_SERIAL_SA1100=y CONFIG_SERIAL_SA1100_CONSOLE=y -# CONFIG_TOUCHSCREEN_SA1100 is not set +# CONFIG_TOUCHSCREEN_UCB1200 is not set # CONFIG_TOUCHSCREEN_BITSY is not set # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set @@ -192,9 +196,8 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set +# CONFIG_DRM is not set # # File systems @@ -256,6 +259,7 @@ # CONFIG_FB=y CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_CYBER2000 is not set CONFIG_FB_SA1100=y # CONFIG_FB_VIRTUAL is not set # CONFIG_FBCON_ADVANCED is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/cerf linux/arch/arm/def-configs/cerf --- v2.4.0-test11/linux/arch/arm/def-configs/cerf Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/def-configs/cerf Mon Nov 27 17:07:59 2000 @@ -21,8 +21,8 @@ # # System Type # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_FOOTBRIDGE is not set @@ -35,34 +35,39 @@ # CONFIG_SA1100_ASSABET is not set # CONFIG_SA1100_BRUTUS is not set CONFIG_SA1100_CERF=y +CONFIG_SA1100_CERF_32MB=y # CONFIG_SA1100_BITSY is not set # CONFIG_SA1100_LART is not set # CONFIG_SA1100_THINCLIENT is not set # CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_NANOENGINE is not set # CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_XP860 is not set # CONFIG_ANGELBOOT is not set # CONFIG_SA1100_FREQUENCY_SCALE is not set # CONFIG_SA1100_VOLTAGE_SCALE is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_SA1100=y # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y CONFIG_DISCONTIGMEM=y # CONFIG_PCI is not set # CONFIG_ISA is not set # CONFIG_ISA_DMA is not set +CONFIG_PC_KEYMAP=y # # General setup # +# CONFIG_SA1100_CERF_CMDLINE is not set CONFIG_HOTPLUG=y # -# PC Card support +# PCMCIA/CardBus support # CONFIG_PCMCIA=y # CONFIG_PCMCIA_DEBUG is not set @@ -70,7 +75,7 @@ CONFIG_VIRTUAL_BUS=y CONFIG_NET=y CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y CONFIG_NWFPE=y CONFIG_KCORE_ELF=y @@ -80,7 +85,7 @@ # CONFIG_BINFMT_MISC is not set # CONFIG_PM is not set # CONFIG_ARTHUR is not set -CONFIG_CMDLINE="keepinitrd" +CONFIG_CMDLINE="console=ttyS0,38400" CONFIG_LEDS=y CONFIG_LEDS_TIMER=y CONFIG_LEDS_CPU=y @@ -126,7 +131,9 @@ CONFIG_INET=y # CONFIG_IP_MULTICAST is not set # CONFIG_IP_ADVANCED_ROUTER is not set -# CONFIG_IP_PNP is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set # CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set @@ -282,10 +289,11 @@ # # Character devices # -# CONFIG_VT is not set +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set CONFIG_SERIAL_SA1100=y CONFIG_SERIAL_SA1100_CONSOLE=y -# CONFIG_TOUCHSCREEN_UCB1200 is not set +CONFIG_TOUCHSCREEN_UCB1200=y # CONFIG_TOUCHSCREEN_BITSY is not set # CONFIG_SERIAL is not set # CONFIG_SERIAL_EXTENDED is not set @@ -329,9 +337,9 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_PCMCIA_SERIAL is not set -# CONFIG_AGP is not set # # File systems @@ -345,6 +353,7 @@ # CONFIG_BFS_FS is not set # CONFIG_FAT_FS is not set # CONFIG_EFS_FS is not set +CONFIG_JFFS_FS_VERBOSE=0 # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set @@ -367,6 +376,7 @@ # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set # CONFIG_NFSD is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y @@ -376,36 +386,37 @@ # # Partition Types # -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set +# CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set # +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_SA1100=y +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +# CONFIG_FBCON_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# # Sound # -CONFIG_SOUND=y -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND is not set # # USB support diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/ebsa110 linux/arch/arm/def-configs/ebsa110 --- v2.4.0-test11/linux/arch/arm/def-configs/ebsa110 Mon Jun 19 17:59:33 2000 +++ linux/arch/arm/def-configs/ebsa110 Mon Nov 27 17:07:59 2000 @@ -1,53 +1,79 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # CONFIG_ARM=y +# CONFIG_EISA is not set # CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_UID16=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y # # System Type # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set # CONFIG_ARCH_CO285 is not set CONFIG_ARCH_EBSA110=y # CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_SA110=y +# CONFIG_ARCH_CLPS711X is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# + +# +# CLPS711X/EP721X Implementations +# # CONFIG_ARCH_ACORN is not set # CONFIG_FOOTBRIDGE is not set # CONFIG_FOOTBRIDGE_HOST is not set # CONFIG_FOOTBRIDGE_ADDIN is not set -# CONFIG_DISCONTIGMEM is not set -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set # -# Loadable module support +# Processor Type # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +CONFIG_CPU_32v4=y +CONFIG_CPU_SA110=y +# CONFIG_DISCONTIGMEM is not set # # General setup # +# CONFIG_ANGELBOOT is not set +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set # CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set CONFIG_NET=y CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_BSD_PROCESS_ACCT=y CONFIG_SYSCTL=y # CONFIG_NWFPE is not set CONFIG_KCORE_ELF=y @@ -55,6 +81,7 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set # CONFIG_ARTHUR is not set CONFIG_CMDLINE="root=/dev/nfs rw mem=16M console=ttyS1,38400n8" CONFIG_LEDS=y @@ -66,7 +93,7 @@ CONFIG_PARPORT=y CONFIG_PARPORT_PC=y CONFIG_PARPORT_PC_FIFO=y -CONFIG_PARPORT_PC_SUPERIO=y +# CONFIG_PARPORT_PC_SUPERIO is not set # CONFIG_PARPORT_ARC is not set # CONFIG_PARPORT_AMIGA is not set # CONFIG_PARPORT_MFC3 is not set @@ -76,6 +103,11 @@ CONFIG_PARPORT_1284=y # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Plug and Play configuration # # CONFIG_PNP is not set @@ -88,15 +120,12 @@ # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 # CONFIG_BLK_DEV_INITRD is not set # @@ -126,14 +155,12 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_IP_MROUTE is not set -CONFIG_IP_ALIAS=y # CONFIG_ARPD is not set +# CONFIG_INET_ECN is not set CONFIG_SYN_COOKIES=y -# CONFIG_SKB_LARGE is not set # # IP: Netfilter Configuration @@ -164,9 +191,25 @@ CONFIG_IP_NF_COMPAT_IPCHAINS=m CONFIG_IP_NF_NAT_NEEDED=y # CONFIG_IP_NF_COMPAT_IPFWADM is not set -# CONFIG_IPV6 is not set +CONFIG_IPV6=m +CONFIG_IPV6_EUI64=y +# CONFIG_IPV6_NO_PB is not set + +# +# IPv6: Netfilter Configuration +# +CONFIG_IP6_NF_IPTABLES=m +CONFIG_IP6_NF_MATCH_LIMIT=m +CONFIG_IP6_NF_MATCH_MARK=m +CONFIG_IP6_NF_FILTER=m +CONFIG_IP6_NF_MANGLE=m +CONFIG_IP6_NF_TARGET_MARK=m # CONFIG_KHTTPD is not set # CONFIG_ATM is not set + +# +# +# # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set @@ -174,6 +217,7 @@ # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set @@ -196,6 +240,7 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_ETHERTAP is not set # CONFIG_NET_SB1000 is not set @@ -217,8 +262,9 @@ # # Ethernet (1000 Mbit) # -# CONFIG_YELLOWFIN is not set # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -287,6 +333,11 @@ # CONFIG_ISDN is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# # Character devices # # CONFIG_VT is not set @@ -299,7 +350,8 @@ # CONFIG_SERIAL_MULTIPORT is not set # CONFIG_HUB6 is not set # CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 CONFIG_PRINTER=m # CONFIG_LP_CONSOLE is not set # CONFIG_PPDEV is not set @@ -319,6 +371,10 @@ # Joysticks # # CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# # CONFIG_QIC02_TAPE is not set # @@ -326,19 +382,17 @@ # CONFIG_WATCHDOG=y # CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_SOFT_WATCHDOG=y # CONFIG_WDT is not set # CONFIG_WDTPCI is not set -CONFIG_SOFT_WATCHDOG=y # CONFIG_PCWATCHDOG is not set # CONFIG_ACQUIRE_WDT is not set +# CONFIG_60XX_WDT is not set # CONFIG_MIXCOMWD is not set +# CONFIG_I810_TCO is not set +# CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -347,9 +401,13 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set # CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set # # File systems @@ -367,6 +425,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set # CONFIG_ISO9660_FS is not set @@ -400,7 +459,6 @@ CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set -# CONFIG_NFSD_TCP is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set @@ -427,6 +485,7 @@ # CONFIG_MAC_PARTITION is not set # CONFIG_MSDOS_PARTITION is not set # CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set # CONFIG_NLS is not set @@ -438,7 +497,7 @@ # # Kernel hacking # -# CONFIG_FRAME_POINTER is not set +CONFIG_FRAME_POINTER=y CONFIG_DEBUG_ERRORS=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_INFO is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge --- v2.4.0-test11/linux/arch/arm/def-configs/footbridge Mon Jun 19 17:59:33 2000 +++ linux/arch/arm/def-configs/footbridge Mon Nov 27 17:07:59 2000 @@ -2,54 +2,82 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_UID16=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set # -# System and Processor Type +# Loadable module support # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -# CONFIG_ARCH_RPC is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -CONFIG_FOOTBRIDGE=y -CONFIG_HOST_FOOTBRIDGE=y -# CONFIG_ADDIN_FOOTBRIDGE is not set +CONFIG_ARCH_FOOTBRIDGE=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_CLPS711X is not set + +# +# Archimedes/A5000 Implementations +# # # Footbridge Implementations # -CONFIG_ARCH_EBSA285=y # CONFIG_ARCH_CATS is not set -CONFIG_ARCH_NETWINDER=y # CONFIG_ARCH_PERSONAL_SERVER is not set +# CONFIG_ARCH_EBSA285_ADDIN is not set +CONFIG_ARCH_EBSA285_HOST=y +CONFIG_ARCH_NETWINDER=y + +# +# SA11x0 Implementations +# + +# +# CLPS711X/EP721X Implementations +# # CONFIG_ARCH_ACORN is not set +CONFIG_FOOTBRIDGE=y +CONFIG_FOOTBRIDGE_HOST=y +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_ARCH_EBSA285=y CONFIG_CPU_32=y # CONFIG_CPU_26 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_SA110=y -CONFIG_PCI=y -CONFIG_PCI_NAMES=y -CONFIG_ISA=y -CONFIG_ISA_DMA=y -# CONFIG_SBUS is not set -# CONFIG_PCMCIA is not set -CONFIG_ALIGNMENT_TRAP=y # -# Loadable module support +# Processor Type # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +CONFIG_CPU_32v4=y +CONFIG_CPU_SA110=y +# CONFIG_DISCONTIGMEM is not set # # General setup # +# CONFIG_ANGELBOOT is not set +CONFIG_PCI=y +CONFIG_ISA=y +CONFIG_ISA_DMA=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_NET=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y @@ -60,7 +88,12 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set # CONFIG_ARTHUR is not set +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +# CONFIG_LEDS_CPU is not set +CONFIG_ALIGNMENT_TRAP=y # # Parallel port support @@ -76,25 +109,11 @@ # CONFIG_PARPORT_SUNBPP is not set # CONFIG_PARPORT_OTHER is not set CONFIG_PARPORT_1284=y -CONFIG_CMDLINE="root=/dev/hda1 ro mem=32M parport=0x378,7 ide0=autotune" -CONFIG_LEDS=y -CONFIG_LEDS_TIMER=y -# CONFIG_LEDS_CPU is not set # -# IEEE 1394 (FireWire) support +# Memory Technology Devices (MTD) # -# CONFIG_IEEE1394 is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +# CONFIG_MTD is not set # # Plug and Play configuration @@ -137,185 +156,13 @@ CONFIG_PARIDE_ON20=m CONFIG_PARIDE_ON26=m # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set CONFIG_BLK_DEV_RAM=y -# CONFIG_BLK_DEV_INITRD is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y -# CONFIG_SERIAL_EXTENDED is not set -CONFIG_SERIAL_NONSTANDARD=y -# CONFIG_COMPUTONE is not set -# CONFIG_ROCKETPORT is not set -# CONFIG_CYCLADES is not set -CONFIG_SERIAL_21285=y -CONFIG_SERIAL_21285_CONSOLE=y -# CONFIG_DIGIEPCA is not set -# CONFIG_DIGI is not set -# CONFIG_ESPSERIAL is not set -# CONFIG_MOXA_INTELLIO is not set -# CONFIG_MOXA_SMARTIO is not set -# CONFIG_ISI is not set -# CONFIG_SYNCLINK is not set -# CONFIG_N_HDLC is not set -# CONFIG_RISCOM8 is not set -# CONFIG_SPECIALIX is not set -# CONFIG_SX is not set -# CONFIG_STALDRV is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=256 -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -CONFIG_I2C=m -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_CHARDEV is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -CONFIG_MOUSE=y -CONFIG_PSMOUSE=y -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set -# CONFIG_WDT is not set -# CONFIG_WDTPCI is not set -CONFIG_SOFT_WATCHDOG=y -# CONFIG_PCWATCHDOG is not set -# CONFIG_ACQUIRE_WDT is not set -# CONFIG_MIXCOMWD is not set -CONFIG_21285_WATCHDOG=m -CONFIG_977_WATCHDOG=m -CONFIG_DS1620=y -CONFIG_NWBUTTON=y -CONFIG_NWBUTTON_REBOOT=y -CONFIG_NWFLASH=m -CONFIG_NVRAM=m -CONFIG_RTC=y - -# -# Video For Linux -# -CONFIG_VIDEO_DEV=y -# CONFIG_I2C_PARPORT is not set - -# -# Radio Adapters -# -# CONFIG_RADIO_CADET is not set -# CONFIG_RADIO_RTRACK is not set -# CONFIG_RADIO_RTRACK2 is not set -# CONFIG_RADIO_AZTECH is not set -# CONFIG_RADIO_GEMTEK is not set -# CONFIG_RADIO_MIROPCM20 is not set -# CONFIG_RADIO_SF16FMI is not set -# CONFIG_RADIO_TERRATEC is not set -# CONFIG_RADIO_TRUST is not set -# CONFIG_RADIO_TYPHOON is not set -# CONFIG_RADIO_ZOLTRIX is not set - -# -# Video Adapters -# -# CONFIG_VIDEO_PMS is not set -# CONFIG_VIDEO_BWQCAM is not set -# CONFIG_VIDEO_CQCAM is not set -# CONFIG_VIDEO_CPIA is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_TUNER_3036 is not set -# CONFIG_VIDEO_STRADIS is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_BUZ is not set -# CONFIG_VIDEO_ZR36120 is not set -CONFIG_VIDEO_CYBERPRO=m -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_AGP is not set - -# -# Console drivers -# -CONFIG_VGA_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_CYBER2000=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -# CONFIG_FBCON_MFB is not set -# CONFIG_FBCON_CFB2 is not set -# CONFIG_FBCON_CFB4 is not set -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -# CONFIG_FBCON_CFB32 is not set -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -CONFIG_FBCON_VGA=y -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -CONFIG_FONT_ACORN_8x8=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y # # Networking options @@ -327,24 +174,21 @@ # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -CONFIG_IP_ALIAS=y +# CONFIG_IP_MROUTE is not set +# CONFIG_INET_ECN is not set CONFIG_SYN_COOKIES=y - -# -# (it is safe to leave these untouched) -# -# CONFIG_SKB_LARGE is not set # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set -# CONFIG_ATM is not set +CONFIG_ATM=y +# CONFIG_ATM_CLIP is not set +# CONFIG_ATM_LANE is not set # # @@ -352,10 +196,11 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set @@ -367,55 +212,6 @@ # CONFIG_NET_SCHED is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -CONFIG_IRDA=m - -# -# IrDA protocols -# -CONFIG_IRLAN=m -CONFIG_IRCOMM=m -CONFIG_IRDA_ULTRA=y -CONFIG_IRDA_OPTIONS=y - -# -# IrDA options -# -CONFIG_IRDA_CACHE_LAST_LSAP=y -CONFIG_IRDA_FAST_RR=y -# CONFIG_IRDA_DEBUG is not set -# CONFIG_IRDA_COMPRESSION is not set - -# -# Infrared-port device drivers -# - -# -# SIR device drivers -# -# CONFIG_IRTTY_SIR is not set -# CONFIG_IRPORT_SIR is not set - -# -# FIR device drivers -# -# CONFIG_NSC_FIR is not set -CONFIG_WINBOND_FIR=m -# CONFIG_TOSHIBA_FIR is not set -# CONFIG_SMC_IRCC_FIR is not set - -# -# Dongle support -# -# CONFIG_DONGLE is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -427,13 +223,13 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set CONFIG_NET_VENDOR_3COM=y # CONFIG_EL1 is not set # CONFIG_EL2 is not set @@ -441,12 +237,15 @@ # CONFIG_EL16 is not set # CONFIG_EL3 is not set # CONFIG_3C515 is not set +# CONFIG_ELMC is not set +# CONFIG_ELMC_II is not set CONFIG_VORTEX=y # CONFIG_LANCE is not set # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set +# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set @@ -454,28 +253,34 @@ # CONFIG_AC3200 is not set # CONFIG_APRICOT is not set # CONFIG_CS89x0 is not set -# CONFIG_DE4X5 is not set CONFIG_TULIP=m +# CONFIG_DE4X5 is not set # CONFIG_DGRS is not set # CONFIG_DM9102 is not set # CONFIG_EEPRO100 is not set +# CONFIG_EEPRO100_PM is not set # CONFIG_LNE390 is not set -# CONFIG_NE3210 is not set +# CONFIG_NATSEMI is not set CONFIG_NE2K_PCI=y -# CONFIG_RTL8129 is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set # CONFIG_8139TOO is not set +# CONFIG_RTL8129 is not set # CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set # CONFIG_TLAN is not set # CONFIG_VIA_RHINE is not set -# CONFIG_ES3210 is not set -# CONFIG_EPIC100 is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_HAPPYMEAL is not set # CONFIG_NET_POCKET is not set # # Ethernet (1000 Mbit) # -# CONFIG_YELLOWFIN is not set # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -498,138 +303,306 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +CONFIG_IRDA=m + +# +# IrDA protocols +# +CONFIG_IRLAN=m +CONFIG_IRNET=m +CONFIG_IRCOMM=m +CONFIG_IRDA_ULTRA=y +CONFIG_IRDA_OPTIONS=y + +# +# IrDA options +# +CONFIG_IRDA_CACHE_LAST_LSAP=y +CONFIG_IRDA_FAST_RR=y +CONFIG_IRDA_DEBUG=y + +# +# Infrared-port device drivers +# + +# +# SIR device drivers +# +# CONFIG_IRTTY_SIR is not set +# CONFIG_IRPORT_SIR is not set + +# +# FIR device drivers +# +# CONFIG_NSC_FIR is not set +CONFIG_WINBOND_FIR=m +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_SMC_IRCC_FIR is not set + +# +# Dongle support +# +# CONFIG_DONGLE is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_BLK_DEV_RZ1000 is not set +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +CONFIG_BLK_DEV_OFFBOARD=y +CONFIG_IDEDMA_PCI_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD7409 is not set +# CONFIG_AMD7409_OVERRIDE is not set +# CONFIG_BLK_DEV_CMD64X is not set +CONFIG_BLK_DEV_CY82C693=y +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +CONFIG_BLK_DEV_PDC202XX=y +# CONFIG_PDC202XX_BURST is not set +# CONFIG_BLK_DEV_OSB4 is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_SL82C105=y +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +# CONFIG_SERIAL_EXTENDED is not set +CONFIG_SERIAL_NONSTANDARD=y +# CONFIG_COMPUTONE is not set +# CONFIG_ROCKETPORT is not set +# CONFIG_CYCLADES is not set +# CONFIG_DIGIEPCA is not set +# CONFIG_DIGI is not set +# CONFIG_ESPSERIAL is not set +# CONFIG_MOXA_INTELLIO is not set +# CONFIG_MOXA_SMARTIO is not set +# CONFIG_ISI is not set +# CONFIG_SYNCLINK is not set +# CONFIG_N_HDLC is not set +# CONFIG_RISCOM8 is not set +# CONFIG_SPECIALIX is not set +# CONFIG_SX is not set +# CONFIG_RIO is not set +# CONFIG_STALDRV is not set +CONFIG_SERIAL_21285=y +CONFIG_SERIAL_21285_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set + +# +# I2C support +# +CONFIG_I2C=m +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_CHARDEV is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks # -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set +# CONFIG_JOYSTICK is not set # -# Wan interfaces +# Input core support is needed for joysticks # -# CONFIG_WAN is not set +# CONFIG_QIC02_TAPE is not set # -# ATA/IDE/MFM/RLL support +# Watchdog Cards # -CONFIG_IDE=y +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set +CONFIG_SOFT_WATCHDOG=y +# CONFIG_WDT is not set +# CONFIG_WDTPCI is not set +# CONFIG_PCWATCHDOG is not set +# CONFIG_ACQUIRE_WDT is not set +# CONFIG_60XX_WDT is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_I810_TCO is not set +CONFIG_21285_WATCHDOG=m +CONFIG_977_WATCHDOG=m +CONFIG_DS1620=y +CONFIG_NWBUTTON=y +CONFIG_NWBUTTON_REBOOT=y +CONFIG_NWFLASH=m +# CONFIG_INTEL_RNG is not set +CONFIG_NVRAM=m +CONFIG_RTC=y +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set # -# IDE, ATA and ATAPI Block devices +# Ftape, the floppy tape device driver # -CONFIG_BLK_DEV_IDE=y +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set # -# Please see Documentation/ide.txt for help/info on IDE drives +# Multimedia devices # -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_IDEDISK_MULTI_MODE=y -# CONFIG_BLK_DEV_IDECS is not set -# CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set -# CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set +CONFIG_VIDEO_DEV=m # -# IDE chipset support/bugfixes +# Video For Linux # -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_BLK_DEV_RZ1000 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_IDEPCI_SHARE_IRQ=y -CONFIG_BLK_DEV_IDEDMA_PCI=y -CONFIG_BLK_DEV_OFFBOARD=y -CONFIG_IDEDMA_PCI_AUTO=y -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_PCI_EXPERIMENTAL=y -# CONFIG_IDEDMA_PCI_WIP is not set -# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set -# CONFIG_BLK_DEV_AEC62XX is not set -# CONFIG_AEC62XX_TUNING is not set -# CONFIG_BLK_DEV_ALI15X3 is not set -# CONFIG_WDC_ALI15X3 is not set -# CONFIG_BLK_DEV_AMD7409 is not set -# CONFIG_AMD7409_OVERRIDE is not set -# CONFIG_BLK_DEV_CMD64X is not set -# CONFIG_CMD64X_RAID is not set -CONFIG_BLK_DEV_CY82C693=y -# CONFIG_BLK_DEV_CS5530 is not set -# CONFIG_BLK_DEV_HPT34X is not set -# CONFIG_HPT34X_AUTODMA is not set -# CONFIG_BLK_DEV_HPT366 is not set -# CONFIG_HPT366_FIP is not set -# CONFIG_HPT366_MODE3 is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_OPTI621 is not set -CONFIG_BLK_DEV_PDC202XX=y -# CONFIG_PDC202XX_BURST is not set -# CONFIG_PDC202XX_MASTER is not set -# CONFIG_BLK_DEV_SIS5513 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_VIA82CXXX_TUNING is not set -CONFIG_BLK_DEV_SL82C105=y -# CONFIG_IDE_CHIPSETS is not set -CONFIG_IDEDMA_AUTO=y -CONFIG_BLK_DEV_IDE_MODES=y +CONFIG_VIDEO_PROC_FS=y +# CONFIG_I2C_PARPORT is not set # -# SCSI support +# Video Adapters # -# CONFIG_SCSI is not set +# CONFIG_VIDEO_PMS is not set +# CONFIG_VIDEO_BWQCAM is not set +# CONFIG_VIDEO_CQCAM is not set +# CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_TUNER_3036 is not set +# CONFIG_VIDEO_STRADIS is not set +# CONFIG_VIDEO_ZORAN is not set +# CONFIG_VIDEO_BUZ is not set +# CONFIG_VIDEO_ZR36120 is not set +CONFIG_VIDEO_CYBERPRO=m # -# Sound +# Radio Adapters # -CONFIG_SOUND=m -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -CONFIG_SOUND_ADLIB=m -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -# CONFIG_SOUND_SOFTOSS is not set -CONFIG_SOUND_SB=m -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -# CONFIG_SOUND_VIDC is not set -CONFIG_SOUND_WAVEARTIST=m +# CONFIG_RADIO_CADET is not set +# CONFIG_RADIO_RTRACK is not set +# CONFIG_RADIO_RTRACK2 is not set +# CONFIG_RADIO_AZTECH is not set +# CONFIG_RADIO_GEMTEK is not set +# CONFIG_RADIO_MAESTRO is not set +# CONFIG_RADIO_MIROPCM20 is not set +# CONFIG_RADIO_SF16FMI is not set +# CONFIG_RADIO_TERRATEC is not set +# CONFIG_RADIO_TRUST is not set +# CONFIG_RADIO_TYPHOON is not set +# CONFIG_RADIO_ZOLTRIX is not set # # File systems @@ -647,6 +620,7 @@ # CONFIG_UMSDOS_FS is not set CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=m @@ -713,12 +687,14 @@ # CONFIG_SOLARIS_X86_PARTITION is not set # CONFIG_UNIXWARE_DISKLABEL is not set # CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set @@ -735,6 +711,10 @@ # CONFIG_NLS_CODEPAGE_866 is not set # CONFIG_NLS_CODEPAGE_869 is not set # CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m # CONFIG_NLS_ISO8859_3 is not set @@ -747,6 +727,110 @@ # CONFIG_NLS_ISO8859_14 is not set CONFIG_NLS_ISO8859_15=m # CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_PC_KEYB=y +CONFIG_PC_KEYMAP=y +CONFIG_VGA_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_ACORN is not set +# CONFIG_FB_CLPS711X is not set +CONFIG_FB_CYBER2000=y +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +# CONFIG_FBCON_MFB is not set +# CONFIG_FBCON_CFB2 is not set +# CONFIG_FBCON_CFB4 is not set +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +# CONFIG_FBCON_CFB32 is not set +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set +CONFIG_FBCON_VGA=y +# CONFIG_FBCON_HGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Sound +# +CONFIG_SOUND=m +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +CONFIG_SOUND_ADLIB=m +# CONFIG_SOUND_ACI_MIXER is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set +# CONFIG_SOUND_PSS is not set +CONFIG_SOUND_SB=m +# CONFIG_SOUND_AWE32_SYNTH is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_YMPCI is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set +CONFIG_SOUND_WAVEARTIST=m +# CONFIG_SOUND_TVMIXER is not set # # USB support @@ -757,7 +841,8 @@ # # Miscellaneous USB options # -# CONFIG_USB_DEVICEFS is not set +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set # # USB Controllers @@ -770,7 +855,8 @@ # USB Devices # CONFIG_USB_PRINTER=m -CONFIG_USB_SCANNER=m +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set CONFIG_USB_AUDIO=m # CONFIG_USB_ACM is not set # CONFIG_USB_SERIAL is not set @@ -785,19 +871,16 @@ # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_DSBR is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_NET1080 is not set + +# +# USB Human Interface Devices (HID) +# # -# USB HID +# Input core support is needed for USB HID # -# CONFIG_USB_HID is not set -CONFIG_USB_KBD=m -CONFIG_USB_MOUSE=m -# CONFIG_USB_WACOM is not set -# CONFIG_USB_WMFORCE is not set -# CONFIG_INPUT_KEYBDEV is not set -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/graphicsclient linux/arch/arm/def-configs/graphicsclient --- v2.4.0-test11/linux/arch/arm/def-configs/graphicsclient Mon Jun 19 17:59:33 2000 +++ linux/arch/arm/def-configs/graphicsclient Mon Nov 27 17:07:59 2000 @@ -2,48 +2,88 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +# CONFIG_SBUS is not set +CONFIG_UID16=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set # -# System and processor type +# Loadable module support # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -# CONFIG_ARCH_RPC is not set +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# System Type +# +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_FOOTBRIDGE is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_RPC is not set CONFIG_ARCH_SA1100=y + +# +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set # CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_EMPEG is not set -# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_BITSY is not set # CONFIG_SA1100_LART is not set -# CONFIG_SA1100_PLEB is not set CONFIG_SA1100_GRAPHICSCLIENT=y +# CONFIG_SA1100_NANOENGINE is not set # CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_TIFON is not set -CONFIG_DISCONTIGMEM=y +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_XP860 is not set +# CONFIG_ANGELBOOT is not set +# CONFIG_SA1100_FREQUENCY_SCALE is not set +# CONFIG_SA1100_VOLTAGE_SCALE is not set # CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set + +# +# Processor Type +# CONFIG_CPU_32v4=y CONFIG_CPU_SA1100=y -# CONFIG_ISA_DMA is not set -CONFIG_ALIGNMENT_TRAP=y +CONFIG_DISCONTIGMEM=y # -# Loadable module support +# General setup # -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_PC_KEYMAP=y +CONFIG_HOTPLUG=y # -# General setup +# PCMCIA/CardBus support # +CONFIG_PCMCIA=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_SA1100_PCMCIA=y +CONFIG_VIRTUAL_BUS=y CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -51,22 +91,24 @@ CONFIG_NWFPE=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y +# CONFIG_BINFMT_AOUT is not set CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set # CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=nfs" +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# # CONFIG_PARPORT is not set -CONFIG_CMDLINE="ip=off" # -# I2O device support +# Memory Technology Devices (MTD) # -# CONFIG_I2O is not set -# CONFIG_I2O_PCI is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +# CONFIG_MTD is not set # # Plug and Play configuration @@ -78,118 +120,28 @@ # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_IDE is not set - -# -# Please see Documentation/ide.txt for help/info on IDE drives -# -# CONFIG_BLK_DEV_HD_ONLY is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set # CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_BLK_DEV_INITRD=y -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set - -# -# PCMCIA character device support -# -# CONFIG_AGP is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Console drivers -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_FB=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_SA1100=y -# CONFIG_FB_MATROX is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_FONTWIDTH8_ONLY=y -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_BLK_DEV_FLASH is not set # # Networking options # -# CONFIG_PACKET is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK is not set # CONFIG_NETFILTER is not set # CONFIG_FILTER is not set @@ -200,16 +152,10 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -220,9 +166,9 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -235,16 +181,6 @@ # CONFIG_NET_SCHED is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -254,7 +190,9 @@ # # CONFIG_ARCNET is not set # CONFIG_DUMMY is not set +# CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # @@ -270,12 +208,10 @@ # CONFIG_ULTRA32 is not set CONFIG_SMC9194=y # CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_RTL8139 is not set -# CONFIG_DM9102 is not set # CONFIG_AT1700 is not set # CONFIG_DEPCA is not set # CONFIG_NET_ISA is not set -# CONFIG_NET_EISA is not set +# CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set # @@ -295,7 +231,7 @@ # CONFIG_NET_RADIO is not set # -# Token Ring driver support +# Token Ring devices # # CONFIG_TR is not set # CONFIG_NET_FC is not set @@ -310,7 +246,70 @@ # # PCMCIA network device support # -# CONFIG_NET_PCMCIA is not set +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=m +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=m + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=m + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=m +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=m +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set # # SCSI support @@ -318,54 +317,221 @@ # CONFIG_SCSI is not set # -# Filesystems +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=38400 +# CONFIG_TOUCHSCREEN_UCB1200 is not set +# CONFIG_TOUCHSCREEN_BITSY is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_PCMCIA_SERIAL is not set + +# +# File systems # # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set +CONFIG_FAT_FS=m +CONFIG_MSDOS_FS=m # CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set +CONFIG_VFAT_FS=m # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set +CONFIG_RAMFS=y # CONFIG_ISO9660_FS is not set # CONFIG_JOLIET is not set # CONFIG_MINIX_FS is not set # CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set # CONFIG_HPFS_FS is not set CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set CONFIG_DEVPTS_FS=y # CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set # CONFIG_ROMFS_FS is not set CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set # CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set # # Network File Systems # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_NLS is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# 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 +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_SA1100=y +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking @@ -373,6 +539,6 @@ CONFIG_FRAME_POINTER=y CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_USER=y -CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO is not set # CONFIG_MAGIC_SYSRQ is not set # CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/integrator linux/arch/arm/def-configs/integrator --- v2.4.0-test11/linux/arch/arm/def-configs/integrator Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/integrator Mon Nov 27 17:07:59 2000 @@ -0,0 +1,511 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# System Type +# +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +CONFIG_ARCH_INTEGRATOR=y +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_CLPS711X is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# + +# +# CLPS711X/EP721X Implementations +# +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set + +# +# Processor Type +# +CONFIG_CPU_32v4=y +CONFIG_CPU_ARM720=y +CONFIG_CPU_ARM920=y +CONFIG_CPU_ARM920_CPU_IDLE=y +CONFIG_CPU_ARM920_I_CACHE_ON=y +CONFIG_CPU_ARM920_D_CACHE_ON=y +# CONFIG_CPU_ARM920_WRITETHROUGH is not set +# CONFIG_DISCONTIGMEM is not set + +# +# General setup +# +# CONFIG_ANGELBOOT is not set +CONFIG_PCI_INTEGRATOR=y +CONFIG_PCI=y +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="root=1f04 mem=32M" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_MTDRAM is not set + +# +# MTD drivers for mapped chips +# +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +# CONFIG_MTD_CFI_AMDSTD is not set +# CONFIG_MTD_JEDEC is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_PHYSMAP is not set + +# +# Drivers for chip mappings +# +# CONFIG_MTD_MIXMEM is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_OCTAGON is not set +# CONFIG_MTD_PNC2000 is not set +# CONFIG_MTD_RPXLITE is not set +# CONFIG_MTD_VMAX is not set + +# +# User modules and translation layers for MTD devices +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +CONFIG_MTD_ARM=y + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_INITRD is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +CONFIG_TULIP=y +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=y +CONFIG_EEPRO100_PM=y +# CONFIG_LNE390 is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139TOO is not set +# CONFIG_RTL8129 is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/IDE/MFM/RLL support +# +# CONFIG_IDE is not set +# CONFIG_BLK_DEV_IDE_MODES is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_AMBA=y +CONFIG_SERIAL_INTEGRATOR=y +CONFIG_SERIAL_AMBA_CONSOLE=y +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +CONFIG_ROMFS_FS=y +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_KMI_KEYB=y +CONFIG_PC_KEYMAP=y +CONFIG_VGA_CONSOLE=y +# CONFIG_FB is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_LL=y diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/neponset linux/arch/arm/def-configs/neponset --- v2.4.0-test11/linux/arch/arm/def-configs/neponset Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/neponset Mon Nov 27 17:07:59 2000 @@ -0,0 +1,576 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# System Type +# +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_RPC is not set +CONFIG_ARCH_SA1100=y + +# +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# +CONFIG_SA1100_ASSABET=y +CONFIG_ASSABET_NEPONSET=y +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_BITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_XP860 is not set +CONFIG_ANGELBOOT=y +CONFIG_SA1111=y +CONFIG_SA1100_FREQUENCY_SCALE=y +# CONFIG_SA1100_VOLTAGE_SCALE is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set + +# +# Processor Type +# +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_PC_KEYMAP=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_SA1100_PCMCIA=y +CONFIG_VIRTUAL_BUS=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="keepinitrd" +CONFIG_LEDS=y +CONFIG_LEDS_TIMER=y +CONFIG_LEDS_CPU=y +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_FLASH is not set + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +CONFIG_NET_VENDOR_SMC=y +# CONFIG_WD80x3 is not set +# CONFIG_ULTRA is not set +# CONFIG_ULTRA32 is not set +CONFIG_SMC9194=y +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set +CONFIG_PCMCIA_NETCARD=y + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=9600 +CONFIG_TOUCHSCREEN_UCB1200=y +# CONFIG_TOUCHSCREEN_BITSY is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_PCMCIA_SERIAL is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +CONFIG_NLS_DEFAULT="iso8859-1" +CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# 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 +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_SA1100=y +# CONFIG_FB_MQ200 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_FBCON_ADVANCED is not set +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_FONTWIDTH8_ONLY=y +CONFIG_FBCON_FONTS=y +CONFIG_FONT_8x8=y +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set + +# +# Sound +# +CONFIG_SOUND=y +CONFIG_SOUND_UDA1341=y +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/pangolin linux/arch/arm/def-configs/pangolin --- v2.4.0-test11/linux/arch/arm/def-configs/pangolin Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/pangolin Mon Nov 27 17:07:59 2000 @@ -0,0 +1,491 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_ARM=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_RPC is not set +CONFIG_ARCH_SA1100=y + +# +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# +# CONFIG_SA1100_ASSABET is not set +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_CERF is not set +# CONFIG_SA1100_BITSY is not set +# CONFIG_SA1100_LART is not set +# CONFIG_SA1100_GRAPHICSCLIENT is not set +# CONFIG_SA1100_NANOENGINE is not set +# CONFIG_SA1100_VICTOR is not set +# CONFIG_SA1100_SHERMAN is not set +# CONFIG_SA1100_XP860 is not set +CONFIG_SA1100_PANGOLIN=y +# CONFIG_ANGELBOOT is not set +# CONFIG_SA1100_FREQUENCY_SCALE is not set +# CONFIG_SA1100_VOLTAGE_SCALE is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +CONFIG_CPU_32v4=y +CONFIG_CPU_SA1100=y +CONFIG_DISCONTIGMEM=y + +# +# General setup +# +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +CONFIG_PC_KEYMAP=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +# CONFIG_PCMCIA_DEBUG is not set +CONFIG_SA1100_PCMCIA=y +CONFIG_VIRTUAL_BUS=y +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_NWFPE=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set +# CONFIG_ARTHUR is not set +CONFIG_CMDLINE="keepinitrd" +# CONFIG_LEDS is not set +CONFIG_ALIGNMENT_TRAP=y + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Memory Technology Devices (MTD) +# +CONFIG_MTD=y +# CONFIG_MTD_DOC1000 is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOCPROBE is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_JEDEC is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_MIXMEM is not set +# CONFIG_MTD_NORA is not set +# CONFIG_MTD_OCTAGON is not set +# CONFIG_MTD_PNC2000 is not set +# CONFIG_MTD_RPXLITE is not set +# CONFIG_MTD_VMAX is not set +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set + +# +# Plug and Play configuration +# +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +CONFIG_BLK_DEV_FLASH=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=y +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_ARM_AM79C961A is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_NET_ISA is not set +# CONFIG_NET_PCI is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_YELLOWFIN is not set +# CONFIG_ACENIC is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_NET_PCMCIA_RADIO is not set +CONFIG_PCMCIA_NETCARD=y + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +CONFIG_BLK_DEV_IDECS=y +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +# CONFIG_IDE_CHIPSETS is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_IDE_MODES is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Character devices +# +CONFIG_VT=y +# CONFIG_VT_CONSOLE is not set +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +CONFIG_SA1100_DEFAULT_BAUDRATE=115200 +# CONFIG_TOUCHSCREEN_UCB1200 is not set +# CONFIG_TOUCHSCREEN_BITSY is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=32 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +# CONFIG_PCMCIA_SERIAL is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_JFFS_FS=y +CONFIG_JFFS_FS_VERBOSE=1 +CONFIG_CRAMFS=y +CONFIG_RAMFS=y +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Console drivers +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_FB is not set + +# +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/rpc linux/arch/arm/def-configs/rpc --- v2.4.0-test11/linux/arch/arm/def-configs/rpc Mon Jun 19 17:59:33 2000 +++ linux/arch/arm/def-configs/rpc Mon Nov 27 17:07:59 2000 @@ -2,45 +2,77 @@ # Automatically generated make config: don't edit # CONFIG_ARM=y +# CONFIG_EISA is not set +# CONFIG_SBUS is not set +# CONFIG_MCA is not set CONFIG_UID16=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +# CONFIG_OBSOLETE is not set # -# System and Processor Type +# Loadable module support # -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -CONFIG_ARCH_RPC=y +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# System Type +# +# CONFIG_ARCH_ARCA5K is not set +# CONFIG_ARCH_CLPS7500 is not set +# CONFIG_ARCH_CO285 is not set # CONFIG_ARCH_EBSA110 is not set -# CONFIG_FOOTBRIDGE is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_INTEGRATOR is not set +CONFIG_ARCH_RPC=y +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_CLPS711X is not set + +# +# Archimedes/A5000 Implementations +# + +# +# Footbridge Implementations +# + +# +# SA11x0 Implementations +# + +# +# CLPS711X/EP721X Implementations +# CONFIG_ARCH_ACORN=y +# CONFIG_FOOTBRIDGE is not set +# CONFIG_FOOTBRIDGE_HOST is not set +# CONFIG_FOOTBRIDGE_ADDIN is not set CONFIG_CPU_32=y # CONFIG_CPU_26 is not set + +# +# Processor Type +# CONFIG_CPU_32v3=y CONFIG_CPU_ARM6=y CONFIG_CPU_ARM7=y CONFIG_CPU_SA110=y -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_SBUS is not set -# CONFIG_PCMCIA is not set -# CONFIG_ALIGNMENT_TRAP is not set - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_DISCONTIGMEM is not set # # General setup # +# CONFIG_ANGELBOOT is not set +# CONFIG_PCI is not set +# CONFIG_ISA is not set +# CONFIG_ISA_DMA is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set @@ -51,7 +83,9 @@ CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PM is not set # CONFIG_ARTHUR is not set +# CONFIG_ALIGNMENT_TRAP is not set # # Parallel port support @@ -69,13 +103,9 @@ # CONFIG_PARPORT_1284 is not set # -# I2O device support +# Memory Technology Devices (MTD) # -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set +# CONFIG_MTD is not set # # Plug and Play configuration @@ -90,15 +120,12 @@ # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_RAID15_DANGEROUS is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y # @@ -106,114 +133,6 @@ # # -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_SERIAL=y -# CONFIG_SERIAL_CONSOLE is not set -CONFIG_ATOMWIDE_SERIAL=y -CONFIG_DUALSP_SERIAL=y -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_UNIX98_PTYS is not set -CONFIG_PRINTER=m -# CONFIG_LP_CONSOLE is not set -# CONFIG_PPDEV is not set - -# -# I2C support -# -CONFIG_I2C=y -CONFIG_I2C_ALGOBIT=y -# CONFIG_I2C_PHILIPSPAR is not set -# CONFIG_I2C_ELV is not set -# CONFIG_I2C_VELLEMAN is not set -# CONFIG_I2C_ALGOPCF is not set -CONFIG_I2C_CHARDEV=y - -# -# Mice -# -CONFIG_BUSMOUSE=y -# CONFIG_ATIXL_BUSMOUSE is not set -# CONFIG_LOGIBUSMOUSE is not set -# CONFIG_MS_BUSMOUSE is not set -CONFIG_MOUSE=y -# CONFIG_PSMOUSE is not set -# CONFIG_82C710_MOUSE is not set -# CONFIG_PC110_PAD is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_AGP is not set -CONFIG_RPCMOUSE=y - -# -# Console drivers -# -CONFIG_FB=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_ACORN=y -# CONFIG_FB_VIRTUAL is not set -CONFIG_FBCON_ADVANCED=y -CONFIG_FBCON_MFB=y -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_CFB16=y -CONFIG_FBCON_CFB24=y -CONFIG_FBCON_CFB32=y -# CONFIG_FBCON_AFB is not set -# CONFIG_FBCON_ILBM is not set -# CONFIG_FBCON_IPLAN2P2 is not set -# CONFIG_FBCON_IPLAN2P4 is not set -# CONFIG_FBCON_IPLAN2P8 is not set -# CONFIG_FBCON_MAC is not set -# CONFIG_FBCON_VGA_PLANES is not set -# CONFIG_FBCON_VGA is not set -# CONFIG_FBCON_HGA is not set -# CONFIG_FBCON_FONTWIDTH8_ONLY is not set -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set -# CONFIG_FONT_8x16 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_PEARL_8x8 is not set -CONFIG_FONT_ACORN_8x8=y - -# # Networking options # # CONFIG_PACKET is not set @@ -222,19 +141,14 @@ # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set +CONFIG_IP_MULTICAST=y # CONFIG_IP_ADVANCED_ROUTER is not set # CONFIG_IP_PNP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y # CONFIG_IPV6 is not set # CONFIG_KHTTPD is not set # CONFIG_ATM is not set @@ -245,10 +159,11 @@ # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set # CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_NET_FASTROUTE is not set @@ -260,16 +175,6 @@ # CONFIG_NET_SCHED is not set # -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# # Network device support # CONFIG_NETDEVICES=y @@ -281,14 +186,15 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y -CONFIG_ARM_ETHER1=m -CONFIG_ARM_ETHER3=m +CONFIG_ARM_ETHER1=y +CONFIG_ARM_ETHER3=y CONFIG_ARM_ETHERH=y # CONFIG_NET_VENDOR_3COM is not set # CONFIG_LANCE is not set @@ -303,8 +209,9 @@ # # Ethernet (1000 Mbit) # -# CONFIG_YELLOWFIN is not set # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -337,6 +244,16 @@ # CONFIG_WAN is not set # +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ATA/IDE/MFM/RLL support # CONFIG_IDE=y @@ -353,6 +270,15 @@ # CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set # CONFIG_BLK_DEV_IDECS is not set CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set @@ -372,6 +298,8 @@ CONFIG_BLK_DEV_IDE_RAPIDE=y # CONFIG_IDE_CHIPSETS is not set CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set # CONFIG_BLK_DEV_IDE_MODES is not set # @@ -427,14 +355,14 @@ # CONFIG_SCSI_IZIP_EPP16 is not set # CONFIG_SCSI_IZIP_SLOW_CTR is not set # CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_PAS16 is not set # CONFIG_SCSI_PCI2000 is not set # CONFIG_SCSI_PCI2220I is not set # CONFIG_SCSI_PSI240I is not set # CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set # CONFIG_SCSI_DEBUG is not set @@ -444,7 +372,7 @@ CONFIG_SCSI_ARXESCSI=m CONFIG_SCSI_CUMANA_2=m CONFIG_SCSI_EESOXSCSI=m -CONFIG_SCSI_POWERTECSCSI=m +CONFIG_SCSI_POWERTECSCSI=y # # The following drivers are not fully supported @@ -453,52 +381,101 @@ CONFIG_SCSI_OAK1=m # -# Sound +# I2O device support # -CONFIG_SOUND=m -# CONFIG_SOUND_CMPCI is not set -# CONFIG_SOUND_EMU10K1 is not set -# CONFIG_SOUND_ES1370 is not set -# CONFIG_SOUND_ES1371 is not set -# CONFIG_SOUND_ESSSOLO1 is not set -# CONFIG_SOUND_MAESTRO is not set -# CONFIG_SOUND_SONICVIBES is not set -# CONFIG_SOUND_TRIDENT is not set -# CONFIG_SOUND_MSNDCLAS is not set -# CONFIG_SOUND_MSNDPIN is not set -# CONFIG_SOUND_VIA82CXXX is not set -CONFIG_SOUND_OSS=m -# CONFIG_SOUND_TRACEINIT is not set -# CONFIG_SOUND_DMAP is not set -# CONFIG_SOUND_AD1816 is not set -# CONFIG_SOUND_SGALAXY is not set -# CONFIG_SOUND_ADLIB is not set -# CONFIG_SOUND_ACI_MIXER is not set -# CONFIG_SOUND_CS4232 is not set -# CONFIG_SOUND_SSCAPE is not set -# CONFIG_SOUND_GUS is not set -# CONFIG_SOUND_ICH is not set -# CONFIG_SOUND_VMIDI is not set -# CONFIG_SOUND_TRIX is not set -# CONFIG_SOUND_MSS is not set -# CONFIG_SOUND_MPU401 is not set -# CONFIG_SOUND_NM256 is not set -# CONFIG_SOUND_MAD16 is not set -# CONFIG_SOUND_PAS is not set -# CONFIG_PAS_JOYSTICK is not set -# CONFIG_SOUND_PSS is not set -CONFIG_SOUND_SOFTOSS=m -# CONFIG_SOUND_SB is not set -# CONFIG_SOUND_AWE32_SYNTH is not set -# CONFIG_SOUND_WAVEFRONT is not set -# CONFIG_SOUND_MAUI is not set -# CONFIG_SOUND_YM3812 is not set -# CONFIG_SOUND_OPL3SA1 is not set -# CONFIG_SOUND_OPL3SA2 is not set -# CONFIG_SOUND_UART6850 is not set -# CONFIG_SOUND_AEDSP16 is not set -CONFIG_SOUND_VIDC=m -# CONFIG_SOUND_WAVEARTIST is not set +# CONFIG_I2O is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Input core support +# +# CONFIG_INPUT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_ATOMWIDE_SERIAL=y +CONFIG_DUALSP_SERIAL=y +CONFIG_SERIAL_EXTENDED=y +# CONFIG_SERIAL_MANY_PORTS is not set +CONFIG_SERIAL_SHARE_IRQ=y +# CONFIG_SERIAL_DETECT_IRQ is not set +# CONFIG_SERIAL_MULTIPORT is not set +# CONFIG_HUB6 is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +CONFIG_PRINTER=m +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_PHILIPSPAR is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_ALGOPCF is not set +CONFIG_I2C_CHARDEV=y + +# +# Mice +# +CONFIG_BUSMOUSE=y +# CONFIG_ATIXL_BUSMOUSE is not set +# CONFIG_LOGIBUSMOUSE is not set +# CONFIG_MS_BUSMOUSE is not set +CONFIG_MOUSE=y +# CONFIG_PSMOUSE is not set +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set +CONFIG_RPCMOUSE=y + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set # # File systems @@ -516,6 +493,7 @@ # CONFIG_UMSDOS_FS is not set # CONFIG_VFAT_FS is not set # CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_RAMFS is not set CONFIG_ISO9660_FS=y @@ -582,12 +560,14 @@ CONFIG_SOLARIS_X86_PARTITION=y # CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_SGI_PARTITION=y +# CONFIG_ULTRIX_PARTITION is not set CONFIG_SUN_PARTITION=y CONFIG_NLS=y # # Native Language Support # +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=m CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m @@ -604,6 +584,10 @@ CONFIG_NLS_CODEPAGE_866=m CONFIG_NLS_CODEPAGE_869=m CONFIG_NLS_CODEPAGE_874=m +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_950 is not set CONFIG_NLS_ISO8859_1=m CONFIG_NLS_ISO8859_2=m CONFIG_NLS_ISO8859_3=m @@ -616,6 +600,99 @@ # CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set CONFIG_NLS_KOI8_R=m +# CONFIG_NLS_UTF8 is not set + +# +# Console drivers +# +CONFIG_FB=y + +# +# Frame-buffer support +# +CONFIG_FB=y +CONFIG_DUMMY_CONSOLE=y +CONFIG_FB_ACORN=y +# CONFIG_FB_CLPS711X is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_SA1100 is not set +# CONFIG_FB_VIRTUAL is not set +CONFIG_FBCON_ADVANCED=y +CONFIG_FBCON_MFB=y +CONFIG_FBCON_CFB2=y +CONFIG_FBCON_CFB4=y +CONFIG_FBCON_CFB8=y +CONFIG_FBCON_CFB16=y +CONFIG_FBCON_CFB24=y +CONFIG_FBCON_CFB32=y +# CONFIG_FBCON_AFB is not set +# CONFIG_FBCON_ILBM is not set +# CONFIG_FBCON_IPLAN2P2 is not set +# CONFIG_FBCON_IPLAN2P4 is not set +# CONFIG_FBCON_IPLAN2P8 is not set +# CONFIG_FBCON_MAC is not set +# CONFIG_FBCON_VGA_PLANES is not set +# CONFIG_FBCON_VGA is not set +# CONFIG_FBCON_HGA is not set +# CONFIG_FBCON_FONTWIDTH8_ONLY is not set +CONFIG_FBCON_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_PEARL_8x8 is not set +CONFIG_FONT_ACORN_8x8=y + +# +# Sound +# +CONFIG_SOUND=m +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +# CONFIG_SOUND_ES1371 is not set +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +CONFIG_SOUND_OSS=m +# CONFIG_SOUND_TRACEINIT is not set +# CONFIG_SOUND_DMAP is not set +# CONFIG_SOUND_AD1816 is not set +# CONFIG_SOUND_SGALAXY is not set +# CONFIG_SOUND_ADLIB is not set +# CONFIG_SOUND_ACI_MIXER is not set +# CONFIG_SOUND_CS4232 is not set +# CONFIG_SOUND_SSCAPE is not set +# CONFIG_SOUND_GUS is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_VMIDI is not set +# CONFIG_SOUND_TRIX is not set +# CONFIG_SOUND_MSS is not set +# CONFIG_SOUND_MPU401 is not set +# CONFIG_SOUND_NM256 is not set +# CONFIG_SOUND_MAD16 is not set +# CONFIG_SOUND_PAS is not set +# CONFIG_PAS_JOYSTICK is not set +# CONFIG_SOUND_PSS is not set +# CONFIG_SOUND_SB is not set +# CONFIG_SOUND_AWE32_SYNTH is not set +# CONFIG_SOUND_WAVEFRONT is not set +# CONFIG_SOUND_MAUI is not set +# CONFIG_SOUND_YM3812 is not set +# CONFIG_SOUND_OPL3SA1 is not set +# CONFIG_SOUND_OPL3SA2 is not set +# CONFIG_SOUND_YMPCI is not set +# CONFIG_SOUND_UART6850 is not set +# CONFIG_SOUND_AEDSP16 is not set +CONFIG_SOUND_VIDC=m +# CONFIG_SOUND_TVMIXER is not set # # USB support @@ -627,7 +704,7 @@ # CONFIG_FRAME_POINTER=y CONFIG_DEBUG_ERRORS=y -# CONFIG_DEBUG_USER is not set +CONFIG_DEBUG_USER=y # CONFIG_DEBUG_INFO is not set CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_LL=y diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/sherman linux/arch/arm/def-configs/sherman --- v2.4.0-test11/linux/arch/arm/def-configs/sherman Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/def-configs/sherman Mon Nov 27 17:07:59 2000 @@ -0,0 +1,210 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_ARM=y + +# +# System and processor type +# +# CONFIG_ARCH_ARC is not set +# CONFIG_ARCH_A5K is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_FOOTBRIDGE is not set +CONFIG_ARCH_SA1100=y +CONFIG_CPU_SA1100=y +# CONFIG_SA1100_BRUTUS is not set +# CONFIG_SA1100_EMPEG is not set +# CONFIG_SA1100_ITSY is not set +# CONFIG_SA1100_PLEB is not set +# CONFIG_SA1100_VICTOR is not set +CONFIG_SA1100_SHERMAN=y +# CONFIG_VICTOR_BOARD1 is not set +# CONFIG_ARCH_ACORN is not set +# CONFIG_ISA_DMA is not set +CONFIG_CPU_32=y +# CONFIG_CPU_26 is not set +# CONFIG_CPU_ARM2 is not set +# CONFIG_CPU_ARM3 is not set +# CONFIG_CPU_ARM6 is not set +# CONFIG_CPU_ARM7 is not set +CONFIG_CPU_SA110=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_ALIGNMENT_TRAP is not set +# CONFIG_TEXT_SECTIONS is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# General setup +# +# CONFIG_NET is not set +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_NWFPE=y +# CONFIG_BINFMT_AOUT is not set +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_ARTHUR is not set +# CONFIG_PARPORT is not set +CONFIG_CMDLINE="" + +# +# Plug and Play support +# +# CONFIG_PNP is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_IDE is not set + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_IDEDISK is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_CMD640 is not set +# CONFIG_IDE_CHIPSETS is not set + +# +# Additional Block Devices +# +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_RAM=y +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE_PARPORT is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_FLASH=y + +# +# Character devices +# +# CONFIG_VT is not set +CONFIG_SERIAL_SA1100=y +CONFIG_SERIAL_SA1100_CONSOLE=y +# CONFIG_SERIAL is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_UNIX98_PTYS is not set +# CONFIG_MOUSE is not set +# CONFIG_QIC02_TAPE is not set +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set + +# +# Video For Linux +# +# CONFIG_VIDEO_DEV is not set + +# +# Joystick support +# +# CONFIG_JOYSTICK is not set +# CONFIG_DTLK is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set + +# +# SCSI support +# +# CONFIG_SCSI is not set + +# +# Filesystems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_ISO9660_FS is not set +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_OSF_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ACORN_PARTITION is not set +CONFIG_NLS=y + +# +# Native Language Support +# +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set + +# +# Kernel hacking +# +CONFIG_FRAME_POINTER=y +CONFIG_DEBUG_ERRORS=y +CONFIG_DEBUG_USER=y +CONFIG_DEBUG_INFO=y +# CONFIG_MAGIC_SYSRQ is not set +CONFIG_DEBUG_LL=y diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/def-configs/thinclient linux/arch/arm/def-configs/thinclient --- v2.4.0-test11/linux/arch/arm/def-configs/thinclient Mon Jun 19 17:59:33 2000 +++ linux/arch/arm/def-configs/thinclient Wed Dec 31 16:00:00 1969 @@ -1,402 +0,0 @@ -# -# Automatically generated make config: don't edit -# -CONFIG_ARM=y -CONFIG_UID16=y - -# -# Code maturity level options -# -CONFIG_EXPERIMENTAL=y - -# -# System and processor type -# -# CONFIG_ARCH_ARC is not set -# CONFIG_ARCH_A5K is not set -# CONFIG_ARCH_RPC is not set -# CONFIG_ARCH_EBSA110 is not set -# CONFIG_FOOTBRIDGE is not set -CONFIG_ARCH_SA1100=y -# CONFIG_SA1100_ASSABET is not set -# CONFIG_SA1100_BRUTUS is not set -# CONFIG_SA1100_EMPEG is not set -# CONFIG_SA1100_ITSY is not set -# CONFIG_SA1100_BITSY is not set -# CONFIG_SA1100_LART is not set -# CONFIG_SA1100_PLEB is not set -CONFIG_SA1100_THINCLIENT=y -# CONFIG_SA1100_GRAPHICSCLIENT is not set -# CONFIG_SA1100_VICTOR is not set -# CONFIG_SA1100_TIFON is not set -CONFIG_DISCONTIGMEM=y -# CONFIG_ARCH_ACORN is not set -CONFIG_CPU_32=y -# CONFIG_CPU_26 is not set -CONFIG_CPU_32v4=y -CONFIG_CPU_SA1100=y -# CONFIG_PCI is not set -# CONFIG_ISA is not set -# CONFIG_ISA_DMA is not set -# CONFIG_SBUS is not set -# CONFIG_PCMCIA is not set -CONFIG_ALIGNMENT_TRAP=y - -# -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -# CONFIG_KMOD is not set - -# -# General setup -# -CONFIG_NET=y -CONFIG_SYSVIPC=y -# CONFIG_BSD_PROCESS_ACCT is not set -CONFIG_SYSCTL=y -CONFIG_NWFPE=y -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set -CONFIG_BINFMT_AOUT=y -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set -# CONFIG_ARTHUR is not set - -# -# Parallel port support -# -# CONFIG_PARPORT is not set -CONFIG_CMDLINE="root=nfs" -# CONFIG_LEDS is not set - -# -# I2O device support -# -# CONFIG_I2O is not set -# CONFIG_I2O_BLOCK is not set -# CONFIG_I2O_LAN is not set -# CONFIG_I2O_SCSI is not set -# CONFIG_I2O_PROC is not set - -# -# Plug and Play configuration -# -# CONFIG_PNP is not set -# CONFIG_ISAPNP is not set - -# -# Block devices -# -# CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_STRIPED is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_BLK_DEV_FLASH=y - -# -# Character devices -# -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_SERIAL_SA1100=y -CONFIG_SERIAL_SA1100_CONSOLE=y -# CONFIG_SERIAL is not set -# CONFIG_SERIAL_EXTENDED is not set -# CONFIG_SERIAL_NONSTANDARD is not set -CONFIG_UNIX98_PTYS=y -CONFIG_UNIX98_PTY_COUNT=32 - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# Mice -# -# CONFIG_BUSMOUSE is not set -# CONFIG_MOUSE is not set - -# -# Joysticks -# -# CONFIG_JOYSTICK is not set -# CONFIG_QIC02_TAPE is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# -# CONFIG_FTAPE is not set -# CONFIG_DRM is not set -# CONFIG_DRM_TDFX is not set -# CONFIG_AGP is not set - -# -# Console drivers -# -# CONFIG_VGA_CONSOLE is not set -CONFIG_FB=y - -# -# Frame-buffer support -# -CONFIG_FB=y -CONFIG_DUMMY_CONSOLE=y -CONFIG_FB_SA1100=y -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FBCON_ADVANCED is not set -CONFIG_FBCON_CFB2=y -CONFIG_FBCON_CFB4=y -CONFIG_FBCON_CFB8=y -CONFIG_FBCON_FONTWIDTH8_ONLY=y -CONFIG_FBCON_FONTS=y -# CONFIG_FONT_8x8 is not set -CONFIG_FONT_8x16=y -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -# CONFIG_NETLINK is not set -# CONFIG_NETFILTER is not set -# CONFIG_FILTER is not set -CONFIG_UNIX=y -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_PNP=y -CONFIG_IP_PNP_BOOTP=y -# CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set -# CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_SKB_LARGE=y -# CONFIG_IPV6 is not set -# CONFIG_KHTTPD is not set -# CONFIG_ATM is not set - -# -# -# -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_DECNET is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_BRIDGE is not set -# CONFIG_LLC is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_FASTROUTE is not set -# CONFIG_NET_HW_FLOWCONTROL is not set - -# -# QoS and/or fair queueing -# -# CONFIG_NET_SCHED is not set - -# -# Amateur Radio support -# -# CONFIG_HAMRADIO is not set - -# -# IrDA (infrared) support -# -# CONFIG_IRDA is not set - -# -# Network device support -# -CONFIG_NETDEVICES=y - -# -# ARCnet devices -# -# CONFIG_ARCNET is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_EQUALIZER is not set -# CONFIG_NET_SB1000 is not set - -# -# Ethernet (10 or 100Mbit) -# -CONFIG_NET_ETHERNET=y -# CONFIG_ARM_AM79C961A is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_LANCE is not set -CONFIG_NET_VENDOR_SMC=y -# CONFIG_WD80x3 is not set -# CONFIG_ULTRA is not set -# CONFIG_ULTRA32 is not set -CONFIG_SMC9194=y -# CONFIG_NET_VENDOR_RACAL is not set -# CONFIG_AT1700 is not set -# CONFIG_DEPCA is not set -# CONFIG_NET_ISA is not set -# CONFIG_NET_PCI is not set -# CONFIG_NET_POCKET is not set - -# -# Ethernet (1000 Mbit) -# -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC is not set -# CONFIG_SK98LIN is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Wireless LAN (non-hamradio) -# -# CONFIG_NET_RADIO is not set - -# -# Token Ring devices -# -# CONFIG_TR is not set -# CONFIG_NET_FC is not set -# CONFIG_RCPCI is not set -# CONFIG_SHAPER is not set - -# -# Wan interfaces -# -# CONFIG_WAN is not set - -# -# ATA/IDE/MFM/RLL support -# -# CONFIG_IDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD is not set - -# -# SCSI support -# -# CONFIG_SCSI is not set - -# -# File systems -# -# CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_RAMFS is not set -# CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set -CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -CONFIG_DEVPTS_FS=y -# CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y -# CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set -# CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set - -# -# Network File Systems -# -# CONFIG_CODA_FS is not set -CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set -CONFIG_ROOT_NFS=y -# CONFIG_NFSD is not set -# CONFIG_NFSD_V3 is not set -CONFIG_SUNRPC=y -CONFIG_LOCKD=y -# CONFIG_SMB_FS is not set -# CONFIG_NCP_FS is not set -# CONFIG_NCPFS_PACKET_SIGNING is not set -# CONFIG_NCPFS_IOCTL_LOCKING is not set -# CONFIG_NCPFS_STRONG is not set -# CONFIG_NCPFS_NFS_NS is not set -# CONFIG_NCPFS_OS2_NS is not set -# CONFIG_NCPFS_SMALLDOS is not set -# CONFIG_NCPFS_MOUNT_SUBDIR is not set -# CONFIG_NCPFS_NDS_DOMAINS is not set -# CONFIG_NCPFS_NLS is not set -# CONFIG_NCPFS_EXTRAS is not set - -# -# Partition Types -# -# CONFIG_PARTITION_ADVANCED is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_NLS is not set - -# -# USB support -# -# CONFIG_USB is not set - -# -# Kernel hacking -# -CONFIG_FRAME_POINTER=y -CONFIG_DEBUG_ERRORS=y -CONFIG_DEBUG_USER=y -CONFIG_DEBUG_INFO=y -# CONFIG_MAGIC_SYSRQ is not set -# CONFIG_DEBUG_LL is not set diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c --- v2.4.0-test11/linux/arch/arm/kernel/bios32.c Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/bios32.c Mon Nov 27 17:51:34 2000 @@ -451,7 +451,6 @@ */ pci_assign_unassigned_resources(); pci_fixup_irqs(hw_pci->swizzle, hw_pci->map_irq); - pci_set_bus_ranges(); } char * __init pcibios_setup(char *str) @@ -463,8 +462,29 @@ return str; } +/* + * From arch/i386/kernel/pci-i386.c: + * + * We need to avoid collisions with `mirrored' VGA ports + * and other strange ISA hardware, so we always want the + * addresses to be allocated in the 0x000-0x0ff region + * modulo 0x400. + * + * Why? Because some silly external IO cards only decode + * the low 10 bits of the IO address. The 0x00-0xff region + * is reserved for motherboard devices that decode all 16 + * bits, so it's ok to allocate at, say, 0x2800-0x28ff, + * but we want to try to avoid allocating at 0x2900-0x2bff + * which might have be mirrored at 0x0100-0x03ff.. + */ void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { + if (res->flags & IORESOURCE_IO) { + unsigned long start = res->start; + + if (start & 0x300) + res->start = (start + 0x3ff) & ~0x3ff; + } } /** diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c --- v2.4.0-test11/linux/arch/arm/kernel/dec21285.c Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/dec21285.c Mon Nov 27 17:07:59 2000 @@ -258,17 +258,21 @@ void __init dc21285_init(struct arm_pci_sysdata *sysdata) { unsigned long cntl; - unsigned int mem_size; + unsigned int mem_size, mem_mask; unsigned int pci_cmd = PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE; int cfn_mode; + mem_size = (unsigned int)high_memory - PAGE_OFFSET; + for (mem_mask = 0x00100000; mem_mask < 0x10000000; mem_mask <<= 1) + if (mem_mask >= mem_size) + break; + /* * These registers need to be set up whether we're the * central function or not. */ - mem_size = (unsigned int)high_memory - PAGE_OFFSET; - *CSR_SDRAMBASEMASK = (mem_size - 1) & 0x0ffc0000; + *CSR_SDRAMBASEMASK = (mem_mask - 1) & 0x0ffc0000; *CSR_SDRAMBASEOFFSET = 0; *CSR_ROMBASEMASK = 0x80000000; *CSR_CSRBASEMASK = 0; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/dma-arc.c linux/arch/arm/kernel/dma-arc.c --- v2.4.0-test11/linux/arch/arm/kernel/dma-arc.c Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/dma-arc.c Mon Nov 27 17:07:59 2000 @@ -156,7 +156,7 @@ memcpy((void *)0x1c, fiqhandler_start, fiqhandler_length); regs.ARM_r9 = dma->buf.length; regs.ARM_r10 = dma->buf.address; - regs.ARM_fp = (int)PCIO_FLOPPYDMABASE; + regs.ARM_fp = FLOPPYDMA_BASE; set_fiq_regs(®s); enable_irq(dma->dma_irq); } @@ -191,7 +191,7 @@ void __init arch_dma_init(dma_t *dma) { #if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE) - if (machine_is_arc()) { + if (machine_is_archimedes()) { dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64; dma[DMA_VIRTUAL_FLOPPY0].d_ops = &arc_floppy_data_dma_ops; dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S --- v2.4.0-test11/linux/arch/arm/kernel/entry-armv.S Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/entry-armv.S Mon Nov 27 17:07:59 2000 @@ -84,7 +84,7 @@ strb r12, [r12, #0x38] @ Disable FIQ register .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov r4, #ioc_base_high @ point at IOC .if ioc_base_low orr r4, r4, #ioc_base_low @@ -165,36 +165,23 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base - mov r4, #0xf3000000 - ldrb \irqstat, [r4] @ get interrupts - adr \base, irq_prio_ebsa110 - - teq \irqstat, #0 - ldrneb \irqnr, [\base, \irqstat] @ get IRQ number + .macro get_irqnr_and_base, irqnr, stat, base, tmp + mov \base, #IRQ_STAT + ldrb \stat, [\base] @ get interrupts + mov \irqnr, #0 + tst \stat, #15 + addeq \irqnr, \irqnr, #4 + moveq \stat, \stat, lsr #4 + tst \stat, #3 + addeq \irqnr, \irqnr, #2 + moveq \stat, \stat, lsr #2 + tst \stat, #1 + addeq \irqnr, \irqnr, #1 + moveq \stat, \stat, lsr #1 + tst \stat, #1 @ bit 0 should be set .endm .macro irq_prio_table -irq_prio_ebsa110: - .byte 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - - .byte 7, 0, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - .byte 4, 4, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - .byte 5, 5, 1, 1, 2, 2, 2, 2, 3, 3, 1, 1, 2, 2, 2, 2 - - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 - .byte 6, 6, 6, 6, 2, 2, 2, 2, 3, 3, 6, 6, 2, 2, 2, 2 .endm #elif defined(CONFIG_ARCH_SHARK) @@ -202,7 +189,7 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov r4, #0xe0000000 orr r4, r4, #0x20 @@ -238,7 +225,7 @@ .equ dc21285_high, ARMCSR_BASE & 0xff000000 .equ dc21285_low, ARMCSR_BASE & 0x00ffffff - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov r4, #dc21285_high .if dc21285_low orr r4, r4, #dc21285_low @@ -334,7 +321,7 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \irqstat, =INTCONT_BASE ldr \base, =soft_irq_mask ldr \irqstat, [\irqstat] @ get interrupts @@ -362,7 +349,7 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp ldr \irqstat, =0xffff7000 ldr \irqstat, [\irqstat] @ get interrupts ldr \base, =soft_irq_mask @@ -390,7 +377,7 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov r4, #0xfa000000 @ ICIP = 0xfa050000 add r4, r4, #0x00050000 ldr \irqstat, [r4] @ get irqs @@ -428,7 +415,7 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp mov \irqstat, #irq_base_addr @ Virt addr IRQ regs add \irqstat, \irqstat, #0x00001000 @ Status reg ldr \irqstat, [\irqstat, #0] @ get interrupts @@ -449,7 +436,7 @@ .macro disable_fiq .endm - .macro get_irqnr_and_base, irqnr, irqstat, base + .macro get_irqnr_and_base, irqnr, irqstat, base, tmp /* FIXME: should not be using soo many LDRs here */ ldr \irqnr, =IO_ADDRESS(INTEGRATOR_IC_BASE) ldr \irqstat, [\irqnr, #IRQ_STATUS] @ get masked status @@ -470,6 +457,50 @@ .macro irq_prio_table .endm +#elif defined(CONFIG_ARCH_P720T) + + .macro disable_fiq + .endm + +#if (INTSR2 - INTSR1) != (INTMR2 - INTMR1) +#error INTSR stride != INTMR stride +#endif + + .macro get_irqnr_and_base, irqnr, stat, base, mask + mov \base, #CLPS7111_BASE + ldr \stat, [\base, #INTSR1] + ldr \mask, [\base, #INTMR1] + mov \irqnr, #4 + mov \mask, \mask, lsl #16 + and \stat, \stat, \mask, lsr #16 + movs \stat, \stat, lsr #4 + bne 1001f + + add \base, \base, #INTSR2 - INTSR1 + ldr \stat, [\base, #INTSR1] + ldr \mask, [\base, #INTMR1] + mov \irqnr, #16 + mov \mask, \mask, lsl #16 + and \stat, \stat, \mask, lsr #16 + +1001: tst \stat, #255 + addeq \irqnr, \irqnr, #8 + moveq \stat, \stat, lsr #8 + tst \stat, #15 + addeq \irqnr, \irqnr, #4 + moveq \stat, \stat, lsr #4 + tst \stat, #3 + addeq \irqnr, \irqnr, #2 + moveq \stat, \stat, lsr #2 + tst \stat, #1 + addeq \irqnr, \irqnr, #1 + moveq \stat, \stat, lsr #1 + tst \stat, #1 @ bit 0 should be set + .endm + + .macro irq_prio_table + .endm + #else #error Unknown architecture #endif @@ -594,7 +625,7 @@ adr r10, wfs_mask_data ldmia r10, {r4, r5, r6, r7, r8} ldr r10, [sp, #S_PC] @ Load PC - sub r10, r10, #-4 + sub r10, r10, #4 mask_pc r10, r10 ldrt r10, [r10] @ get instruction and r5, r10, r5 @@ -660,7 +691,7 @@ add r4, sp, #S_SP mov r6, lr stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro -1: get_irqnr_and_base r0, r6, r5 +1: get_irqnr_and_base r0, r6, r5, lr movne r1, sp @ @ routine called with r0 = irq number, r1 = struct pt_regs * @@ -695,6 +726,28 @@ ldmia sp, {r0 - pc}^ @ Restore SVC registers .align 5 +__pabt_svc: sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ save r0 - r12 + ldr r2, .LCabt + add r0, sp, #S_FRAME_SIZE + ldmia r2, {r2 - r4} @ get pc, cpsr + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro + mrs r9, cpsr @ Enable interrupts if they were + tst r3, #I_BIT + biceq r9, r9, #I_BIT @ previously + msr cpsr_c, r9 + mov r0, r2 @ address (pc) + mov r1, sp @ regs + bl SYMBOL_NAME(do_PrefetchAbort) @ call abort handler + mov r0, #I_BIT | MODE_SVC + msr cpsr_c, r0 + ldr r0, [sp, #S_PSR] + msr spsr, r0 + ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr + + .align 5 .LCirq: .word __temp_irq .LCund: .word __temp_und .LCabt: .word __temp_abt @@ -744,7 +797,7 @@ stmdb r8, {sp, lr}^ alignment_trap r4, r7, __temp_irq zero_fp -1: get_irqnr_and_base r0, r6, r5 +1: get_irqnr_and_base r0, r6, r5, lr movne r1, sp adrsvc ne, lr, 1b @ @@ -762,7 +815,7 @@ add r8, sp, #S_PC ldmia r4, {r5 - r7} stmia r8, {r5 - r7} @ Save USR pc, cpsr, old_r0 - stmdb r8, {sp, lr}^ @ Save user r0 - r12 + stmdb r8, {sp, lr}^ @ Save user sp, lr alignment_trap r4, r7, __temp_und zero_fp adrsvc al, r9, ret_from_sys_call @ r9 = normal FP return @@ -960,12 +1013,25 @@ msr spsr_c, r13 @ switch to SVC_32 mode ands lr, lr, #15 - ldreq lr, .LCtab_pabt - ldrne lr, .LCtab_pabt + 4 + ldr lr, [pc, lr, lsl #2] movs pc, lr -.LCtab_pabt: .word __pabt_usr - .word __pabt_invalid +.LCtab_pabt: .word __pabt_usr @ 0 (USR_26 / USR_32) + .word __pabt_invalid @ 1 (FIQ_26 / FIQ_32) + .word __pabt_invalid @ 2 (IRQ_26 / IRQ_32) + .word __pabt_svc @ 3 (SVC_26 / SVC_32) + .word __pabt_invalid @ 4 + .word __pabt_invalid @ 5 + .word __pabt_invalid @ 6 + .word __pabt_invalid @ 7 + .word __pabt_invalid @ 8 + .word __pabt_invalid @ 9 + .word __pabt_invalid @ a + .word __pabt_invalid @ b + .word __pabt_invalid @ c + .word __pabt_invalid @ d + .word __pabt_invalid @ e + .word __pabt_invalid @ f .align 5 diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c --- v2.4.0-test11/linux/arch/arm/kernel/fiq.c Sun Aug 13 09:54:15 2000 +++ linux/arch/arm/kernel/fiq.c Mon Nov 27 17:07:59 2000 @@ -131,15 +131,14 @@ #endif #ifdef CONFIG_CPU_32 "mrs %0, cpsr - bic %1, %0, #0xf - orr %1, %1, #0xc1 - msr cpsr, %1 @ select FIQ mode + mov %1, #0xc1 + msr cpsr_c, %1 @ select FIQ mode mov r0, r0 ldmia %2, {r8 - r14} - msr cpsr, %0 @ return to SVC mode + msr cpsr_c, %0 @ return to SVC mode mov r0, r0" #endif - : "=r" (tmp), "=r" (tmp2) + : "=&r" (tmp), "=&r" (tmp2) : "r" (®s->ARM_r8) /* These registers aren't modified by the above code in a way visible to the compiler, but we mark them as clobbers anyway @@ -164,15 +163,14 @@ #endif #ifdef CONFIG_CPU_32 "mrs %0, cpsr - bic %1, %0, #0xf - orr %1, %1, #0xc1 - msr cpsr, %1 @ select FIQ mode + mov %1, #0xc1 + msr cpsr_c, %1 @ select FIQ mode mov r0, r0 stmia %2, {r8 - r14} - msr cpsr, %0 @ return to SVC mode + msr cpsr_c, %0 @ return to SVC mode mov r0, r0" #endif - : "=r" (tmp), "=r" (tmp2) + : "=&r" (tmp), "=&r" (tmp2) : "r" (®s->ARM_r8) /* These registers aren't modified by the above code in a way visible to the compiler, but we mark them as clobbers anyway diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/head-armo.S linux/arch/arm/kernel/head-armo.S --- v2.4.0-test11/linux/arch/arm/kernel/head-armo.S Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/head-armo.S Mon Nov 27 17:07:59 2000 @@ -21,7 +21,6 @@ */ .section ".text.init",#alloc,#execinstr ENTRY(stext) -ENTRY(_stext) __entry: cmp pc, #0x02000000 ldrlt pc, LC0 @ if 0x01800000, call at 0x02080000 teq r0, #0 @ Check for old calling method diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S --- v2.4.0-test11/linux/arch/arm/kernel/head-armv.S Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/head-armv.S Mon Nov 27 17:07:59 2000 @@ -16,28 +16,33 @@ #include #include -#if (TEXTADDR & 0xffff) != 0x8000 -#error TEXTADDR must start at 0xXXXX8000 -#endif - #define K(a,b,c) ((a) << 24 | (b) << 12 | (c)) /* - * swapper_pg_dir is the virtual address of the "init_task" page tables. - * SWAPPER_PGDIR_OFFSET is the offset from the start of memory of the - * page tables. + * We place the page tables 16K below TEXTADDR. Therefore, we must make sure + * that TEXTADDR is correctly set. Currently, we expect the least significant + * "short" to be 0x8000, but we could probably relax this restriction to + * TEXTADDR > PAGE_OFFSET + 0x4000 * - * Note that at the moment, we assume TEXTADDR is the virtual equivalent - * of start of memory + 0x8000 + * Note that swapper_pg_dir is the virtual address of the page tables, and + * pgtbl gives us a position-independent reference to these tables. We can + * do this because stext == TEXT_ADDR */ -#define SWAPPER_PGDIR_OFFSET 0x4000 +#if (TEXTADDR & 0xffff) != 0x8000 +#error TEXTADDR must start at 0xXXXX8000 +#endif + .globl SYMBOL_NAME(swapper_pg_dir) - .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x8000 + SWAPPER_PGDIR_OFFSET + .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 + + .macro pgtbl, reg + adr \reg, stext + sub \reg, \reg, #0x4000 + .endm .section ".text.init",#alloc,#execinstr .type stext, #function ENTRY(stext) -ENTRY(_stext) /* * Entry point. The general rules are: * should be called with r0 == 0 @@ -185,7 +190,7 @@ * r8 = page table flags */ __create_page_tables: - add r4, r5, #SWAPPER_PGDIR_OFFSET + pgtbl r4 mov r0, r4 mov r3, #0 add r2, r0, #0x4000 @ 16k of page table diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/oldlatches.c linux/arch/arm/kernel/oldlatches.c --- v2.4.0-test11/linux/arch/arm/kernel/oldlatches.c Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/oldlatches.c Mon Nov 27 17:07:59 2000 @@ -26,12 +26,12 @@ /* newval=(oldval & ~mask)|newdata */ void oldlatch_aupdate(unsigned char mask,unsigned char newdata) { - if (machine_is_arc()) { + if (machine_is_archimedes()) { latch_a_copy = (latch_a_copy & ~mask) | newdata; printk("Latch: A = 0x%02x\n", latch_a_copy); - outb(latch_a_copy, LATCHAADDR); + __raw_writeb(latch_a_copy, LATCHA_BASE); } else BUG(); } @@ -40,19 +40,19 @@ /* newval=(oldval & ~mask)|newdata */ void oldlatch_bupdate(unsigned char mask,unsigned char newdata) { - if (machine_is_arc()) { + if (machine_is_archimedes()) { latch_b_copy = (latch_b_copy & ~mask) | newdata; printk("Latch: B = 0x%02x\n", latch_b_copy); - outb(latch_b_copy, LATCHBADDR); + __raw_writeb(latch_b_copy, LATCHB_BASE); } else BUG(); } static void __init oldlatch_init(void) { - if (machine_is_arc()) { + if (machine_is_archimedes()) { oldlatch_aupdate(0xff, 0xff); /* Thats no FDC reset...*/ oldlatch_bupdate(0xff, LATCHB_FDCRESET); diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c --- v2.4.0-test11/linux/arch/arm/kernel/traps.c Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/traps.c Sun Dec 3 17:48:19 2000 @@ -31,6 +31,7 @@ #include "ptrace.h" extern void c_backtrace (unsigned long fp, int pmode); +extern void show_pte(struct mm_struct *mm, unsigned long addr); const char *processor_modes[]= { "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , @@ -41,12 +42,6 @@ static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; -static inline void console_verbose(void) -{ - extern int console_loglevel; - console_loglevel = 15; -} - /* * Stack pointers should always be within the kernels view of * physical memory. If it is not there, then we can't dump @@ -72,10 +67,14 @@ printk("%08lx: ", p); for (i = 0; i < 8; i++, p += 4) { + unsigned int val; + if (p < bottom || p >= top) printk(" "); - else - printk("%08lx ", *(unsigned long *)p); + else { + __get_user(val, (unsigned long *)p); + printk("%08x ", val); + } if (i == 3) printk(" "); } @@ -91,45 +90,57 @@ #define VMALLOC_OFFSET (8*1024*1024) #define MODULE_RANGE (8*1024*1024) -static void dump_instr(unsigned long pc, int user) +static void dump_instr(struct pt_regs *regs) { - int pmin = -2, pmax = 3, ok = 0; - extern char start_kernel, _etext; + unsigned long addr = instruction_pointer(regs); + const int thumb = thumb_mode(regs); + const int width = thumb ? 4 : 8; + int i; - if (!user) { - unsigned long module_start, module_end; - unsigned long kernel_start, kernel_end; - - module_start = VMALLOC_START; - module_end = module_start + MODULE_RANGE; - - kernel_start = (unsigned long)&start_kernel; - kernel_end = (unsigned long)&_etext; - - if (pc >= kernel_start && pc < kernel_end) { - if (pc + pmin < kernel_start) - pmin = kernel_start - pc; - if (pc + pmax > kernel_end) - pmax = kernel_end - pc; - ok = 1; - } else if (pc >= module_start && pc < module_end) { - if (pc + pmin < module_start) - pmin = module_start - pc; - if (pc + pmax > module_end) - pmax = module_end - pc; - ok = 1; + printk("Code: "); + for (i = -2; i < 3; i++) { + unsigned int val, bad; + + if (thumb) + bad = __get_user(val, &((u16 *)addr)[i]); + else + bad = __get_user(val, &((u32 *)addr)[i]); + + if (!bad) + printk(i == 0 ? "(%0*x) " : "%0*x", width, val); + else { + printk("bad PC value."); + break; } - } else - ok = verify_area(VERIFY_READ, (void *)(pc + pmin), pmax - pmin) == 0; + } + printk("\n"); +} - printk ("Code: "); - if (ok) { - int i; - for (i = pmin; i < pmax; i++) - printk(i == 0 ? "(%08lx) " : "%08lx ", ((unsigned long *)pc)[i]); - printk ("\n"); - } else - printk ("pc not in code space\n"); +static void dump_stack(struct task_struct *tsk, unsigned long sp) +{ + printk("Stack:\n"); + dump_mem(sp - 16, 8192+(unsigned long)tsk); +} + +static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk) +{ + unsigned int fp; + int ok = 1; + + printk("Backtrace: "); + fp = regs->ARM_fp; + if (!fp) { + printk("no frame pointer"); + ok = 0; + } else if (verify_stack(fp)) { + printk("invalid frame pointer %08lx", fp); + ok = 0; + } else if (fp < 4096+(unsigned long)tsk) + printk("frame pointer underflow"); + printk("\n"); + + if (ok) + c_backtrace(fp, processor_mode(regs)); } spinlock_t die_lock = SPIN_LOCK_UNLOCKED; @@ -141,9 +152,9 @@ { struct task_struct *tsk = current; + console_verbose(); spin_lock_irq(&die_lock); - console_verbose(); printk("Internal error: %s: %x\n", str, err); printk("CPU: %d\n", smp_processor_id()); show_regs(regs); @@ -151,39 +162,22 @@ current->comm, current->pid, 4096+(unsigned long)tsk); if (!user_mode(regs)) { - unsigned long sp = (unsigned long)(regs + 1); - unsigned long fp; - int dump_info = 1; - - printk("Stack: "); - if (verify_stack(sp)) { - printk("invalid kernel stack pointer %08lx", sp); - dump_info = 0; - } else if (sp < 4096+(unsigned long)tsk) - printk("kernel stack pointer underflow"); - printk("\n"); - - if (dump_info) - dump_mem(sp - 16, 8192+(unsigned long)tsk); - - dump_info = 1; - - printk("Backtrace: "); - fp = regs->ARM_fp; - if (!fp) { - printk("no frame pointer"); - dump_info = 0; - } else if (verify_stack(fp)) { - printk("invalid frame pointer %08lx", fp); - dump_info = 0; - } else if (fp < 4096+(unsigned long)tsk) - printk("frame pointer underflow"); - printk("\n"); + mm_segment_t fs; - if (dump_info) - c_backtrace(fp, processor_mode(regs)); + /* + * We need to switch to kernel mode so that we can + * use __get_user to safely read from kernel space. + * Note that we now dump the code first, just in case + * the backtrace kills us. + */ + fs = get_fs(); + set_fs(KERNEL_DS); + + dump_instr(regs); + dump_stack(tsk, (unsigned long)(regs + 1)); + dump_backtrace(regs, tsk); - dump_instr(instruction_pointer(regs), 0); + set_fs(fs); } spin_unlock_irq(&die_lock); @@ -206,6 +200,7 @@ #ifdef CONFIG_DEBUG_USER printk(KERN_INFO "%s (%d): undefined instruction: pc=%08lx\n", current->comm, current->pid, addr); + dump_instr(regs); #endif current->thread.error_code = 0; @@ -228,6 +223,7 @@ #ifdef CONFIG_DEBUG_USER printk(KERN_INFO "%s (%d): address exception: pc=%08lx\n", current->comm, current->pid, instruction_pointer(regs)); + dump_instr(regs); #endif current->thread.error_code = 0; @@ -275,7 +271,7 @@ die("Oops", regs, 0); cli(); - while(1); + panic("bad mode"); } /* @@ -332,6 +328,7 @@ * something catastrophic has happened */ printk("[%d] %s: arm syscall %d\n", current->pid, current->comm, no); + dump_instr(regs); if (user_mode(regs)) { show_regs(regs); c_backtrace(regs->ARM_fp, processor_mode(regs)); @@ -359,8 +356,9 @@ } #ifdef CONFIG_DEBUG_USER - printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", current->pid, - current->comm, n); + printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n", + current->pid, current->comm, n); + dump_instr(regs); #endif force_sig(SIGILL, current); die_if_kernel("Oops", regs, n); @@ -384,21 +382,10 @@ siginfo_t info; #ifdef CONFIG_DEBUG_USER - dump_instr(addr, 1); - { - pgd_t *pgd; - - pgd = pgd_offset(current->mm, addr); - printk ("*pgd = %08lx", pgd_val (*pgd)); - if (!pgd_none (*pgd)) { - pmd_t *pmd; - pmd = pmd_offset (pgd, addr); - printk (", *pmd = %08lx", pmd_val (*pmd)); - if (!pmd_none (*pmd)) - printk (", *pte = %08lx", pte_val(*pte_offset (pmd, addr))); - } - printk ("\n"); - } + printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n", + current->pid, current->comm, code, instr); + dump_instr(regs); + show_pte(current->mm, addr); #endif info.si_signo = SIGILL; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/kernel/via82c505.c linux/arch/arm/kernel/via82c505.c --- v2.4.0-test11/linux/arch/arm/kernel/via82c505.c Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/kernel/via82c505.c Mon Nov 27 17:07:59 2000 @@ -76,7 +76,7 @@ #ifdef CONFIG_ARCH_SHARK -static char size_wanted = 0; +static char size_wanted; static int dummy_read_config_byte(struct pci_dev *dev, int where, u8 *value) diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile --- v2.4.0-test11/linux/arch/arm/lib/Makefile Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/lib/Makefile Mon Nov 27 17:07:59 2000 @@ -13,19 +13,35 @@ strncpy_from_user.o strnlen_user.o strchr.o strrchr.o \ testchangebit.o testclearbit.o testsetbit.o uaccess.o +l-obj-y := +l-obj-n := + O_TARGET := lib.o O_OBJS := backtrace.o delay.o -L_OBJS_arc := io-acorn.o floppydma.o -L_OBJS_rpc := io-acorn.o floppydma.o +ifeq ($(CONFIG_ARCH_ACORN),y) + half := n + full := y +else + half := y + full := n +endif + +L_OBJS_arc := ecard.o io-acorn.o floppydma.o +L_OBJS_rpc := ecard.o io-acorn.o floppydma.o L_OBJS_clps7500 := io-acorn.o -L_OBJS_ebsa110 := io-ebsa110.o -L_OBJS_footbridge := io-footbridge.o +L_OBJS_footbridge := io-pcio.o L_OBJS_l7200 := io-acorn.o -L_OBJS_nexuspci := io-footbridge.o -L_OBJS_sa1100 := io-footbridge.o +L_OBJS_nexuspci := io-pcio.o +L_OBJS_sa1100 := io-pcio.o L_OBJS_shark := io-shark.o -L_OBJS_integrator := io-shark.o +L_OBJS_integrator := io-pcio.o +L_OBJS_clps711x := io-shark.o + +l-obj-y += io-readsb.o io-writesb.o +l-obj-$(full) += io-readsw-armv3.o io-writesw-armv3.o +l-obj-$(half) += io-readsw-armv4.o io-writesw-armv4.o +l-obj-y += io-readsl.o io-writesl.o ifeq ($(PROCESSOR),armo) L_OBJS += uaccess-armo.o @@ -35,7 +51,7 @@ OX_OBJS += io.o endif -L_OBJS += $(L_OBJS_$(MACHINE)) +L_OBJS += $(L_OBJS_$(MACHINE)) $(l-obj-y) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/ecard.S linux/arch/arm/lib/ecard.S --- v2.4.0-test11/linux/arch/arm/lib/ecard.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/ecard.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,47 @@ +/* + * linux/arch/arm/lib/ecard.S + * + * Copyright (C) 1995, 1996 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include /* for CONFIG_CPU_nn */ +#include +#include +#include + +#if defined(CONFIG_CPU_26) +#define CPSR2SPSR(rt) +#else +#define CPSR2SPSR(rt) \ + mrs rt, cpsr; \ + msr spsr, rt +#endif + +@ Purpose: call an expansion card loader to read bytes. +@ Proto : char read_loader(int offset, char *card_base, char *loader); +@ Returns: byte read + +ENTRY(ecard_loader_read) + stmfd sp!, {r4 - r12, lr} + mov r11, r1 + mov r1, r0 + CPSR2SPSR(r0) + mov lr, pc + mov pc, r2 + LOADREGS(fd, sp!, {r4 - r12, pc}) + +@ Purpose: call an expansion card loader to reset the card +@ Proto : void read_loader(int card_base, char *loader); +@ Returns: byte read + +ENTRY(ecard_loader_reset) + stmfd sp!, {r4 - r12, lr} + mov r11, r0 + CPSR2SPSR(r0) + mov lr, pc + add pc, r1, #8 + LOADREGS(fd, sp!, {r4 - r12, pc}) + diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-acorn.S linux/arch/arm/lib/io-acorn.S --- v2.4.0-test11/linux/arch/arm/lib/io-acorn.S Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/lib/io-acorn.S Mon Nov 27 17:07:59 2000 @@ -40,8 +40,6 @@ addeq \rd, \rd, #diff_pcio_base .endm -.iosw_bad_align_msg: - .ascii "insw: bad buffer alignment (%p), called from %08lX\n\0" .iosl_warning: .ascii "<4>insl/outsl not implemented, called from %08lX\0" .align @@ -56,422 +54,38 @@ mov r1, lr b SYMBOL_NAME(printk) -.iosw_bad_alignment: - adr r0, .iosw_bad_align_msg - mov r2, lr - b SYMBOL_NAME(panic) - - /* Purpose: read a block of data from a hardware register to memory. * Proto : void insw(int from_port, void *to, int len_in_words); * Notes : increment to, 'to' must be 16-bit aligned */ -.insw_align: tst r1, #1 - bne .iosw_bad_alignment - - ldr r3, [r0] - strb r3, [r1], #1 - mov r3, r3, lsr #8 - strb r3, [r1], #1 - - subs r2, r2, #1 - bne .insw_aligned - ENTRY(insw) teq r2, #0 - RETINSTR(moveq,pc,lr) + RETINSTR(moveq, pc, lr) addr r0 - tst r1, #3 - bne .insw_align - -.insw_aligned: mov ip, #0xff - orr ip, ip, ip, lsl #8 - stmfd sp!, {r4, r5, r6, lr} - - subs r2, r2, #8 - bmi .no_insw_8 - -.insw_8_lp: ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - ldr r4, [r0] - and r4, r4, ip - ldr r5, [r0] - orr r4, r4, r5, lsl #16 - - ldr r5, [r0] - and r5, r5, ip - ldr r6, [r0] - orr r5, r5, r6, lsl #16 - - ldr r6, [r0] - and r6, r6, ip - ldr lr, [r0] - orr r6, r6, lr, lsl #16 - - stmia r1!, {r3 - r6} - subs r2, r2, #8 - bpl .insw_8_lp - tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) + b __arch_readsw -.no_insw_8: tst r2, #4 - beq .no_insw_4 - - ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - ldr r4, [r0] - and r4, r4, ip - ldr r5, [r0] - orr r4, r4, r5, lsl #16 - - stmia r1!, {r3, r4} - -.no_insw_4: tst r2, #2 - beq .no_insw_2 - - ldr r3, [r0] - and r3, r3, ip - ldr r4, [r0] - orr r3, r3, r4, lsl #16 - - str r3, [r1], #4 - -.no_insw_2: tst r2, #1 - ldrne r3, [r0] - strneb r3, [r1], #1 - movne r3, r3, lsr #8 - strneb r3, [r1] - LOADREGS(fd, sp!, {r4, r5, r6, pc}) +ENTRY(insb) + teq r2, #0 + RETINSTR(moveq, pc, lr) + addr r0 + b __arch_readsb @ Purpose: write a block of data from memory to a hardware register. @ Proto : outsw(int to_reg, void *from, int len_in_words); @ Notes : increments from -.outsw_align: tst r1, #1 - bne .iosw_bad_alignment - - add r1, r1, #2 - - ldr r3, [r1, #-4] - mov r3, r3, lsr #16 - orr r3, r3, r3, lsl #16 - str r3, [r0] - subs r2, r2, #1 - bne .outsw_aligned - ENTRY(outsw) teq r2, #0 - RETINSTR(moveq,pc,lr) + RETINSTR(moveq, pc, lr) addr r0 - tst r1, #3 - bne .outsw_align - -.outsw_aligned: stmfd sp!, {r4, r5, r6, lr} - - subs r2, r2, #8 - bmi .no_outsw_8 -.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6} - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r4, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r4, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r5, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r5, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r6, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r6, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - subs r2, r2, #8 - bpl .outsw_8_lp - tst r2, #7 - LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) - -.no_outsw_8: tst r2, #4 - beq .no_outsw_4 - - ldmia r1!, {r3, r4} - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - - mov ip, r4, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r4, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - -.no_outsw_4: tst r2, #2 - beq .no_outsw_2 - - ldr r3, [r1], #4 - - mov ip, r3, lsl #16 - orr ip, ip, ip, lsr #16 - str ip, [r0] - - mov ip, r3, lsr #16 - orr ip, ip, ip, lsl #16 - str ip, [r0] - -.no_outsw_2: tst r2, #1 - - ldrne r3, [r1] - - movne ip, r3, lsl #16 - orrne ip, ip, ip, lsr #16 - strne ip, [r0] - - LOADREGS(fd, sp!, {r4, r5, r6, pc}) - -.insb_align: rsb ip, ip, #4 - cmp ip, r2 - movgt ip, r2 - cmp ip, #2 - ldrb r3, [r0] - strb r3, [r1], #1 - ldrgeb r3, [r0] - strgeb r3, [r1], #1 - ldrgtb r3, [r0] - strgtb r3, [r1], #1 - subs r2, r2, ip - bne .insb_aligned - -ENTRY(insb) - teq r2, #0 - moveq pc, lr - addr r0 - ands ip, r1, #3 - bne .insb_align - -.insb_aligned: stmfd sp!, {r4 - r6, lr} - - subs r2, r2, #16 - bmi .insb_no_16 - -.insb_16_lp: ldrb r3, [r0] - ldrb r4, [r0] - orr r3, r3, r4, lsl #8 - ldrb r4, [r0] - orr r3, r3, r4, lsl #16 - ldrb r4, [r0] - orr r3, r3, r4, lsl #24 - ldrb r4, [r0] - ldrb r5, [r0] - orr r4, r4, r5, lsl #8 - ldrb r5, [r0] - orr r4, r4, r5, lsl #16 - ldrb r5, [r0] - orr r4, r4, r5, lsl #24 - ldrb r5, [r0] - ldrb r6, [r0] - orr r5, r5, r6, lsl #8 - ldrb r6, [r0] - orr r5, r5, r6, lsl #16 - ldrb r6, [r0] - orr r5, r5, r6, lsl #24 - ldrb r6, [r0] - ldrb ip, [r0] - orr r6, r6, ip, lsl #8 - ldrb ip, [r0] - orr r6, r6, ip, lsl #16 - ldrb ip, [r0] - orr r6, r6, ip, lsl #24 - stmia r1!, {r3 - r6} - subs r2, r2, #16 - bpl .insb_16_lp - - tst r2, #15 - LOADREGS(eqfd, sp!, {r4 - r6, pc}) - -.insb_no_16: tst r2, #8 - beq .insb_no_8 - - ldrb r3, [r0] - ldrb r4, [r0] - orr r3, r3, r4, lsl #8 - ldrb r4, [r0] - orr r3, r3, r4, lsl #16 - ldrb r4, [r0] - orr r3, r3, r4, lsl #24 - ldrb r4, [r0] - ldrb r5, [r0] - orr r4, r4, r5, lsl #8 - ldrb r5, [r0] - orr r4, r4, r5, lsl #16 - ldrb r5, [r0] - orr r4, r4, r5, lsl #24 - stmia r1!, {r3, r4} - -.insb_no_8: tst r2, #4 - bne .insb_no_4 - - ldrb r3, [r0] - ldrb r4, [r0] - orr r3, r3, r4, lsl #8 - ldrb r4, [r0] - orr r3, r3, r4, lsl #16 - ldrb r4, [r0] - orr r3, r3, r4, lsl #24 - str r3, [r1], #4 - -.insb_no_4: ands r2, r2, #3 - LOADREGS(eqfd, sp!, {r4 - r6, pc}) - cmp r2, #2 - ldrb r3, [r0] - strb r3, [r1], #1 - ldrgeb r3, [r0] - strgeb r3, [r1], #1 - ldrgtb r3, [r0] - strgtb r3, [r1] - LOADREGS(fd, sp!, {r4 - r6, pc}) - - - -.outsb_align: rsb ip, ip, #4 - cmp ip, r2 - mov ip, r2 - cmp ip, #2 - ldrb r3, [r1], #1 - strb r3, [r0] - ldrgeb r3, [r1], #1 - strgeb r3, [r0] - ldrgtb r3, [r1], #1 - strgtb r3, [r0] - subs r2, r2, ip - bne .outsb_aligned + b __arch_writesw ENTRY(outsb) teq r2, #0 - moveq pc, lr + RETINSTR(moveq, pc, lr) addr r0 - ands ip, r1, #3 - bne .outsb_align - -.outsb_aligned: stmfd sp!, {r4 - r6, lr} - - subs r2, r2, #16 - bmi .outsb_no_16 - -.outsb_16_lp: ldmia r1!, {r3 - r6} - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - - strb r4, [r0] - mov r4, r4, lsr #8 - strb r4, [r0] - mov r4, r4, lsr #8 - strb r4, [r0] - mov r4, r4, lsr #8 - strb r4, [r0] - - strb r5, [r0] - mov r5, r5, lsr #8 - strb r5, [r0] - mov r5, r5, lsr #8 - strb r5, [r0] - mov r5, r5, lsr #8 - strb r5, [r0] - - strb r6, [r0] - mov r6, r6, lsr #8 - strb r6, [r0] - mov r6, r6, lsr #8 - strb r6, [r0] - mov r6, r6, lsr #8 - strb r6, [r0] - subs r2, r2, #16 - bpl .outsb_16_lp - - tst r2, #15 - LOADREGS(eqfd, sp!, {r4 - r6, pc}) - -.outsb_no_16: tst r2, #8 - beq .outsb_no_8 - - ldmia r1, {r3, r4} - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - - strb r4, [r0] - mov r4, r4, lsr #8 - strb r4, [r0] - mov r4, r4, lsr #8 - strb r4, [r0] - mov r4, r4, lsr #8 - strb r4, [r0] - -.outsb_no_8: tst r2, #4 - bne .outsb_no_4 - - ldr r3, [r1], #4 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - mov r3, r3, lsr #8 - strb r3, [r0] - -.outsb_no_4: ands r2, r2, #3 - LOADREGS(eqfd, sp!, {r4 - r6, pc}) - cmp r2, #2 - ldrb r3, [r1], #1 - strb r3, [r0] - ldrgeb r3, [r1], #1 - strgeb r3, [r0] - ldrgtb r3, [r1] - strgtb r3, [r0] - LOADREGS(fd, sp!, {r4 - r6, pc}) - - - + b __arch_writesb @ Purpose: write a memc register @ Proto : void memc_write(int register, int value); @@ -488,146 +102,5 @@ add r0, r0, #0x03600000 strb r0, [r0] RETINSTR(mov,pc,lr) -#define CPSR2SPSR(rt) -#else -#define CPSR2SPSR(rt) \ - mrs rt, cpsr; \ - msr spsr, rt -#endif - -@ Purpose: call an expansion card loader to read bytes. -@ Proto : char read_loader(int offset, char *card_base, char *loader); -@ Returns: byte read - -ENTRY(ecard_loader_read) - stmfd sp!, {r4 - r12, lr} - mov r11, r1 - mov r1, r0 - CPSR2SPSR(r0) - mov lr, pc - mov pc, r2 - LOADREGS(fd, sp!, {r4 - r12, pc}) - -@ Purpose: call an expansion card loader to reset the card -@ Proto : void read_loader(int card_base, char *loader); -@ Returns: byte read - -ENTRY(ecard_loader_reset) - stmfd sp!, {r4 - r12, lr} - mov r11, r0 - CPSR2SPSR(r0) - mov lr, pc - add pc, r1, #8 - LOADREGS(fd, sp!, {r4 - r12, pc}) - - -#if 0 - mov r2, r2, lsl#1 - mov ip, sp - stmfd sp!, {r4 - r10, fp, ip, lr, pc} - sub fp, ip, #4 - addr r3, r0 - add r0, r3, r0, lsl #2 - tst r1, #3 - beq Linswok - tst r1, #1 - bne Linsw_notaligned - cmp r2, #1 - ldrge r4, [r0] - strgeb r4, [r1], #1 - movgt r4, r4, LSR#8 - strgtb r4, [r1], #1 - LOADREGS(leea, fp, {r4 - r10, fp, sp, pc}) - sub r2, r2, #2 -Linswok: mov ip, #0xFF - orr ip, ip, ip, lsl #8 -Linswlp: subs r2, r2, #64 - bmi Linsw_toosmall - IN(r3) - IN(r4) - IN(r5) - IN(r6) - IN(r7) - IN(r8) - IN(r9) - IN(r10) - stmia r1!, {r3 - r10} - IN(r3) - IN(r4) - IN(r5) - IN(r6) - IN(r7) - IN(r8) - IN(r9) - IN(r10) - stmia r1!, {r3 - r10} - bne Linswlp - LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) -Linsw_toosmall: - adds r2, r2, #32 - bmi Linsw_toosmall2 -Linsw2lp: IN(r3) - IN(r4) - IN(r5) - IN(r6) - IN(r7) - IN(r8) - IN(r9) - IN(r10) - stmia r1!, {r3 - r10} - LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc}) - b Linsw_notaligned -Linsw_toosmall2: - add r2, r2, #32 -Linsw_notaligned: - cmp r2, #1 - LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc}) - ldr r4, [r0] - strb r4, [r1], #1 - movgt r4, r4, LSR#8 - strgtb r4, [r1], #1 - subs r2, r2, #2 - bgt Linsw_notaligned - LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) - - -ENTRY(outsw) - mov r2, r2, lsl#1 - mov ip, sp - stmfd sp!, {r4 - r8, fp, ip, lr, pc} - sub fp, ip, #4 - addr r3, r0 - tst r1, #2 - beq 1f - ldr r4, [r1], #2 - mov r4, r4, lsl #16 - orr r4, r4, r4, lsr #16 - str r4, [r3, r0, lsl #2] - subs r2, r2, #2 - LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) -1: subs r2, r2, #32 - blt 2f - ldmia r1!, {r4, r5, r6, r7} - OUT(r4) - OUT(r5) - OUT(r6) - OUT(r7) - ldmia r1!, {r4, r5, r6, r7} - OUT(r4) - OUT(r5) - OUT(r6) - OUT(r7) - bne 1b - LOADREGS(ea, fp, {r4 - r8, fp, sp, pc}) -2: adds r2, r2, #32 - LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) -3: ldr r4, [r1],#2 - mov r4, r4, lsl#16 - orr r4, r4, r4, lsr#16 - str r4, [r3, r0, lsl#2] - subs r2, r2, #2 - bgt 3b - LOADREGS(ea, fp, {r4 - r8, fp, sp, pc}) - #endif diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-ebsa110.S linux/arch/arm/lib/io-ebsa110.S --- v2.4.0-test11/linux/arch/arm/lib/io-ebsa110.S Sun Oct 8 10:50:05 2000 +++ linux/arch/arm/lib/io-ebsa110.S Wed Dec 31 16:00:00 1969 @@ -1,169 +0,0 @@ -/* - * linux/arch/arm/lib/io-ebsa.S - * - * Copyright (C) 1995, 1996 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include -#include - .text - .align - -#define OUT(reg) \ - mov r8, reg, lsl $16 ;\ - orr r8, r8, r8, lsr $16 ;\ - str r8, [r3, r0, lsl $2] ;\ - mov r8, reg, lsr $16 ;\ - orr r8, r8, r8, lsl $16 ;\ - str r8, [r3, r0, lsl $2] - -#define IN(reg) \ - ldr reg, [r0] ;\ - and reg, reg, ip ;\ - ldr lr, [r0] ;\ - orr reg, reg, lr, lsl $16 - -/* - * These make no sense on these machines. - * Print a warning message. - */ -ENTRY(insl) -ENTRY(outsl) -ENTRY(insb) -ENTRY(outsb) - adr r0, io_long_warning - mov r1, lr - b SYMBOL_NAME(printk) - -io_long_warning: - .ascii "<4>ins?/outs? not implemented on this architecture\0" - .align - -@ Purpose: read a block of data from a hardware register to memory. -@ Proto : insw(int from_port, void *to, int len_in_words); -@ Proto : inswb(int from_port, void *to, int len_in_bytes); -@ Notes : increment to - -ENTRY(insw) - mov r2, r2, lsl#1 -ENTRY(inswb) - mov ip, sp - stmfd sp!, {r4 - r10 ,fp ,ip ,lr ,pc} - sub fp, ip, #4 - cmp r0, #0x00c00000 - movge r3, #0 - movlt r3, #0xf0000000 - add r0, r3, r0, lsl #2 - tst r1, #3 - beq Linswok - tst r1, #1 - bne Linsw_notaligned - cmp r2, #1 - ldrge r4, [r0] - strgeb r4, [r1], #1 - movgt r4, r4, LSR#8 - strgtb r4, [r1], #1 - ldmleea fp, {r4 - r10, fp, sp, pc}^ - sub r2, r2, #2 -Linswok: mov ip, #0xFF - orr ip, ip, ip, lsl #8 -Linswlp: subs r2, r2, #64 - bmi Linsw_toosmall - IN(r3) - IN(r4) - IN(r5) - IN(r6) - IN(r7) - IN(r8) - IN(r9) - IN(r10) - stmia r1!, {r3 - r10} - IN(r3) - IN(r4) - IN(r5) - IN(r6) - IN(r7) - IN(r8) - IN(r9) - IN(r10) - stmia r1!, {r3 - r10} - bne Linswlp - LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) -Linsw_toosmall: - add r2, r2, #32 - bmi Linsw_toosmall2 -Linsw2lp: IN(r3) - IN(r4) - IN(r5) - IN(r6) - IN(r7) - IN(r8) - IN(r9) - IN(r10) - stmia r1!, {r3 - r10} - LOADREGS(eqea, fp, {r4 - r10, fp, sp, pc}) - b Linsw_notaligned -Linsw_toosmall2: - add r2, r2, #32 -Linsw_notaligned: - cmp r2, #1 - LOADREGS(ltea, fp, {r4 - r10, fp, sp, pc}) - ldr r4, [r0] - strb r4, [r1], #1 - movgt r4, r4, LSR#8 - strgtb r4, [r1], #1 - subs r2, r2, #2 - bgt Linsw_notaligned - LOADREGS(ea, fp, {r4 - r10, fp, sp, pc}) - -@ Purpose: write a block of data from memory to a hardware register. -@ Proto : outsw(int to_reg, void *from, int len_in_words); -@ Proto : outswb(int to_reg, void *from, int len_in_bytes); -@ Notes : increments from - -ENTRY(outsw) - mov r2, r2, LSL#1 -ENTRY(outswb) - mov ip, sp - stmfd sp!, {r4 - r8, fp, ip, lr, pc} - sub fp, ip, #4 - cmp r0, #0x00c00000 - movge r3, #0 - movlt r3, #0xf0000000 - tst r1, #2 - beq Loutsw32lp - ldr r4, [r1], #2 - mov r4, r4, lsl #16 - orr r4, r4, r4, lsr #16 - str r4, [r3, r0, lsl #2] - sub r2, r2, #2 - teq r2, #0 - LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) -Loutsw32lp: subs r2,r2,#32 - blt Loutsw_toosmall - ldmia r1!,{r4,r5,r6,r7} - OUT(r4) - OUT(r5) - OUT(r6) - OUT(r7) - ldmia r1!,{r4,r5,r6,r7} - OUT(r4) - OUT(r5) - OUT(r6) - OUT(r7) - LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) - b Loutsw32lp -Loutsw_toosmall: - adds r2,r2,#32 - LOADREGS(eqea, fp, {r4 - r8, fp, sp, pc}) -Llpx: ldr r4,[r1],#2 - mov r4,r4,LSL#16 - orr r4,r4,r4,LSR#16 - str r4,[r3,r0,LSL#2] - subs r2,r2,#2 - bgt Llpx - LOADREGS(ea, fp, {r4 - r8, fp, sp, pc}) - diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-footbridge.S linux/arch/arm/lib/io-footbridge.S --- v2.4.0-test11/linux/arch/arm/lib/io-footbridge.S Thu Jan 13 13:30:31 2000 +++ linux/arch/arm/lib/io-footbridge.S Wed Dec 31 16:00:00 1969 @@ -1,202 +0,0 @@ -#include -#include - - .equ pcio_high, PCIO_BASE & 0xff000000 - .equ pcio_low, PCIO_BASE & 0x00ffffff - - .macro ioaddr, rd,rn - add \rd, \rn, #pcio_high - .if pcio_low - add \rd, \rd, #pcio_low - .endif - .endm - -ENTRY(insl) - ioaddr r0, r0 - ands ip, r1, #3 - bne 2f - -1: ldr r3, [r0] - str r3, [r1], #4 - subs r2, r2, #1 - bne 1b - mov pc, lr - -2: cmp ip, #2 - ldr ip, [r0] - blt 4f - bgt 6f - - strh ip, [r1], #2 - mov ip, ip, lsr #16 -3: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #16 - strne ip, [r1], #4 - movne ip, r3, lsr #16 - bne 3b - strh ip, [r1], #2 - mov pc, lr - -4: strb ip, [r1], #1 - mov ip, ip, lsr #8 - strh ip, [r1], #2 - mov ip, ip, lsr #16 -5: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #8 - strne ip, [r1], #4 - movne ip, r3, lsr #24 - bne 5b - strb ip, [r1], #1 - mov pc, lr - -6: strb ip, [r1], #1 - mov ip, ip, lsr #8 -7: subs r2, r2, #1 - ldrne r3, [r0] - orrne ip, ip, r3, lsl #24 - strne ip, [r1], #4 - movne ip, r3, lsr #8 - bne 7b - strb ip, [r1], #1 - mov ip, ip, lsr #8 - strh ip, [r1], #2 - mov pc, lr - -ENTRY(outsl) - ioaddr r0, r0 - ands ip, r1, #3 - bne 2f - -1: ldr r3, [r1], #4 - str r3, [r0] - subs r2, r2, #1 - bne 1b - mov pc, lr - -2: bic r1, r1, #3 - cmp ip, #2 - ldr ip, [r1], #4 - mov ip, ip, lsr #16 - blt 4f - bgt 5f - -3: ldr r3, [r1], #4 - orr ip, ip, r3, lsl #16 - str ip, [r0] - mov ip, r3, lsr #16 - subs r2, r2, #1 - bne 3b - mov pc, lr - -4: ldr r3, [r1], #4 - orr ip, ip, r3, lsl #8 - str ip, [r0] - mov ip, r3, lsr #24 - subs r2, r2, #1 - bne 4b - mov pc, lr - -5: ldr r3, [r1], #4 - orr ip, ip, r3, lsl #24 - str ip, [r0] - mov ip, r3, lsr #8 - subs r2, r2, #1 - bne 5b - mov pc, lr - - /* Nobody could say these are optimal, but not to worry. */ - -ENTRY(outswb) - mov r2, r2, lsr #1 -ENTRY(outsw) - ioaddr r0, r0 -1: subs r2, r2, #1 - ldrgeh r3, [r1], #2 - strgeh r3, [r0] - bgt 1b - mov pc, lr - -ENTRY(inswb) - mov r2, r2, lsr #1 -ENTRY(insw) - stmfd sp!, {r4, r5, lr} - ioaddr r0, r0 - @ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17 - subs ip, r2, #8 - blo too_little - @ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 - ands lr, r1, #3 @ check alignment - beq 1f - - ldrh r3, [r0] - strh r3, [r1], #2 - sub ip, ip, #1 - cmn ip, #8 - blo too_little - -1: ldrh r2, [r0] - ldrh r3, [r0] - orr r2, r2, r3, lsl #16 - ldrh r3, [r0] - ldrh r4, [r0] - orr r3, r3, r4, lsl #16 - ldrh r4, [r0] - ldrh r5, [r0] - orr r4, r4, r5, lsl #16 - ldrh r5, [r0] - ldrh lr, [r0] - orr r5, r5, lr, lsl #16 - stmia r1!, {r2, r3, r4, r5} - subs ip, ip, #8 - @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 + 0 + 1 - bhs 1b - @ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 8 - 7 - cmn ip, #4 - ldrhsh r2, [r0] @ ... ... ... ... - 4 - 3 - 2 - 1 ... ... - ldrhsh r3, [r0] - orrhs r2, r2, r3, lsl #16 - ldrhsh r3, [r0] - ldrhsh r4, [r0] - orrhs r3, r3, r4, lsl #16 - stmhsia r1!, {r2, r3} - - tst ip, #2 - ldrneh r2, [r0] @ ... ... - 6 - 5 ... ... - 2 - 1 ... ... - ldrneh r3, [r0] - orrne r2, r2, r3, lsl #16 - strne r2, [r1], #4 - - tst ip, #1 - ldrneh r2, [r0] - strneh r2, [r1], #2 - - ldmfd sp!, {r4, r5, pc} - -too_little: subs r2, r2, #1 - ldrgeh r3, [r0] - strgeh r3, [r1], #2 - bgt too_little - - ldmfd sp!, {r4, r5, pc} - - -ENTRY(insb) - ioaddr r0, r0 -1: teq r2, #0 - ldrneb r3, [r0] - strneb r3, [r1], #1 - subne r2, r2, #1 - bne 1b - mov pc, lr - - -ENTRY(outsb) - ioaddr r0, r0 -1: teq r2, #0 - ldrneb r3, [r1], #1 - strneb r3, [r0] - subne r2, r2, #1 - bne 1b - mov pc, lr diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-pcio.S linux/arch/arm/lib/io-pcio.S --- v2.4.0-test11/linux/arch/arm/lib/io-pcio.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-pcio.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,38 @@ +#include +#include + + .equ pcio_high, PCIO_BASE & 0xff000000 + .equ pcio_low, PCIO_BASE & 0x00ffffff + + .macro ioaddr, rd,rn + add \rd, \rn, #pcio_high + .if pcio_low + add \rd, \rd, #pcio_low + .endif + .endm + +ENTRY(insl) + ioaddr r0, r0 + b __arch_readsl + +ENTRY(outsl) + ioaddr r0, r0 + b __arch_writesl + + /* Nobody could say these are optimal, but not to worry. */ + +ENTRY(outsw) + ioaddr r0, r0 + b __arch_writesw + +ENTRY(insw) + ioaddr r0, r0 + b __arch_readsw + +ENTRY(insb) + ioaddr r0, r0 + b __arch_readsb + +ENTRY(outsb) + ioaddr r0, r0 + b __arch_writesb diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-readsb.S linux/arch/arm/lib/io-readsb.S --- v2.4.0-test11/linux/arch/arm/lib/io-readsb.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-readsb.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,111 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +.insb_align: rsb ip, ip, #4 + cmp ip, r2 + movgt ip, r2 + cmp ip, #2 + ldrb r3, [r0] + strb r3, [r1], #1 + ldrgeb r3, [r0] + strgeb r3, [r1], #1 + ldrgtb r3, [r0] + strgtb r3, [r1], #1 + subs r2, r2, ip + bne .insb_aligned + +ENTRY(__arch_readsb) + ands ip, r1, #3 + bne .insb_align + +.insb_aligned: stmfd sp!, {r4 - r6, lr} + + subs r2, r2, #16 + bmi .insb_no_16 + +.insb_16_lp: ldrb r3, [r0] + ldrb r4, [r0] + orr r3, r3, r4, lsl #8 + ldrb r4, [r0] + orr r3, r3, r4, lsl #16 + ldrb r4, [r0] + orr r3, r3, r4, lsl #24 + ldrb r4, [r0] + ldrb r5, [r0] + orr r4, r4, r5, lsl #8 + ldrb r5, [r0] + orr r4, r4, r5, lsl #16 + ldrb r5, [r0] + orr r4, r4, r5, lsl #24 + ldrb r5, [r0] + ldrb r6, [r0] + orr r5, r5, r6, lsl #8 + ldrb r6, [r0] + orr r5, r5, r6, lsl #16 + ldrb r6, [r0] + orr r5, r5, r6, lsl #24 + ldrb r6, [r0] + ldrb ip, [r0] + orr r6, r6, ip, lsl #8 + ldrb ip, [r0] + orr r6, r6, ip, lsl #16 + ldrb ip, [r0] + orr r6, r6, ip, lsl #24 + stmia r1!, {r3 - r6} + subs r2, r2, #16 + bpl .insb_16_lp + + tst r2, #15 + LOADREGS(eqfd, sp!, {r4 - r6, pc}) + +.insb_no_16: tst r2, #8 + beq .insb_no_8 + + ldrb r3, [r0] + ldrb r4, [r0] + orr r3, r3, r4, lsl #8 + ldrb r4, [r0] + orr r3, r3, r4, lsl #16 + ldrb r4, [r0] + orr r3, r3, r4, lsl #24 + ldrb r4, [r0] + ldrb r5, [r0] + orr r4, r4, r5, lsl #8 + ldrb r5, [r0] + orr r4, r4, r5, lsl #16 + ldrb r5, [r0] + orr r4, r4, r5, lsl #24 + stmia r1!, {r3, r4} + +.insb_no_8: tst r2, #4 + bne .insb_no_4 + + ldrb r3, [r0] + ldrb r4, [r0] + orr r3, r3, r4, lsl #8 + ldrb r4, [r0] + orr r3, r3, r4, lsl #16 + ldrb r4, [r0] + orr r3, r3, r4, lsl #24 + str r3, [r1], #4 + +.insb_no_4: ands r2, r2, #3 + LOADREGS(eqfd, sp!, {r4 - r6, pc}) + cmp r2, #2 + ldrb r3, [r0] + strb r3, [r1], #1 + ldrgeb r3, [r0] + strgeb r3, [r1], #1 + ldrgtb r3, [r0] + strgtb r3, [r1] + LOADREGS(fd, sp!, {r4 - r6, pc}) diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-readsl.S linux/arch/arm/lib/io-readsl.S --- v2.4.0-test11/linux/arch/arm/lib/io-readsl.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-readsl.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,65 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +ENTRY(__arch_readsl) + ands ip, r1, #3 + bne 2f + +1: ldr r3, [r0] + str r3, [r1], #4 + subs r2, r2, #1 + bne 1b + mov pc, lr + +2: cmp ip, #2 + ldr ip, [r0] + blt 4f + bgt 6f + + strh ip, [r1], #2 + mov ip, ip, lsr #16 +3: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #16 + strne ip, [r1], #4 + movne ip, r3, lsr #16 + bne 3b + strh ip, [r1], #2 + mov pc, lr + +4: strb ip, [r1], #1 + mov ip, ip, lsr #8 + strh ip, [r1], #2 + mov ip, ip, lsr #16 +5: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #8 + strne ip, [r1], #4 + movne ip, r3, lsr #24 + bne 5b + strb ip, [r1], #1 + mov pc, lr + +6: strb ip, [r1], #1 + mov ip, ip, lsr #8 +7: subs r2, r2, #1 + ldrne r3, [r0] + orrne ip, ip, r3, lsl #24 + strne ip, [r1], #4 + movne ip, r3, lsr #8 + bne 7b + strb ip, [r1], #1 + mov ip, ip, lsr #8 + strh ip, [r1], #2 + mov pc, lr + diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-readsw-armv3.S linux/arch/arm/lib/io-readsw-armv3.S --- v2.4.0-test11/linux/arch/arm/lib/io-readsw-armv3.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-readsw-armv3.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,102 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +.insw_bad_alignment: + adr r0, .insw_bad_align_msg + mov r2, lr + b SYMBOL_NAME(panic) +.insw_bad_align_msg: + .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" + .align + +.insw_align: tst r1, #1 + bne .insw_bad_alignment + + ldr r3, [r0] + strb r3, [r1], #1 + mov r3, r3, lsr #8 + strb r3, [r1], #1 + + subs r2, r2, #1 + RETINSTR(moveq, pc, lr) + +ENTRY(__arch_readsw) + tst r1, #3 + bne .insw_align + +.insw_aligned: mov ip, #0xff + orr ip, ip, ip, lsl #8 + stmfd sp!, {r4, r5, r6, lr} + + subs r2, r2, #8 + bmi .no_insw_8 + +.insw_8_lp: ldr r3, [r0] + and r3, r3, ip + ldr r4, [r0] + orr r3, r3, r4, lsl #16 + + ldr r4, [r0] + and r4, r4, ip + ldr r5, [r0] + orr r4, r4, r5, lsl #16 + + ldr r5, [r0] + and r5, r5, ip + ldr r6, [r0] + orr r5, r5, r6, lsl #16 + + ldr r6, [r0] + and r6, r6, ip + ldr lr, [r0] + orr r6, r6, lr, lsl #16 + + stmia r1!, {r3 - r6} + subs r2, r2, #8 + bpl .insw_8_lp + tst r2, #7 + LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) + +.no_insw_8: tst r2, #4 + beq .no_insw_4 + + ldr r3, [r0] + and r3, r3, ip + ldr r4, [r0] + orr r3, r3, r4, lsl #16 + + ldr r4, [r0] + and r4, r4, ip + ldr r5, [r0] + orr r4, r4, r5, lsl #16 + + stmia r1!, {r3, r4} + +.no_insw_4: tst r2, #2 + beq .no_insw_2 + + ldr r3, [r0] + and r3, r3, ip + ldr r4, [r0] + orr r3, r3, r4, lsl #16 + + str r3, [r1], #4 + +.no_insw_2: tst r2, #1 + ldrne r3, [r0] + strneb r3, [r1], #1 + movne r3, r3, lsr #8 + strneb r3, [r1] + LOADREGS(fd, sp!, {r4, r5, r6, pc}) + + diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-readsw-armv4.S linux/arch/arm/lib/io-readsw-armv4.S --- v2.4.0-test11/linux/arch/arm/lib/io-readsw-armv4.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-readsw-armv4.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,87 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +.insw_bad_alignment: + adr r0, .insw_bad_align_msg + mov r2, lr + b SYMBOL_NAME(panic) +.insw_bad_align_msg: + .asciz "insw: bad buffer alignment (0x%p, lr=0x%08lX)\n" + .align + +.insw_align: tst r1, #1 + bne .insw_bad_alignment + + ldrh r3, [r0] + strh r3, [r1], #2 + + subs r2, r2, #1 + RETINSTR(moveq, pc, lr) + +ENTRY(__arch_readsw) + tst r1, #3 + bne .insw_align + + stmfd sp!, {r4, r5, lr} + + subs r2, r2, #8 + bmi .no_insw_8 + +.insw_8_lp: ldrh r3, [r0] + ldrh r4, [r0] + orr r3, r3, r4, lsl #16 + + ldrh r4, [r0] + ldrh r5, [r0] + orr r4, r4, r5, lsl #16 + + ldrh r5, [r0] + ldrh r6, [r0] + orr r5, r5, r6, lsl #16 + + ldrh ip, [r0] + ldrh lr, [r0] + orr ip, ip, lr, lsl #16 + + stmia r1!, {r3 - r5, ip} + subs r2, r2, #8 + bpl .insw_8_lp + tst r2, #7 + LOADREGS(eqfd, sp!, {r4, r5, pc}) + +.no_insw_8: tst r2, #4 + beq .no_insw_4 + + ldrh r3, [r0] + ldrh r4, [r0] + orr r3, r3, r4, lsl #16 + + ldrh r4, [r0] + ldrh ip, [r0] + orr r4, r4, ip, lsl #16 + + stmia r1!, {r3, r4} + +.no_insw_4: tst r2, #2 + beq .no_insw_2 + + ldrh r3, [r0] + ldrh ip, [r0] + orr r3, r3, ip, lsl #16 + + str r3, [r1], #4 + +.no_insw_2: tst r2, #1 + ldrneh r3, [r0] + strneh r3, [r1] + LOADREGS(fd, sp!, {r4, r5, pc}) diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-writesb.S linux/arch/arm/lib/io-writesb.S --- v2.4.0-test11/linux/arch/arm/lib/io-writesb.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-writesb.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,115 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +.outsb_align: rsb ip, ip, #4 + cmp ip, r2 + mov ip, r2 + cmp ip, #2 + ldrb r3, [r1], #1 + strb r3, [r0] + ldrgeb r3, [r1], #1 + strgeb r3, [r0] + ldrgtb r3, [r1], #1 + strgtb r3, [r0] + subs r2, r2, ip + bne .outsb_aligned + +ENTRY(__arch_writesb) + ands ip, r1, #3 + bne .outsb_align + +.outsb_aligned: stmfd sp!, {r4 - r6, lr} + + subs r2, r2, #16 + bmi .outsb_no_16 + +.outsb_16_lp: ldmia r1!, {r3 - r6} + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + + strb r4, [r0] + mov r4, r4, lsr #8 + strb r4, [r0] + mov r4, r4, lsr #8 + strb r4, [r0] + mov r4, r4, lsr #8 + strb r4, [r0] + + strb r5, [r0] + mov r5, r5, lsr #8 + strb r5, [r0] + mov r5, r5, lsr #8 + strb r5, [r0] + mov r5, r5, lsr #8 + strb r5, [r0] + + strb r6, [r0] + mov r6, r6, lsr #8 + strb r6, [r0] + mov r6, r6, lsr #8 + strb r6, [r0] + mov r6, r6, lsr #8 + strb r6, [r0] + subs r2, r2, #16 + bpl .outsb_16_lp + + tst r2, #15 + LOADREGS(eqfd, sp!, {r4 - r6, pc}) + +.outsb_no_16: tst r2, #8 + beq .outsb_no_8 + + ldmia r1, {r3, r4} + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + + strb r4, [r0] + mov r4, r4, lsr #8 + strb r4, [r0] + mov r4, r4, lsr #8 + strb r4, [r0] + mov r4, r4, lsr #8 + strb r4, [r0] + +.outsb_no_8: tst r2, #4 + bne .outsb_no_4 + + ldr r3, [r1], #4 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + mov r3, r3, lsr #8 + strb r3, [r0] + +.outsb_no_4: ands r2, r2, #3 + LOADREGS(eqfd, sp!, {r4 - r6, pc}) + cmp r2, #2 + ldrb r3, [r1], #1 + strb r3, [r0] + ldrgeb r3, [r1], #1 + strgeb r3, [r0] + ldrgtb r3, [r1] + strgtb r3, [r0] + LOADREGS(fd, sp!, {r4 - r6, pc}) diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-writesl.S linux/arch/arm/lib/io-writesl.S --- v2.4.0-test11/linux/arch/arm/lib/io-writesl.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-writesl.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,55 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +ENTRY(__arch_writesl) + ands ip, r1, #3 + bne 2f + +1: ldr r3, [r1], #4 + str r3, [r0] + subs r2, r2, #1 + bne 1b + mov pc, lr + +2: bic r1, r1, #3 + cmp ip, #2 + ldr ip, [r1], #4 + mov ip, ip, lsr #16 + blt 4f + bgt 5f + +3: ldr r3, [r1], #4 + orr ip, ip, r3, lsl #16 + str ip, [r0] + mov ip, r3, lsr #16 + subs r2, r2, #1 + bne 3b + mov pc, lr + +4: ldr r3, [r1], #4 + orr ip, ip, r3, lsl #8 + str ip, [r0] + mov ip, r3, lsr #24 + subs r2, r2, #1 + bne 4b + mov pc, lr + +5: ldr r3, [r1], #4 + orr ip, ip, r3, lsl #24 + str ip, [r0] + mov ip, r3, lsr #8 + subs r2, r2, #1 + bne 5b + mov pc, lr + + diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-writesw-armv3.S linux/arch/arm/lib/io-writesw-armv3.S --- v2.4.0-test11/linux/arch/arm/lib/io-writesw-armv3.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-writesw-armv3.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,125 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +.outsw_bad_alignment: + adr r0, .outsw_bad_align_msg + mov r2, lr + b SYMBOL_NAME(panic) +.outsw_bad_align_msg: + .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" + .align + +.outsw_align: tst r1, #1 + bne .outsw_bad_alignment + + add r1, r1, #2 + + ldr r3, [r1, #-4] + mov r3, r3, lsr #16 + orr r3, r3, r3, lsl #16 + str r3, [r0] + subs r2, r2, #1 + RETINSTR(moveq, pc, lr) + +ENTRY(__arch_writesw) + tst r1, #3 + bne .outsw_align + +.outsw_aligned: stmfd sp!, {r4, r5, r6, lr} + + subs r2, r2, #8 + bmi .no_outsw_8 +.outsw_8_lp: ldmia r1!, {r3, r4, r5, r6} + + mov ip, r3, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r3, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r4, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r4, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r5, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r5, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r6, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r6, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + subs r2, r2, #8 + bpl .outsw_8_lp + tst r2, #7 + LOADREGS(eqfd, sp!, {r4, r5, r6, pc}) + +.no_outsw_8: tst r2, #4 + beq .no_outsw_4 + + ldmia r1!, {r3, r4} + + mov ip, r3, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r3, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + + mov ip, r4, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r4, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + +.no_outsw_4: tst r2, #2 + beq .no_outsw_2 + + ldr r3, [r1], #4 + + mov ip, r3, lsl #16 + orr ip, ip, ip, lsr #16 + str ip, [r0] + + mov ip, r3, lsr #16 + orr ip, ip, ip, lsl #16 + str ip, [r0] + +.no_outsw_2: tst r2, #1 + + ldrne r3, [r1] + + movne ip, r3, lsl #16 + orrne ip, ip, ip, lsr #16 + strne ip, [r0] + + LOADREGS(fd, sp!, {r4, r5, r6, pc}) + + diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/lib/io-writesw-armv4.S linux/arch/arm/lib/io-writesw-armv4.S --- v2.4.0-test11/linux/arch/arm/lib/io-writesw-armv4.S Wed Dec 31 16:00:00 1969 +++ linux/arch/arm/lib/io-writesw-armv4.S Mon Nov 27 17:07:59 2000 @@ -0,0 +1,79 @@ +/* + * linux/arch/arm/lib/io-readsb.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + +.outsw_bad_alignment: + adr r0, .outsw_bad_align_msg + mov r2, lr + b SYMBOL_NAME(panic) +.outsw_bad_align_msg: + .asciz "outsw: bad buffer alignment (0x%p, lr=0x%08lX)\n" + .align + +.outsw_align: tst r1, #1 + bne .outsw_bad_alignment + + ldrh r3, [r1], #2 + strh r3, [r0] + + subs r2, r2, #1 + RETINSTR(moveq, pc, lr) + +ENTRY(__arch_writesw) + tst r1, #3 + bne .outsw_align + + subs r2, r2, #8 + bmi .no_outsw_8 + + stmfd sp!, {r4, r5, lr} + +.outsw_8_lp: ldmia r1!, {r3, r4, r5, ip} + + strh r3, [r0] + mov r3, r3, lsr #16 + strh r3, [r0] + strh r4, [r0] + mov r4, r4, lsr #16 + strh r4, [r0] + strh r5, [r0] + mov r5, r5, lsr #16 + strh r5, [r0] + strh ip, [r0] + mov ip, ip, lsr #16 + strh ip, [r0] + + subs r2, r2, #8 + bpl .outsw_8_lp + ldmfd sp!, {r4, r5, lr} + tst r2, #7 + RETINSTR(moveq, pc, lr) + +.no_outsw_8: tst r2, #4 + ldmneia r1!, {r3, ip} + strneh r3, [r0] + movne r3, r3, lsr #16 + strneh r3, [r0] + strneh ip, [r0] + movne ip, ip, lsr #16 + strneh ip, [r0] + tst r2, #2 + ldrne r3, [r1], #4 + strneh r3, [r0] + movne r3, r3, lsr #16 + strneh r3, [r0] + tst r2, #1 + ldrneh r3, [r1] + strneh r3, [r0] + RETINSTR(mov, pc, lr) + + diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/mach-footbridge/netwinder-hw.c linux/arch/arm/mach-footbridge/netwinder-hw.c --- v2.4.0-test11/linux/arch/arm/mach-footbridge/netwinder-hw.c Tue Sep 5 12:56:51 2000 +++ linux/arch/arm/mach-footbridge/netwinder-hw.c Mon Nov 27 17:07:59 2000 @@ -65,9 +65,9 @@ */ spinlock_t gpio_lock = SPIN_LOCK_UNLOCKED; -static unsigned int current_gpio_op = 0; -static unsigned int current_gpio_io = 0; -static unsigned int current_cpld = 0; +static unsigned int current_gpio_op; +static unsigned int current_gpio_io; +static unsigned int current_cpld; void gpio_modify_op(int mask, int set) { diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c --- v2.4.0-test11/linux/arch/arm/mm/fault-common.c Sun Oct 8 10:50:06 2000 +++ linux/arch/arm/mm/fault-common.c Mon Nov 27 17:07:59 2000 @@ -126,6 +126,39 @@ return fault; } +static int __do_vmalloc_fault(unsigned long addr, struct mm_struct *mm) +{ + /* Synchronise this task's top level page-table + * with the 'reference' page table. + */ + int offset = __pgd_offset(addr); + pgd_t *pgd, *pgd_k; + pmd_t *pmd, *pmd_k; + + pgd_k = init_mm.pgd + offset; + if (!pgd_present(*pgd_k)) + goto bad_area; + + pgd = mm->pgd + offset; +#if 0 /* note that we are two-level */ + if (!pgd_present(*pgd)) + set_pgd(pgd, *pgd_k); +#endif + + pmd_k = pmd_offset(pgd_k, addr); + if (pmd_none(*pmd_k)) + goto bad_area; + + pmd = pmd_offset(pgd, addr); + if (!pmd_none(*pmd)) + goto bad_area; + set_pmd(pmd, *pmd_k); + return 1; + +bad_area: + return -2; +} + static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs) { struct task_struct *tsk; @@ -137,6 +170,18 @@ mm = tsk->mm; /* + * We fault-in kernel-space virtual memory on-demand. The + * 'reference' page table is init_mm.pgd. + * + * NOTE! We MUST NOT take any locks for this case. We may + * be in an interrupt or a critical region, and should + * only copy the information from the master page table, + * nothing more. + */ + if (addr >= TASK_SIZE) + goto vmalloc_fault; + + /* * If we're in an interrupt or have no user * context, we must not take the fault.. */ @@ -147,6 +192,7 @@ fault = __do_page_fault(mm, addr, mode, tsk); up(&mm->mmap_sem); +ret: /* * Handle the "normal" case first */ @@ -240,4 +286,8 @@ do_exit(SIGKILL); return 0; + +vmalloc_fault: + fault = __do_vmalloc_fault(addr, mm); + goto ret; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c --- v2.4.0-test11/linux/arch/arm/mm/init.c Tue Oct 31 12:42:25 2000 +++ linux/arch/arm/mm/init.c Mon Nov 27 17:07:59 2000 @@ -377,34 +377,48 @@ /* * Reserve the various regions of node 0 */ -static inline void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages) +static __init void reserve_node_zero(unsigned int bootmap_pfn, unsigned int bootmap_pages) { + pg_data_t *pgdat = NODE_DATA(0); + /* * Register the kernel text and data with bootmem. * Note that this can only be in node 0. */ - reserve_bootmem_node(NODE_DATA(0), __pa(&_stext), &_end - &_stext); + reserve_bootmem_node(pgdat, __pa(&_stext), &_end - &_stext); #ifdef CONFIG_CPU_32 /* * Reserve the page tables. These are already in use, * and can only be in node 0. */ - reserve_bootmem_node(NODE_DATA(0), __pa(swapper_pg_dir), + reserve_bootmem_node(pgdat, __pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(void *)); -#else - /* - * Stop this memory from being grabbed - its special DMA - * memory that is required for the screen. - */ - reserve_bootmem_node(NODE_DATA(0), 0x02000000, 0x00080000); #endif /* * And don't forget to reserve the allocator bitmap, * which will be freed later. */ - reserve_bootmem_node(NODE_DATA(0), bootmap_pfn << PAGE_SHIFT, + reserve_bootmem_node(pgdat, bootmap_pfn << PAGE_SHIFT, bootmap_pages << PAGE_SHIFT); + + /* + * Hmm... This should go elsewhere, but we really really + * need to stop things allocating the low memory; we need + * a better implementation of GFP_DMA which does not assume + * that DMA-able memory starts at zero. + */ + if (machine_is_integrator()) + reserve_bootmem_node(pgdat, 0, __pa(swapper_pg_dir)); + /* + * These should likewise go elsewhere. They pre-reserve + * the screen memory region at the start of main system + * memory. + */ + if (machine_is_archimedes() || machine_is_a5k()) + reserve_bootmem_node(pgdat, 0x02000000, 0x00080000); + if (machine_is_p720t()) + reserve_bootmem_node(pgdat, 0xc0000000, 0x00014000); } /* @@ -412,11 +426,12 @@ */ static inline void free_bootmem_node_bank(int node, struct meminfo *mi) { + pg_data_t *pgdat = NODE_DATA(node); int bank; for (bank = 0; bank < mi->nr_banks; bank++) if (mi->bank[bank].node == node) - free_bootmem_node(NODE_DATA(node), mi->bank[bank].start, + free_bootmem_node(pgdat, mi->bank[bank].start, mi->bank[bank].size); } @@ -632,9 +647,11 @@ void free_initmem(void) { - free_area((unsigned long)(&__init_begin), - (unsigned long)(&__init_end), - "init"); + if (!machine_is_integrator()) { + free_area((unsigned long)(&__init_begin), + (unsigned long)(&__init_end), + "init"); + } } #ifdef CONFIG_BLK_DEV_INITRD diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c --- v2.4.0-test11/linux/arch/arm/mm/mm-armv.c Tue Oct 31 12:42:25 2000 +++ linux/arch/arm/mm/mm-armv.c Mon Nov 27 17:07:59 2000 @@ -361,6 +361,7 @@ p ++; } +#ifdef FLUSH_BASE p->physical = FLUSH_BASE_PHYS; p->virtual = FLUSH_BASE; p->length = PGDIR_SIZE; @@ -371,6 +372,7 @@ p->bufferable = 1; p ++; +#endif #ifdef FLUSH_BASE_MINICACHE p->physical = FLUSH_BASE_PHYS + PGDIR_SIZE; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/mm/proc-arm720.S linux/arch/arm/mm/proc-arm720.S --- v2.4.0-test11/linux/arch/arm/mm/proc-arm720.S Sun Oct 8 10:50:06 2000 +++ linux/arch/arm/mm/proc-arm720.S Mon Nov 27 17:07:59 2000 @@ -139,7 +139,7 @@ Ldata_saver7: str r7, [sp, r5, lsr #14] @ Put register Ldata_simple: mrc p15, 0, r0, c6, c0, 0 @ get FAR mrc p15, 0, r3, c5, c0, 0 @ get FSR - and r3, r3, #15 + and r3, r3, #255 mov pc, lr ENTRY(cpu_arm720_data_abort) @@ -155,7 +155,7 @@ b Ldata_unknown b Ldata_unknown b Ldata_lateldrpostconst @ ldr rd, [rn], #m - b Ldata_lateldrpreconst @ ldr rd, [rn, #m] @ RegVal + b Ldata_lateldrpreconst @ ldr rd, [rn, #m] b Ldata_lateldrpostreg @ ldr rd, [rn], rm b Ldata_lateldrprereg @ ldr rd, [rn, rm] b Ldata_ldmstm @ ldm*a rn, @@ -177,25 +177,14 @@ tst r4, #1 << 21 @ check writeback bit beq Ldata_simple Ldata_lateldrhpost: - tst r4, #1 << 22 @ check if register or immediate offset - beq Ldata_lateldrhpostreg -Ldata_lateldrhpostconst: - and r2, r4, #0xf @ load and clear low nibble of const offset - and r5, r4, #0xf00 @ load and clear high nibble of const offset - orrs r2, r2, r5, lsr #4 @ create offset - beq Ldata_simple @ don't have to do anything if zero - and r5, r4, #0xf << 16 @ get Rn - ldr r0, [sp, r5, lsr #14] + and r5, r4, #0x00f @ get Rm / low nibble of immediate value + tst r4, #1 << 22 @ if (immediate offset) + andne r2, r4, #0xf00 @ { immediate high nibble + orrne r2, r5, r2, lsr #4 @ combine nibbles } else + ldreq r2, [sp, r5, lsl #2] @ { load Rm value } + and r5, r4, #15 << 16 @ get Rn + ldr r0, [sp, r5, lsr #14] @ load Rn value tst r4, #1 << 23 @ U bit - subne r7, r0, r2, lsr #20 - addeq r7, r0, r2, lsr #20 - b Ldata_saver7 -Ldata_lateldrhpostreg: - and r5, r4, #0xf - ldr r2, [sp, r5, lsl #2] @ get Rm - and r5, r4, #0xf << 16 - ldr r0, [sp, r5, lsr #14] @ get Rn - tst r4, #1 << 23 subne r7, r0, r2 addeq r7, r0, r2 b Ldata_saver7 @@ -385,7 +374,7 @@ cpu_armvlsi_name: - .asciz "ARM/VLSI" + .asciz "ARM" cpu_arm720_name: .asciz "ARM720T" .align @@ -471,8 +460,8 @@ __arm720_proc_info: .long 0x41807200 @ cpu_val .long 0xffffff00 @ cpu_mask - .long 0x00000c0e @ __cpu_mmu_flags - b __arm720_setup @ --cpu_flush + .long 0x00000c1e @ section_mmu_flags + b __arm720_setup @ cpu_flush .long cpu_arch_name @ arch_name .long cpu_elf_name @ elf_name .long HWCAP_SWP | HWCAP_HALF | HWCAP_26BIT @ elf_hwcap diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/double_cpdo.c linux/arch/arm/nwfpe/double_cpdo.c --- v2.4.0-test11/linux/arch/arm/nwfpe/double_cpdo.c Wed Oct 20 16:29:08 1999 +++ linux/arch/arm/nwfpe/double_cpdo.c Mon Nov 27 17:07:59 2000 @@ -44,7 +44,7 @@ float64 rFm, rFn; unsigned int Fd, Fm, Fn, nRc = 1; - //fp_printk("DoubleCPDO(0x%08x)\n",opcode); + //printk("DoubleCPDO(0x%08x)\n",opcode); Fm = getFm(opcode); if (CONSTANT_FM(opcode)) @@ -65,7 +65,7 @@ case typeExtended: // !! patb - //fp_printk("not implemented! why not?\n"); + //printk("not implemented! why not?\n"); //!! ScottB // should never get here, if extended involved // then other operand should be promoted then diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/extended_cpdo.c linux/arch/arm/nwfpe/extended_cpdo.c --- v2.4.0-test11/linux/arch/arm/nwfpe/extended_cpdo.c Wed Oct 20 16:29:08 1999 +++ linux/arch/arm/nwfpe/extended_cpdo.c Mon Nov 27 17:07:59 2000 @@ -42,7 +42,7 @@ floatx80 rFm, rFn; unsigned int Fd, Fm, Fn, nRc = 1; - //fp_printk("ExtendedCPDO(0x%08x)\n",opcode); + //printk("ExtendedCPDO(0x%08x)\n",opcode); Fm = getFm(opcode); if (CONSTANT_FM(opcode)) diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/fpa11_cpdo.c linux/arch/arm/nwfpe/fpa11_cpdo.c --- v2.4.0-test11/linux/arch/arm/nwfpe/fpa11_cpdo.c Wed Oct 20 16:29:08 1999 +++ linux/arch/arm/nwfpe/fpa11_cpdo.c Mon Nov 27 17:07:59 2000 @@ -30,7 +30,7 @@ { unsigned int Fd, nType, nDest, nRc = 1; - //fp_printk("EmulateCPDO(0x%08x)\n",opcode); + //printk("EmulateCPDO(0x%08x)\n",opcode); /* Get the destination size. If not valid let Linux perform an invalid instruction trap. */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/fpa11_cpdt.c linux/arch/arm/nwfpe/fpa11_cpdt.c --- v2.4.0-test11/linux/arch/arm/nwfpe/fpa11_cpdt.c Wed Oct 20 16:29:08 1999 +++ linux/arch/arm/nwfpe/fpa11_cpdt.c Mon Nov 27 17:07:59 2000 @@ -189,7 +189,7 @@ unsigned int *pBase, *pAddress, *pFinal, nRc = 1, write_back = WRITE_BACK(opcode); - //fp_printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); + //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); pBase = (unsigned int*)readRegister(getRn(opcode)); if (REG_PC == getRn(opcode)) @@ -223,7 +223,7 @@ unsigned int *pBase, *pAddress, *pFinal, nRc = 1, write_back = WRITE_BACK(opcode); - //fp_printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); + //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); SetRoundingMode(ROUND_TO_NEAREST); pBase = (unsigned int*)readRegister(getRn(opcode)); @@ -322,7 +322,7 @@ { unsigned int nRc = 0; - //fp_printk("EmulateCPDT(0x%08x)\n",opcode); + //printk("EmulateCPDT(0x%08x)\n",opcode); if (LDF_OP(opcode)) { diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/fpa11_cprt.c linux/arch/arm/nwfpe/fpa11_cprt.c --- v2.4.0-test11/linux/arch/arm/nwfpe/fpa11_cprt.c Wed Oct 20 16:29:08 1999 +++ linux/arch/arm/nwfpe/fpa11_cprt.c Mon Nov 27 17:07:59 2000 @@ -44,7 +44,7 @@ { unsigned int nRc = 1; - //fp_printk("EmulateCPRT(0x%08x)\n",opcode); + //printk("EmulateCPRT(0x%08x)\n",opcode); if (opcode & 0x800000) { @@ -188,7 +188,7 @@ int n_flag = opcode & 0x200000; /* 1 if CNxx */ unsigned int flags = 0; - //fp_printk("PerformComparison(0x%08x)\n",opcode); + //printk("PerformComparison(0x%08x)\n",opcode); Fn = getFn(opcode); Fm = getFm(opcode); @@ -201,21 +201,21 @@ switch (fpa11->fType[Fn]) { case typeSingle: - //fp_printk("single.\n"); + //printk("single.\n"); if (float32_is_nan(fpa11->fpreg[Fn].fSingle)) goto unordered; rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle); break; case typeDouble: - //fp_printk("double.\n"); + //printk("double.\n"); if (float64_is_nan(fpa11->fpreg[Fn].fDouble)) goto unordered; rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble); break; case typeExtended: - //fp_printk("extended.\n"); + //printk("extended.\n"); if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended)) goto unordered; rFn = fpa11->fpreg[Fn].fExtended; @@ -226,32 +226,32 @@ if (CONSTANT_FM(opcode)) { - //fp_printk("Fm is a constant: #%d.\n",Fm); + //printk("Fm is a constant: #%d.\n",Fm); rFm = getExtendedConstant(Fm); if (floatx80_is_nan(rFm)) goto unordered; } else { - //fp_printk("Fm = r%d which contains a ",Fm); + //printk("Fm = r%d which contains a ",Fm); switch (fpa11->fType[Fm]) { case typeSingle: - //fp_printk("single.\n"); + //printk("single.\n"); if (float32_is_nan(fpa11->fpreg[Fm].fSingle)) goto unordered; rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle); break; case typeDouble: - //fp_printk("double.\n"); + //printk("double.\n"); if (float64_is_nan(fpa11->fpreg[Fm].fDouble)) goto unordered; rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble); break; case typeExtended: - //fp_printk("extended.\n"); + //printk("extended.\n"); if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended)) goto unordered; rFm = fpa11->fpreg[Fm].fExtended; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/fpmodule.c linux/arch/arm/nwfpe/fpmodule.c --- v2.4.0-test11/linux/arch/arm/nwfpe/fpmodule.c Sun Feb 13 10:47:01 2000 +++ linux/arch/arm/nwfpe/fpmodule.c Mon Nov 27 17:07:59 2000 @@ -46,7 +46,6 @@ typedef struct task_struct* PTASK; #ifdef MODULE -int fp_printk(const char *,...); void fp_send_sig(unsigned long sig, PTASK p, int priv); #if LINUX_VERSION_CODE > 0x20115 MODULE_AUTHOR("Scott Bambrough "); @@ -54,7 +53,6 @@ #endif #else -#define fp_printk printk #define fp_send_sig send_sig #define kern_fp_enter fp_enter #endif @@ -74,23 +72,14 @@ /* Address of user registers on the kernel stack. */ unsigned int *userRegisters; -void __init fpe_version(void) -{ - static const char szTitle[] = "<4>NetWinder Floating Point Emulator "; - static const char szVersion[] = "V0.95 "; - static const char szCopyright[] = "(c) 1998-1999 Rebel.com\n"; - fp_printk(szTitle); - fp_printk(szVersion); - fp_printk(szCopyright); -} - int __init fpe_init(void) { if (sizeof(FPA11) > sizeof(union fp_state)) printk(KERN_ERR "nwfpe: bad structure size\n"); else { /* Display title, version and copyright information. */ - fpe_version(); + printk(KERN_WARNING "NetWinder Floating Point Emulator V0.95 " + "(c) 1998-1999 Rebel.com\n"); /* Save pointer to the old FP handler and then patch ourselves in */ orig_fp_enter = kern_fp_enter; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/nwfpe/softfloat.c linux/arch/arm/nwfpe/softfloat.c --- v2.4.0-test11/linux/arch/arm/nwfpe/softfloat.c Thu Jun 17 01:11:35 1999 +++ linux/arch/arm/nwfpe/softfloat.c Mon Nov 27 17:07:59 2000 @@ -39,7 +39,7 @@ */ int8 float_rounding_mode = float_round_nearest_even; int8 floatx80_rounding_precision = 80; -int8 float_exception_flags = 0; +int8 float_exception_flags; /* ------------------------------------------------------------------------------- @@ -418,9 +418,8 @@ || ( ( zExp == 0x7FD ) && ( (sbits64) ( zSig + roundIncrement ) < 0 ) ) ) { - //register int lr; - //__asm__("mov %0, lr" :: "g" (lr)); - //fp_printk("roundAndPackFloat64 called from 0x%08x\n",lr); + //register int lr = __builtin_return_address(0); + //printk("roundAndPackFloat64 called from 0x%08x\n",lr); float_raise( float_flag_overflow | float_flag_inexact ); return packFloat64( zSign, 0x7FF, 0 ) - ( roundIncrement == 0 ); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types --- v2.4.0-test11/linux/arch/arm/tools/mach-types Sun Sep 3 11:19:11 2000 +++ linux/arch/arm/tools/mach-types Mon Nov 27 17:07:59 2000 @@ -1,7 +1,10 @@ # Database of machine macros and numbers # -# To add an entry into this database, please see -# Documentation/arm/README +# Please do not send patches to this file; it is automatically generated! +# To add an entry into this database, please see Documentation/arm/README, +# or contact rmk@arm.linux.org.uk +# +# Last update: Mon Nov 20 22:59:11 2000 # # machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number # @@ -14,7 +17,7 @@ tbox ARCH_TBOX TBOX 7 co285 ARCH_CO285 CO285 8 clps7110 ARCH_CLPS7110 CLPS7110 9 -arc ARCH_ARC ARCHIMEDES 10 +archimedes ARCH_ARC ARCHIMEDES 10 a5k ARCH_A5K A5K 11 etoile ARCH_ETOILE ETOILE 12 lacie_nas ARCH_LACIE_NAS LACIE_NAS 13 @@ -28,7 +31,7 @@ integrator ARCH_INTEGRATOR INTEGRATOR 21 bitsy SA1100_BITSY BITSY 22 ixp1200 ARCH_IXP1200 IXP1200 23 -thinclient SA1100_THINCLIENT THINCLIENT 24 +p720t ARCH_P720T P720T 24 assabet SA1100_ASSABET ASSABET 25 victor SA1100_VICTOR VICTOR 26 lart SA1100_LART LART 27 @@ -42,8 +45,16 @@ sherman SA1100_SHERMAN SHERMAN 35 accelent_sa SA1100_ACCELENT ACCELENT_SA 36 accelent_l7200 ARCH_L7200_ACCELENT ACCELENT_L7200 37 +netport SA1100_NETPORT NETPORT 38 +pangolin SA1100_PANGOLIN PANGOLIN 39 +yopy SA1100_YOPY YOPY 40 +sa1100 SA1100_SA1100 SA1100 41 +huw_webpanel ARCH_HUW_WEBPANEL HUW_WEBPANEL 42 +spotme ARCH_SPOTME SPOTME 43 +freebird ARCH_FREEBIRD FREEBIRD 44 +ti925 ARCH_TI925 TI925 45 +riscstation ARCH_RISCSTATION RISCSTATION 46 +cavy SA1100_CAVY CAVY 47 # The following are unallocated empeg SA1100_EMPEG EMPEG -tifon SA1100_TIFON TIFON -penny SA1100_PENNY PENNY diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in --- v2.4.0-test11/linux/arch/arm/vmlinux-armo.lds.in Sun Sep 3 11:19:11 2000 +++ linux/arch/arm/vmlinux-armo.lds.in Mon Nov 27 17:07:59 2000 @@ -9,6 +9,7 @@ . = TEXTADDR; .init : { + _stext = .; __init_begin = .; /* Init code and data */ *(.text.init) __proc_info_begin = .; diff -u --recursive --new-file v2.4.0-test11/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in --- v2.4.0-test11/linux/arch/arm/vmlinux-armv.lds.in Sun Sep 3 11:19:11 2000 +++ linux/arch/arm/vmlinux-armv.lds.in Mon Nov 27 17:07:59 2000 @@ -8,6 +8,7 @@ { . = TEXTADDR; .init : { /* Init code and data */ + _stext = .; __init_begin = .; *(.text.init) __proc_info_begin = .; diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/boot/setup.S linux/arch/i386/boot/setup.S --- v2.4.0-test11/linux/arch/i386/boot/setup.S Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/boot/setup.S Tue Dec 5 17:31:53 2000 @@ -825,10 +825,18 @@ # # Some machines have delusions that the keyboard buffer is always full # with no keyboard attached... +# +# If there is no keyboard controller, we will usually get 0xff +# to all the reads. With each IO taking a microsecond and +# a timeout of 100,000 iterations, this can take about half a +# second ("delay" == outb to port 0x80). That should be ok, +# and should also be plenty of time for a real keyboard controller +# to empty. +# empty_8042: pushl %ecx - movl $0x00FFFFFF, %ecx + movl $100000, %ecx empty_8042_loop: decl %ecx @@ -867,7 +875,7 @@ # Delay is needed after doing I/O delay: - jmp .+2 # jmp $+2 + outb %al,$0x80 ret # Descriptor tables diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.4.0-test11/linux/arch/i386/config.in Sun Nov 19 18:44:02 2000 +++ linux/arch/i386/config.in Mon Dec 11 13:42:08 2000 @@ -140,7 +140,7 @@ fi tristate 'Toshiba Laptop support' CONFIG_TOSHIBA -tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE +tristate '/dev/cpu/microcode - Intel IA32 CPU microcode support' CONFIG_MICROCODE tristate '/dev/cpu/*/msr - Model-specific register support' CONFIG_X86_MSR tristate '/dev/cpu/*/cpuid - CPU information support' CONFIG_X86_CPUID diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.0-test11/linux/arch/i386/defconfig Sun Nov 19 18:44:02 2000 +++ linux/arch/i386/defconfig Mon Nov 27 18:40:34 2000 @@ -649,20 +649,15 @@ # CONFIG_USB_OHCI is not set # -# USB Devices +# USB Device Class drivers # -# CONFIG_USB_PRINTER is not set -# CONFIG_USB_SCANNER is not set # CONFIG_USB_AUDIO is not set -# CONFIG_USB_ACM is not set -# CONFIG_USB_SERIAL is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_DC2XX is not set +# CONFIG_USB_BLUETOOTH is not set CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set -# CONFIG_USB_USS720 is not set -# CONFIG_USB_DABUSB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set # # USB Human Interface Devices (HID) @@ -671,6 +666,44 @@ # # Input core support is needed for USB HID # + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_USB_DABUSB is not set + +# +# USB Network adaptors +# +# CONFIG_USB_PLUSB is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_NET1080 is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB misc drivers +# +# CONFIG_USB_RIO500 is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c --- v2.4.0-test11/linux/arch/i386/kernel/apic.c Sun Nov 19 18:44:02 2000 +++ linux/arch/i386/kernel/apic.c Tue Dec 5 12:43:48 2000 @@ -220,66 +220,19 @@ BUG(); /* - * Set up LVT0, LVT1: - * - * set up through-local-APIC on the BP's LINT0. This is not - * strictly necessery in pure symmetric-IO mode, but sometimes - * we delegate interrupts to the 8259A. - */ - /* - * TODO: set up through-local-APIC from through-I/O-APIC? --macro - */ - value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; - if (!smp_processor_id() && (pic_mode || !value)) { - value = APIC_DM_EXTINT; - printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); - } else { - value = APIC_DM_EXTINT | APIC_LVT_MASKED; - printk("masked ExtINT on CPU#%d\n", smp_processor_id()); - } - apic_write_around(APIC_LVT0, value); - - /* - * only the BP should see the LINT1 NMI signal, obviously. + * Intel recommends to set DFR, LDR and TPR before enabling + * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel + * document number 292116). So here it goes... */ - if (!smp_processor_id()) - value = APIC_DM_NMI; - else - value = APIC_DM_NMI | APIC_LVT_MASKED; - if (!APIC_INTEGRATED(ver)) /* 82489DX */ - value |= APIC_LVT_LEVEL_TRIGGER; - apic_write_around(APIC_LVT1, value); - - if (APIC_INTEGRATED(ver)) { /* !82489DX */ - maxlvt = get_maxlvt(); - if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ - apic_write(APIC_ESR, 0); - value = apic_read(APIC_ESR); - printk("ESR value before enabling vector: %08lx\n", value); - - value = ERROR_APIC_VECTOR; // enables sending errors - apic_write_around(APIC_LVTERR, value); - /* - * spec says clear errors after enabling vector. - */ - if (maxlvt > 3) - apic_write(APIC_ESR, 0); - value = apic_read(APIC_ESR); - printk("ESR value after enabling vector: %08lx\n", value); - } else - printk("No ESR for 82489DX.\n"); /* - * Set Task Priority to 'accept all'. We never change this - * later on. + * Put the APIC into flat delivery mode. + * Must be "all ones" explicitly for 82489DX. */ - value = apic_read(APIC_TASKPRI); - value &= ~APIC_TPRI_MASK; - apic_write_around(APIC_TASKPRI, value); + apic_write_around(APIC_DFR, 0xffffffff); /* - * Set up the logical destination ID and put the - * APIC into flat delivery mode. + * Set up the logical destination ID. */ value = apic_read(APIC_LDR); value &= ~APIC_LDR_MASK; @@ -287,9 +240,12 @@ apic_write_around(APIC_LDR, value); /* - * Must be "all ones" explicitly for 82489DX. + * Set Task Priority to 'accept all'. We never change this + * later on. */ - apic_write_around(APIC_DFR, 0xffffffff); + value = apic_read(APIC_TASKPRI); + value &= ~APIC_TPRI_MASK; + apic_write_around(APIC_TASKPRI, value); /* * Now that we are all set up, enable the APIC @@ -326,6 +282,56 @@ */ value |= SPURIOUS_APIC_VECTOR; apic_write_around(APIC_SPIV, value); + + /* + * Set up LVT0, LVT1: + * + * set up through-local-APIC on the BP's LINT0. This is not + * strictly necessery in pure symmetric-IO mode, but sometimes + * we delegate interrupts to the 8259A. + */ + /* + * TODO: set up through-local-APIC from through-I/O-APIC? --macro + */ + value = apic_read(APIC_LVT0) & APIC_LVT_MASKED; + if (!smp_processor_id() && (pic_mode || !value)) { + value = APIC_DM_EXTINT; + printk("enabled ExtINT on CPU#%d\n", smp_processor_id()); + } else { + value = APIC_DM_EXTINT | APIC_LVT_MASKED; + printk("masked ExtINT on CPU#%d\n", smp_processor_id()); + } + apic_write_around(APIC_LVT0, value); + + /* + * only the BP should see the LINT1 NMI signal, obviously. + */ + if (!smp_processor_id()) + value = APIC_DM_NMI; + else + value = APIC_DM_NMI | APIC_LVT_MASKED; + if (!APIC_INTEGRATED(ver)) /* 82489DX */ + value |= APIC_LVT_LEVEL_TRIGGER; + apic_write_around(APIC_LVT1, value); + + if (APIC_INTEGRATED(ver)) { /* !82489DX */ + maxlvt = get_maxlvt(); + if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ + apic_write(APIC_ESR, 0); + value = apic_read(APIC_ESR); + printk("ESR value before enabling vector: %08lx\n", value); + + value = ERROR_APIC_VECTOR; // enables sending errors + apic_write_around(APIC_LVTERR, value); + /* + * spec says clear errors after enabling vector. + */ + if (maxlvt > 3) + apic_write(APIC_ESR, 0); + value = apic_read(APIC_ESR); + printk("ESR value after enabling vector: %08lx\n", value); + } else + printk("No ESR for 82489DX.\n"); } void __init init_apic_mappings(void) diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.4.0-test11/linux/arch/i386/kernel/apm.c Sun Nov 19 18:44:02 2000 +++ linux/arch/i386/kernel/apm.c Wed Dec 6 21:00:12 2000 @@ -37,6 +37,7 @@ * Nov 1999, Version 1.11 * Jan 2000, Version 1.12 * Feb 2000, Version 1.13 + * Nov 2000, Version 1.14 * * History: * 0.6b: first version in official kernel, Linux 1.3.46 @@ -144,6 +145,9 @@ * and ) modified by sfr. * Remove CONFIG_APM_SUSPEND_BOUNCE. The bounce ignore * interval is now configurable. + * 1.14: Make connection version persist across module unload/load. + * Enable and engage power management earlier. + * Disengage power management on module unload. * * APM 1.1 Reference: * @@ -344,9 +348,9 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitqueue); static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); -static struct apm_user * user_list = NULL; +static struct apm_user * user_list; -static char driver_version[] = "1.13"; /* no spaces */ +static char driver_version[] = "1.14"; /* no spaces */ static char * apm_event_name[] = { "system standby", @@ -527,7 +531,7 @@ &dummy, &dummy)) return (eax >> 8) & 0xff; *event = ebx; - if (apm_bios_info.version < 0x0102) + if (apm_info.connection_version < 0x0102) *info = ~0; /* indicate info not valid */ else *info = ecx; @@ -559,7 +563,7 @@ #ifdef ALWAYS_CALL_BUSY clock_slowed = 1; #else - clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0; + clock_slowed = (apm_info.bios.flags & APM_IDLE_SLOWS_CLOCK) != 0; #endif return 1; } @@ -670,15 +674,15 @@ { u32 eax; - if ((enable == 0) && (apm_bios_info.flags & APM_BIOS_DISENGAGED)) + if ((enable == 0) && (apm_info.bios.flags & APM_BIOS_DISENGAGED)) return APM_NOT_ENGAGED; if (apm_bios_call_simple(APM_FUNC_ENABLE_PM, APM_DEVICE_BALL, enable, &eax)) return (eax >> 8) & 0xff; if (enable) - apm_bios_info.flags &= ~APM_BIOS_DISABLED; + apm_info.bios.flags &= ~APM_BIOS_DISABLED; else - apm_bios_info.flags |= APM_BIOS_DISABLED; + apm_info.bios.flags |= APM_BIOS_DISABLED; return APM_SUCCESS; } #endif @@ -691,6 +695,8 @@ u32 edx; u32 dummy; + if (apm_info.get_power_status_broken) + return APM_32_UNSUPPORTED; if (apm_bios_call(APM_FUNC_GET_STATUS, APM_DEVICE_ALL, 0, &eax, &ebx, &ecx, &edx, &dummy)) return (eax >> 8) & 0xff; @@ -710,7 +716,7 @@ u32 edx; u32 esi; - if (apm_bios_info.version < 0x0102) { + if (apm_info.connection_version < 0x0102) { /* pretend we only have one battery. */ if (which != 1) return APM_BAD_DEVICE; @@ -734,15 +740,15 @@ u32 eax; if ((enable == 0) && (device == APM_DEVICE_ALL) - && (apm_bios_info.flags & APM_BIOS_DISABLED)) + && (apm_info.bios.flags & APM_BIOS_DISABLED)) return APM_DISABLED; if (apm_bios_call_simple(APM_FUNC_ENGAGE_PM, device, enable, &eax)) return (eax >> 8) & 0xff; if (device == APM_DEVICE_ALL) { if (enable) - apm_bios_info.flags &= ~APM_BIOS_DISENGAGED; + apm_info.bios.flags &= ~APM_BIOS_DISENGAGED; else - apm_bios_info.flags |= APM_BIOS_DISENGAGED; + apm_info.bios.flags |= APM_BIOS_DISENGAGED; } return APM_SUCCESS; } @@ -890,7 +896,7 @@ printk(KERN_CRIT "apm: Critical suspend was vetoed, expect armageddon\n" ); return 0; } - if (apm_bios_info.version > 0x100) + if (apm_info.connection_version > 0x100) apm_set_power_state(APM_STATE_REJECT); return 0; } @@ -993,13 +999,13 @@ case APM_USER_SUSPEND: #ifdef CONFIG_APM_IGNORE_USER_SUSPEND - if (apm_bios_info.version > 0x100) + if (apm_info.connection_version > 0x100) apm_set_power_state(APM_STATE_REJECT); break; #endif case APM_SYS_SUSPEND: if (ignore_bounce) { - if (apm_bios_info.version > 0x100) + if (apm_info.connection_version > 0x100) apm_set_power_state(APM_STATE_REJECT); break; } @@ -1064,7 +1070,7 @@ int err; if ((standbys_pending > 0) || (suspends_pending > 0)) { - if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) { + if ((apm_info.connection_version > 0x100) && (pending_count-- <= 0)) { pending_count = 4; if (debug) printk(KERN_DEBUG "apm: setting state busy\n"); @@ -1334,7 +1340,7 @@ unsigned short bx; unsigned short cx; unsigned short dx; - unsigned short error; + int error; unsigned short ac_line_status = 0xff; unsigned short battery_status = 0xff; unsigned short battery_flag = 0xff; @@ -1351,7 +1357,7 @@ if ((cx & 0xff) != 0xff) percentage = cx & 0xff; - if (apm_bios_info.version > 0x100) { + if (apm_info.connection_version > 0x100) { battery_flag = (cx >> 8) & 0xff; if (dx != 0xffff) { units = (dx & 0x8000) ? "min" : "sec"; @@ -1399,9 +1405,9 @@ p += sprintf(p, "%s %d.%d 0x%02x 0x%02x 0x%02x 0x%02x %d%% %d %s\n", driver_version, - (apm_bios_info.version >> 8) & 0xff, - apm_bios_info.version & 0xff, - apm_bios_info.flags, + (apm_info.bios.version >> 8) & 0xff, + apm_info.bios.version & 0xff, + apm_info.bios.flags, ac_line_status, battery_status, battery_flag, @@ -1417,7 +1423,7 @@ unsigned short bx; unsigned short cx; unsigned short dx; - unsigned short error; + int error; char * power_stat; char * bat_stat; @@ -1429,22 +1435,53 @@ sigfillset(¤t->blocked); current->tty = NULL; /* get rid of controlling tty */ - if (apm_bios_info.version > 0x100) { + if (apm_info.connection_version == 0) { + apm_info.connection_version = apm_info.bios.version; + if (apm_info.connection_version > 0x100) { + /* + * We only support BIOSs up to version 1.2 + */ + if (apm_info.connection_version > 0x0102) + apm_info.connection_version = 0x0102; + error = apm_driver_version(&apm_info.connection_version); + if (error != APM_SUCCESS) { + apm_error("driver version", error); + /* Fall back to an APM 1.0 connection. */ + apm_info.connection_version = 0x100; + } + } + } + + if (debug) + printk(KERN_INFO "apm: Connection version %d.%d\n", + (apm_info.connection_version >> 8) & 0xff, + apm_info.connection_version & 0xff); + +#ifdef CONFIG_APM_DO_ENABLE + if (apm_info.bios.flags & APM_BIOS_DISABLED) { /* - * We only support BIOSs up to version 1.2 + * This call causes my NEC UltraLite Versa 33/C to hang if it + * is booted with PM disabled but not in the docking station. + * Unfortunate ... */ - if (apm_bios_info.version > 0x0102) - apm_bios_info.version = 0x0102; - if (apm_driver_version(&apm_bios_info.version) != APM_SUCCESS) { - /* Fall back to an APM 1.0 connection. */ - apm_bios_info.version = 0x100; + error = apm_enable_power_management(1); + if (error) { + apm_error("enable power management", error); + return -1; + } + } +#endif + + if ((apm_info.bios.flags & APM_BIOS_DISENGAGED) + && (apm_info.connection_version > 0x0100)) { + error = apm_engage_power_management(APM_DEVICE_ALL, 1); + if (error) { + apm_error("engage power management", error); + return -1; } } - if (debug && (smp_num_cpus == 1)) { - printk(KERN_INFO "apm: Connection version %d.%d\n", - (apm_bios_info.version >> 8) & 0xff, - apm_bios_info.version & 0xff); + if (debug && (smp_num_cpus == 1)) { error = apm_get_power_status(&bx, &cx, &dx); if (error) printk(KERN_INFO "apm: power status not available\n"); @@ -1469,7 +1506,7 @@ printk("unknown\n"); else printk("%d%%\n", cx & 0xff); - if (apm_bios_info.version > 0x100) { + if (apm_info.connection_version > 0x100) { printk(KERN_INFO "apm: battery flag 0x%02x, battery life ", (cx >> 8) & 0xff); @@ -1483,29 +1520,6 @@ } } -#ifdef CONFIG_APM_DO_ENABLE - if (apm_bios_info.flags & APM_BIOS_DISABLED) { - /* - * This call causes my NEC UltraLite Versa 33/C to hang if it - * is booted with PM disabled but not in the docking station. - * Unfortunate ... - */ - error = apm_enable_power_management(1); - if (error) { - apm_error("enable power management", error); - return -1; - } - } -#endif - if ((apm_bios_info.flags & APM_BIOS_DISENGAGED) - && (apm_bios_info.version > 0x0100)) { - error = apm_engage_power_management(APM_DEVICE_ALL, 1); - if (error) { - apm_error("engage power management", error); - return -1; - } - } - /* Install our power off handler.. */ if (power_off) pm_power_off = apm_power_off; @@ -1584,17 +1598,19 @@ */ static int __init apm_init(void) { - if (apm_bios_info.version == 0) { + struct proc_dir_entry *apm_proc; + + if (apm_info.bios.version == 0) { printk(KERN_INFO "apm: BIOS not found.\n"); return -ENODEV; } printk(KERN_INFO "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n", - ((apm_bios_info.version >> 8) & 0xff), - (apm_bios_info.version & 0xff), - apm_bios_info.flags, + ((apm_info.bios.version >> 8) & 0xff), + (apm_info.bios.version & 0xff), + apm_info.bios.flags, driver_version); - if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) { + if ((apm_info.bios.flags & APM_32_BIT_SUPPORT) == 0) { printk(KERN_INFO "apm: no 32 bit BIOS support\n"); return -ENODEV; } @@ -1603,23 +1619,23 @@ * Fix for the Compaq Contura 3/25c which reports BIOS version 0.1 * but is reportedly a 1.0 BIOS. */ - if (apm_bios_info.version == 0x001) - apm_bios_info.version = 0x100; + if (apm_info.bios.version == 0x001) + apm_info.bios.version = 0x100; /* BIOS < 1.2 doesn't set cseg_16_len */ - if (apm_bios_info.version < 0x102) - apm_bios_info.cseg_16_len = 0; /* 64k */ + if (apm_info.bios.version < 0x102) + apm_info.bios.cseg_16_len = 0; /* 64k */ if (debug) { printk(KERN_INFO "apm: entry %x:%lx cseg16 %x dseg %x", - apm_bios_info.cseg, apm_bios_info.offset, - apm_bios_info.cseg_16, apm_bios_info.dseg); - if (apm_bios_info.version > 0x100) + apm_info.bios.cseg, apm_info.bios.offset, + apm_info.bios.cseg_16, apm_info.bios.dseg); + if (apm_info.bios.version > 0x100) printk(" cseg len %x, dseg len %x", - apm_bios_info.cseg_len, - apm_bios_info.dseg_len); - if (apm_bios_info.version > 0x101) - printk(" cseg16 len %x", apm_bios_info.cseg_16_len); + apm_info.bios.cseg_len, + apm_info.bios.dseg_len); + if (apm_info.bios.version > 0x101) + printk(" cseg16 len %x", apm_info.bios.cseg_16_len); printk("\n"); } @@ -1647,16 +1663,16 @@ __va((unsigned long)0x40 << 4)); _set_limit((char *)&gdt[APM_40 >> 3], 4095 - (0x40 << 4)); - apm_bios_entry.offset = apm_bios_info.offset; + apm_bios_entry.offset = apm_info.bios.offset; apm_bios_entry.segment = APM_CS; set_base(gdt[APM_CS >> 3], - __va((unsigned long)apm_bios_info.cseg << 4)); + __va((unsigned long)apm_info.bios.cseg << 4)); set_base(gdt[APM_CS_16 >> 3], - __va((unsigned long)apm_bios_info.cseg_16 << 4)); + __va((unsigned long)apm_info.bios.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], - __va((unsigned long)apm_bios_info.dseg << 4)); + __va((unsigned long)apm_info.bios.dseg << 4)); #ifndef APM_RELAX_SEGMENTS - if (apm_bios_info.version == 0x100) { + if (apm_info.bios.version == 0x100) { #endif /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); @@ -1667,15 +1683,17 @@ #ifndef APM_RELAX_SEGMENTS } else { _set_limit((char *)&gdt[APM_CS >> 3], - (apm_bios_info.cseg_len - 1) & 0xffff); + (apm_info.bios.cseg_len - 1) & 0xffff); _set_limit((char *)&gdt[APM_CS_16 >> 3], - (apm_bios_info.cseg_16_len - 1) & 0xffff); + (apm_info.bios.cseg_16_len - 1) & 0xffff); _set_limit((char *)&gdt[APM_DS >> 3], - (apm_bios_info.dseg_len - 1) & 0xffff); + (apm_info.bios.dseg_len - 1) & 0xffff); } #endif - create_proc_info_entry("apm", 0, NULL, apm_get_info); + apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); + if (apm_proc) + SET_MODULE_OWNER(apm_proc); kernel_thread(apm, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD); @@ -1692,6 +1710,14 @@ static void __exit apm_exit(void) { + int error; + + if (((apm_info.bios.flags & APM_BIOS_DISENGAGED) == 0) + && (apm_info.connection_version > 0x0100)) { + error = apm_engage_power_management(APM_DEVICE_ALL, 0); + if (error) + apm_error("disengage power management", error); + } misc_deregister(&apm_device); remove_proc_entry("apm", NULL); #ifdef CONFIG_MAGIC_SYSRQ diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c --- v2.4.0-test11/linux/arch/i386/kernel/dmi_scan.c Wed Dec 31 16:00:00 1969 +++ linux/arch/i386/kernel/dmi_scan.c Mon Dec 11 13:38:29 2000 @@ -0,0 +1,182 @@ +#include +#include +#include +#include +#include +#include +#include + +struct dmi_header +{ + u8 type; + u8 length; + u16 handle; +}; + +static char * __init dmi_string(struct dmi_header *dm, u8 s) +{ + u8 *bp=(u8 *)dm; + bp+=dm->length; + s--; + while(s>0) + { + bp+=strlen(bp); + bp++; + s--; + } + return bp; +} + +static int __init dmi_table(u32 base, int len, int num, void (*decode)(struct dmi_header *)) +{ + u8 *buf; + struct dmi_header *dm; + u8 *data; + int i=1; + int last = 0; + + buf = ioremap(base, len); + if(buf==NULL) + return -1; + + data = buf; + while(itype < last) + break; + last = dm->type; + decode(dm); + data+=dm->length; + while(*data || data[1]) + data++; + data+=2; + i++; + } + iounmap(buf); + return 0; +} + + +int __init dmi_iterate(void (*decode)(struct dmi_header *)) +{ + unsigned char buf[20]; + long fp=0xE0000L; + fp -= 16; + + while( fp < 0xFFFFF) + { + fp+=16; + isa_memcpy_fromio(buf, fp, 20); + if(memcmp(buf, "_DMI_", 5)==0) + { + u16 num=buf[13]<<8|buf[12]; + u16 len=buf[7]<<8|buf[6]; + u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]; + + printk(KERN_INFO "DMI %d.%d present.\n", + buf[14]>>4, buf[14]&0x0F); + printk(KERN_INFO "%d structures occupying %d bytes.\n", + buf[13]<<8|buf[12], + buf[7]<<8|buf[6]); + printk(KERN_INFO "DMI table at 0x%08X.\n", + buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]); + if(dmi_table(base,len, num, decode)==0) + return 0; + } + } + return -1; +} + + +/* + * Process a DMI table entry. Right now all we care about are the BIOS + * and machine entries. For 2.4 we should pull the smbus controller info + * out of here. + */ + +static void __init dmi_decode(struct dmi_header *dm) +{ + u8 *data = (u8 *)dm; + char *p; + + switch(dm->type) + { + case 0: + p=dmi_string(dm,data[4]); + + if(*p && *p!=' ') + { + printk("BIOS Vendor: %s\n", p); + printk("BIOS Version: %s\n", + dmi_string(dm, data[5])); + printk("BIOS Release: %s\n", + dmi_string(dm, data[8])); + } + + /* + * Check for clue free BIOS implementations who use + * the following QA technique + * + * [ Write BIOS Code ]<------ + * | ^ + * < Does it Compile >----N-- + * |Y ^ + * < Does it Boot Win98 >-N-- + * |Y + * [Ship It] + * + * Phoenix A04 08/24/2000 is known bad (Dell Inspiron 5000e) + * Phoenix A07 09/29/2000 is known good (Dell Inspiron 5000) + */ + + if(strcmp(dmi_string(dm, data[4]), "Phoenix Technologies LTD")==0) + { + if(strcmp(dmi_string(dm, data[5]), "A04")==0 + && strcmp(dmi_string(dm, data[8]), "08/24/2000")==0) + { + apm_info.get_power_status_broken = 1; + printk(KERN_WARNING "BIOS strings suggest APM bugs, disabling power status reporting.\n"); + } + } + break; + case 1: + p=dmi_string(dm,data[4]); + + if(*p && *p!=' ') + { + printk("System Vendor: %s.\n",p); + printk("Product Name: %s.\n", + dmi_string(dm, data[5])); + printk("Version %s.\n", + dmi_string(dm, data[6])); + printk("Serial Number %s.\n", + dmi_string(dm, data[7])); + } + break; + case 2: + p=dmi_string(dm,data[4]); + + if(*p && *p!=' ') + { + printk("Board Vendor: %s.\n",p); + printk("Board Name: %s.\n", + dmi_string(dm, data[5])); + printk("Board Version: %s.\n", + dmi_string(dm, data[6])); + } + break; + case 3: + p=dmi_string(dm,data[8]); + if(*p && *p!=' ') + printk("Asset Tag: %s.\n", p); + break; + } +} + +static int __init dmi_scan_machine(void) +{ + return dmi_iterate(dmi_decode); +} + +module_init(dmi_scan_machine); diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S --- v2.4.0-test11/linux/arch/i386/kernel/head.S Wed Jul 5 12:03:12 2000 +++ linux/arch/i386/kernel/head.S Tue Nov 28 22:43:39 2000 @@ -119,12 +119,12 @@ /* * Clear BSS first so that there are no surprises... + * No need to cld as DF is already clear from cld above... */ xorl %eax,%eax movl $ SYMBOL_NAME(__bss_start),%edi movl $ SYMBOL_NAME(_end),%ecx subl %edi,%ecx - cld rep stosb diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.4.0-test11/linux/arch/i386/kernel/i386_ksyms.c Sun Nov 19 18:44:02 2000 +++ linux/arch/i386/kernel/i386_ksyms.c Wed Dec 6 21:00:12 2000 @@ -68,7 +68,7 @@ EXPORT_SYMBOL(pm_idle); EXPORT_SYMBOL(pm_power_off); EXPORT_SYMBOL(get_cmos_time); -EXPORT_SYMBOL(apm_bios_info); +EXPORT_SYMBOL(apm_info); EXPORT_SYMBOL(gdt); EXPORT_SYMBOL_NOVERS(__down_failed); diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c --- v2.4.0-test11/linux/arch/i386/kernel/irq.c Fri Aug 4 16:15:38 2000 +++ linux/arch/i386/kernel/irq.c Sun Dec 3 17:48:19 2000 @@ -179,7 +179,7 @@ #ifdef CONFIG_SMP unsigned char global_irq_holder = NO_PROC_ID; -unsigned volatile int global_irq_lock; +unsigned volatile long global_irq_lock; /* pendantic: long for set_bit --RR */ extern void show_stack(unsigned long* esp); diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c --- v2.4.0-test11/linux/arch/i386/kernel/microcode.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/microcode.c Mon Dec 11 13:42:08 2000 @@ -4,13 +4,13 @@ * Copyright (C) 2000 Tigran Aivazian * * This driver allows to upgrade microcode on Intel processors - * belonging to P6 family - PentiumPro, Pentium II, - * Pentium III, Xeon etc. + * belonging to IA-32 family - PentiumPro, Pentium II, + * Pentium III, Xeon, Pentium 4, etc. * - * Reference: Section 8.10 of Volume III, Intel Pentium III Manual, - * Order Number 243192 or free download from: + * Reference: Section 8.10 of Volume III, Intel Pentium 4 Manual, + * Order Number 245472 or free download from: * - * http://developer.intel.com/design/pentiumii/manuals/243192.htm + * http://developer.intel.com/design/pentium4/manuals/245472.htm * * For more information, go to http://www.urbanmyth.org/microcode * @@ -44,6 +44,9 @@ * to be 0 on my machine which is why it worked even when I * disabled update by the BIOS) * Thanks to Eric W. Biederman for the fix. + * 1.08 11 Dec 2000, Richard Schaal and + * Tigran Aivazian + * Intel Pentium 4 processor support and bugfixes. */ #include @@ -58,12 +61,20 @@ #include #include -#define MICROCODE_VERSION "1.07" +#define MICROCODE_VERSION "1.08" -MODULE_DESCRIPTION("Intel CPU (P6) microcode update driver"); +MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver"); MODULE_AUTHOR("Tigran Aivazian "); EXPORT_NO_SYMBOLS; +#define MICRO_DEBUG 0 + +#if MICRO_DEBUG +#define printf(x...) printk(##x) +#else +#define printf(x...) +#endif + /* VFS interface */ static int microcode_open(struct inode *, struct file *); static ssize_t microcode_read(struct file *, char *, size_t, loff_t *); @@ -81,6 +92,7 @@ static char *mc_applied; /* array of applied microcode blocks */ static unsigned int mc_fsize; /* file size of /dev/cpu/microcode */ +/* we share file_operations between misc and devfs mechanisms */ static struct file_operations microcode_fops = { owner: THIS_MODULE, read: microcode_read, @@ -99,23 +111,27 @@ static int __init microcode_init(void) { - int error = 0; + int error; - if (misc_register(µcode_dev) < 0) { + error = misc_register(µcode_dev); + if (error) printk(KERN_WARNING "microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR); - error = 1; - } + devfs_handle = devfs_register(NULL, "cpu/microcode", DEVFS_FL_DEFAULT, 0, 0, S_IFREG | S_IRUSR | S_IWUSR, µcode_fops, NULL); if (devfs_handle == NULL && error) { printk(KERN_ERR "microcode: failed to devfs_register()\n"); - return -EINVAL; + goto out; } - printk(KERN_INFO "P6 Microcode Update Driver v%s\n", MICROCODE_VERSION); - return 0; + printk(KERN_INFO + "IA-32 Microcode Update Driver: v%s \n", + MICROCODE_VERSION); + +out: + return error; } static void __exit microcode_exit(void) @@ -124,12 +140,12 @@ devfs_unregister(devfs_handle); if (mc_applied) kfree(mc_applied); - printk(KERN_INFO "P6 Microcode Update Driver v%s unregistered\n", + printk(KERN_INFO "IA-32 Microcode Update Driver v%s unregistered\n", MICROCODE_VERSION); } -module_init(microcode_init); -module_exit(microcode_exit); +module_init(microcode_init) +module_exit(microcode_exit) static int microcode_open(struct inode *unused1, struct file *unused2) { @@ -175,18 +191,19 @@ unsigned int pf = 0, val[2], rev, sig; int i,found=0; - req->err = 1; /* assume the worst */ + req->err = 1; /* assume update will fail on this cpu */ - if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 != 6){ - printk(KERN_ERR "microcode: CPU%d not an Intel P6\n", cpu_num); + if (c->x86_vendor != X86_VENDOR_INTEL || c->x86 < 6 || + test_bit(X86_FEATURE_IA64, &c->x86_capability)){ + printk(KERN_ERR "microcode: CPU%d not a capable Intel processor\n", cpu_num); return; } sig = c->x86_mask + (c->x86_model<<4) + (c->x86<<8); - if (c->x86_model >= 5) { - /* get processor flags from BBL_CR_OVRD MSR (0x17) */ - rdmsr(0x17, val[0], val[1]); + if ((c->x86_model >= 5) || (c->x86 > 6)) { + /* get processor flags from MSR 0x17 */ + rdmsr(MSR_IA32_PLATFORM_ID, val[0], val[1]); pf = 1 << ((val[1] >> 18) & 7); } @@ -195,9 +212,28 @@ microcode[i].ldrver == 1 && microcode[i].hdrver == 1) { found=1; - wrmsr(0x8B, 0, 0); + + printf("Microcode\n"); + printf(" Header Revision %d\n",microcode[i].hdrver); + printf(" Date %x/%x/%x\n", + ((microcode[i].date >> 24 ) & 0xff), + ((microcode[i].date >> 16 ) & 0xff), + (microcode[i].date & 0xFFFF)); + printf(" Type %x Family %x Model %x Stepping %x\n", + ((microcode[i].sig >> 12) & 0x3), + ((microcode[i].sig >> 8) & 0xf), + ((microcode[i].sig >> 4) & 0xf), + ((microcode[i].sig & 0xf))); + printf(" Checksum %x\n",microcode[i].cksum); + printf(" Loader Revision %x\n",microcode[i].ldrver); + printf(" Processor Flags %x\n\n",microcode[i].pf); + + /* trick, to work even if there was no prior update by the BIOS */ + wrmsr(MSR_IA32_UCODE_REV, 0, 0); __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); - rdmsr(0x8B, val[0], rev); + + /* get current (on-cpu) revision into rev (ignore val[0]) */ + rdmsr(MSR_IA32_UCODE_REV, val[0], rev); if (microcode[i].rev < rev) { printk(KERN_ERR "microcode: CPU%d not 'upgrading' to earlier revision" @@ -219,13 +255,20 @@ break; } - wrmsr(0x79, (unsigned int)(m->bits), 0); + /* write microcode via MSR 0x79 */ + wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(m->bits), 0); + + /* serialize */ __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); - rdmsr(0x8B, val[0], val[1]); + /* get the current revision from MSR 0x8B */ + rdmsr(MSR_IA32_UCODE_REV, val[0], val[1]); + + /* notify the caller of success on this cpu */ req->err = 0; req->slot = i; - printk(KERN_ERR "microcode: CPU%d updated from revision " + + printk(KERN_INFO "microcode: CPU%d updated from revision " "%d to %d, date=%08x\n", cpu_num, rev, val[1], m->date); } @@ -239,18 +282,21 @@ static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos) { - if (*ppos >= mc_fsize) - return 0; + ssize_t ret = 0; + down_read(µcode_rwsem); + if (*ppos >= mc_fsize) + goto out; if (*ppos + len > mc_fsize) len = mc_fsize - *ppos; - if (copy_to_user(buf, mc_applied + *ppos, len)) { - up_read(µcode_rwsem); - return -EFAULT; - } + ret = -EFAULT; + if (copy_to_user(buf, mc_applied + *ppos, len)) + goto out; *ppos += len; + ret = len; +out: up_read(µcode_rwsem); - return len; + return ret; } static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos) @@ -267,8 +313,8 @@ mc_applied = kmalloc(smp_num_cpus*sizeof(struct microcode), GFP_KERNEL); if (!mc_applied) { - printk(KERN_ERR "microcode: out of memory for saved microcode\n"); up_write(µcode_rwsem); + printk(KERN_ERR "microcode: out of memory for saved microcode\n"); return -ENOMEM; } } @@ -307,10 +353,12 @@ case MICROCODE_IOCFREE: down_write(µcode_rwsem); if (mc_applied) { + int bytes = smp_num_cpus * sizeof(struct microcode); + devfs_set_file_size(devfs_handle, 0); kfree(mc_applied); mc_applied = NULL; - printk(KERN_INFO "microcode: freed %d bytes\n", mc_fsize); + printk(KERN_INFO "microcode: freed %d bytes\n", bytes); mc_fsize = 0; up_write(µcode_rwsem); return 0; diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.4.0-test11/linux/arch/i386/kernel/mtrr.c Sun Nov 19 18:44:03 2000 +++ linux/arch/i386/kernel/mtrr.c Tue Nov 28 22:34:01 2000 @@ -480,12 +480,14 @@ } } /* End Function have_wrcomb */ +static u32 size_or_mask, size_and_mask; + static void intel_get_mtrr (unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type *type) { - unsigned long dummy, mask_lo, base_lo; + unsigned long mask_lo, mask_hi, base_lo, base_hi; - rdmsr (MTRRphysMask_MSR(reg), mask_lo, dummy); + rdmsr (MTRRphysMask_MSR(reg), mask_lo, mask_hi); if ( (mask_lo & 0x800) == 0 ) { /* Invalid (i.e. free) range */ @@ -495,20 +497,17 @@ return; } - rdmsr(MTRRphysBase_MSR(reg), base_lo, dummy); + rdmsr(MTRRphysBase_MSR(reg), base_lo, base_hi); - /* We ignore the extra address bits (32-35). If someone wants to - run x86 Linux on a machine with >4GB memory, this will be the - least of their problems. */ + /* Work out the shifted address mask. */ + mask_lo = size_or_mask | mask_hi << (32 - PAGE_SHIFT) + | mask_lo >> PAGE_SHIFT; - /* Clean up mask_lo so it gives the real address mask. */ - mask_lo = (mask_lo & 0xfffff000UL); /* This works correctly if size is a power of two, i.e. a contiguous range. */ - *size = ~(mask_lo - 1); - - *base = (base_lo & 0xfffff000UL); - *type = (base_lo & 0xff); + *size = -mask_lo; + *base = base_hi << (32 - PAGE_SHIFT) | base_lo >> PAGE_SHIFT; + *type = base_lo & 0xff; } /* End Function intel_get_mtrr */ static void cyrix_get_arr (unsigned int reg, unsigned long *base, @@ -533,13 +532,13 @@ /* Enable interrupts if it was enabled previously */ __restore_flags (flags); shift = ((unsigned char *) base)[1] & 0x0f; - *base &= 0xfffff000UL; + *base >>= PAGE_SHIFT; /* Power of two, at least 4K on ARR0-ARR6, 256K on ARR7 * Note: shift==0xf means 4G, this is unsupported. */ if (shift) - *size = (reg < 7 ? 0x800UL : 0x20000UL) << shift; + *size = (reg < 7 ? 0x1UL : 0x40UL) << shift; else *size = 0; @@ -576,7 +575,7 @@ /* Upper dword is region 1, lower is region 0 */ if (reg == 1) low = high; /* The base masks off on the right alignment */ - *base = low & 0xFFFE0000; + *base = (low & 0xFFFE0000) >> PAGE_SHIFT; *type = 0; if (low & 1) *type = MTRR_TYPE_UNCACHABLE; if (low & 2) *type = MTRR_TYPE_WRCOMB; @@ -601,7 +600,7 @@ * *128K ... */ low = (~low) & 0x1FFFC; - *size = (low + 4) << 15; + *size = (low + 4) << (15 - PAGE_SHIFT); return; } /* End Function amd_get_mtrr */ @@ -614,8 +613,8 @@ static void centaur_get_mcr (unsigned int reg, unsigned long *base, unsigned long *size, mtrr_type *type) { - *base = centaur_mcr[reg].high & 0xfffff000; - *size = (~(centaur_mcr[reg].low & 0xfffff000))+1; + *base = centaur_mcr[reg].high >> PAGE_SHIFT; + *size = -(centaur_mcr[reg].low & 0xfffff000) >> PAGE_SHIFT; *type = MTRR_TYPE_WRCOMB; /* If it is there, it is write-combining */ } /* End Function centaur_get_mcr */ @@ -645,8 +644,10 @@ } else { - wrmsr (MTRRphysBase_MSR (reg), base | type, 0); - wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0); + wrmsr (MTRRphysBase_MSR (reg), base << PAGE_SHIFT | type, + (base & size_and_mask) >> (32 - PAGE_SHIFT)); + wrmsr (MTRRphysMask_MSR (reg), -size << PAGE_SHIFT | 0x800, + (-size & size_and_mask) >> (32 - PAGE_SHIFT)); } if (do_safe) set_mtrr_done (&ctxt); } /* End Function intel_set_mtrr_up */ @@ -660,7 +661,9 @@ arr = CX86_ARR_BASE + (reg << 1) + reg; /* avoid multiplication by 3 */ /* count down from 32M (ARR0-ARR6) or from 2G (ARR7) */ - size >>= (reg < 7 ? 12 : 18); + if (reg >= 7) + size >>= 6; + size &= 0x7fff; /* make sure arr_size <= 14 */ for(arr_size = 0; size; arr_size++, size >>= 1); @@ -685,6 +688,7 @@ } if (do_safe) set_mtrr_prepare (&ctxt); + base <<= PAGE_SHIFT; setCx86(arr, ((unsigned char *) &base)[3]); setCx86(arr+1, ((unsigned char *) &base)[2]); setCx86(arr+2, (((unsigned char *) &base)[1]) | arr_size); @@ -704,34 +708,36 @@ [RETURNS] Nothing. */ { - u32 low, high; + u32 regs[2]; struct set_mtrr_context ctxt; if (do_safe) set_mtrr_prepare (&ctxt); /* * Low is MTRR0 , High MTRR 1 */ - rdmsr (0xC0000085, low, high); + rdmsr (0xC0000085, regs[0], regs[1]); /* * Blank to disable */ if (size == 0) - *(reg ? &high : &low) = 0; + regs[reg] = 0; else - /* Set the register to the base (already shifted for us), the - type (off by one) and an inverted bitmask of the size - The size is the only odd bit. We are fed say 512K - We invert this and we get 111 1111 1111 1011 but - if you subtract one and invert you get the desired - 111 1111 1111 1100 mask - */ - *(reg ? &high : &low)=(((~(size-1))>>15)&0x0001FFFC)|base|(type+1); + /* Set the register to the base, the type (off by one) and an + inverted bitmask of the size The size is the only odd + bit. We are fed say 512K We invert this and we get 111 1111 + 1111 1011 but if you subtract one and invert you get the + desired 111 1111 1111 1100 mask + + But ~(x - 1) == ~x + 1 == -x. Two's complement rocks! */ + regs[reg] = (-size>>(15-PAGE_SHIFT) & 0x0001FFFC) + | (base<32M then look at ARR7 immediately */ - if (size > 0x2000000UL) + if (size > 0x2000) { cyrix_get_arr (7, &lbase, &lsize, <ype); - if (lsize < 1) return 7; + if (lsize == 0) return 7; /* Else try ARR0-ARR6 first */ } else @@ -1087,11 +1092,11 @@ { cyrix_get_arr (i, &lbase, &lsize, <ype); if ((i == 3) && arr3_protected) continue; - if (lsize < 1) return i; + if (lsize == 0) return i; } /* ARR0-ARR6 isn't free, try ARR7 but its size must be at least 256K */ cyrix_get_arr (i, &lbase, &lsize, <ype); - if ((lsize < 1) && (size >= 0x40000)) return i; + if ((lsize == 0) && (size >= 0x40)) return i; } return -ENOSPC; } /* End Function cyrix_get_free_region */ @@ -1100,9 +1105,9 @@ unsigned long size) = generic_get_free_region; /** - * mtrr_add - Add a memory type region - * @base: Physical base address of region - * @size: Physical size of region + * mtrr_add_page - Add a memory type region + * @base: Physical base address of region in pages (4 KB) + * @size: Physical size of region in pages (4 KB) * @type: Type of MTRR desired * @increment: If this is true do usage counting on the region * @@ -1135,11 +1140,11 @@ * failures and do not wish system log messages to be sent. */ -int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char increment) +int mtrr_add_page(unsigned long base, unsigned long size, unsigned int type, char increment) { /* [SUMMARY] Add an MTRR entry. - The starting (base) address of the region. - The size (in bytes) of the region. + The starting (base, in pages) address of the region. + The size of the region. (in pages) The type of the new region. If true and the region already exists, the usage count will be incremented. @@ -1164,7 +1169,7 @@ o Power of 2 block o base suitably aligned to the power */ - if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) || + if ( type > MTRR_TYPE_WRCOMB || size < (1 << (17-PAGE_SHIFT)) || (size & ~(size-1))-size || ( base & (size-1) ) ) return -EINVAL; break; @@ -1176,9 +1181,9 @@ boot_cpu_data.x86_model == 1 && boot_cpu_data.x86_mask <= 7 ) { - if ( base & ((1 << 22)-1) ) + if ( base & ((1 << (22-PAGE_SHIFT))-1) ) { - printk (KERN_WARNING "mtrr: base(0x%lx) is not 4 MiB aligned\n", base); + printk (KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base); return -EINVAL; } } @@ -1186,12 +1191,6 @@ case MTRR_IF_CYRIX_ARR: case MTRR_IF_CENTAUR_MCR: - if ( (base & 0xfff) || (size & 0xfff) ) - { - printk ("mtrr: size and base must be multiples of 4 kiB\n"); - printk ("mtrr: size: %lx base: %lx\n", size, base); - return -EINVAL; - } if ( mtrr_if == MTRR_IF_CENTAUR_MCR ) { if (type != MTRR_TYPE_WRCOMB) @@ -1200,9 +1199,9 @@ return -EINVAL; } } - else if (base + size < 0x100000) + else if (base + size < 0x100) { - printk (KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx,0x%lx)\n", + printk (KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n", base, size); return -EINVAL; } @@ -1213,7 +1212,7 @@ lbase = lbase >> 1, last = last >> 1); if (lbase != last) { - printk (KERN_WARNING "mtrr: base(0x%lx) is not aligned on a size(0x%lx) boundary\n", + printk (KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n", base, size); return -EINVAL; } @@ -1228,12 +1227,20 @@ printk ("mtrr: type: %u illegal\n", type); return -EINVAL; } + /* If the type is WC, check that this processor supports it */ if ( (type == MTRR_TYPE_WRCOMB) && !have_wrcomb () ) { printk (KERN_WARNING "mtrr: your processor doesn't support write-combining\n"); return -ENOSYS; } + + if ( base & size_or_mask || size & size_or_mask ) + { + printk ("mtrr: base or size exceeds the MTRR width\n"); + return -EINVAL; + } + increment = increment ? 1 : 0; max = get_num_var_ranges (); /* Search for existing MTRR */ @@ -1247,7 +1254,8 @@ if ( (base < lbase) || (base + size > lbase + lsize) ) { up(&main_lock); - printk (KERN_WARNING "mtrr: 0x%lx,0x%lx overlaps existing 0x%lx,0x%lx\n", + printk (KERN_WARNING "mtrr: 0x%lx000,0x%lx000 overlaps existing" + " 0x%lx000,0x%lx000\n", base, size, lbase, lsize); return -EINVAL; } @@ -1256,7 +1264,7 @@ { if (type == MTRR_TYPE_UNCACHABLE) continue; up(&main_lock); - printk ( "mtrr: type mismatch for %lx,%lx old: %s new: %s\n", + printk ( "mtrr: type mismatch for %lx000,%lx000 old: %s new: %s\n", base, size, attrib_to_str (ltype), attrib_to_str (type) ); return -EINVAL; } @@ -1278,10 +1286,67 @@ compute_ascii (); up(&main_lock); return i; +} /* End Function mtrr_add_page */ + +/** + * mtrr_add - Add a memory type region + * @base: Physical base address of region + * @size: Physical size of region + * @type: Type of MTRR desired + * @increment: If this is true do usage counting on the region + * + * Memory type region registers control the caching on newer Intel and + * non Intel processors. This function allows drivers to request an + * MTRR is added. The details and hardware specifics of each processor's + * implementation are hidden from the caller, but nevertheless the + * caller should expect to need to provide a power of two size on an + * equivalent power of two boundary. + * + * If the region cannot be added either because all regions are in use + * or the CPU cannot support it a negative value is returned. On success + * the register number for this entry is returned, but should be treated + * as a cookie only. + * + * On a multiprocessor machine the changes are made to all processors. + * This is required on x86 by the Intel processors. + * + * The available types are + * + * %MTRR_TYPE_UNCACHEABLE - No caching + * + * %MTRR_TYPE_WRITEBACK - Write data back in bursts whenever + * + * %MTRR_TYPE_WRCOMB - Write data back soon but allow bursts + * + * %MTRR_TYPE_WRTHROUGH - Cache reads but not writes + * + * BUGS: Needs a quiet flag for the cases where drivers do not mind + * failures and do not wish system log messages to be sent. + */ + +int mtrr_add(unsigned long base, unsigned long size, unsigned int type, char increment) +{ +/* [SUMMARY] Add an MTRR entry. + The starting (base) address of the region. + The size (in bytes) of the region. + The type of the new region. + If true and the region already exists, the usage count will be + incremented. + [RETURNS] The MTRR register on success, else a negative number indicating + the error code. +*/ + + if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) + { + printk ("mtrr: size and base must be multiples of 4 kiB\n"); + printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base); + return -EINVAL; + } + return mtrr_add_page(base >> PAGE_SHIFT, size >> PAGE_SHIFT, type, increment); } /* End Function mtrr_add */ /** - * mtrr_del - delete a memory type region + * mtrr_del_page - delete a memory type region * @reg: Register returned by mtrr_add * @base: Physical base address * @size: Size of region @@ -1295,7 +1360,7 @@ * code. */ -int mtrr_del (int reg, unsigned long base, unsigned long size) +int mtrr_del_page (int reg, unsigned long base, unsigned long size) /* [SUMMARY] Delete MTRR/decrement usage count. The register. If this is less than 0 then <> and <> must be supplied. @@ -1320,7 +1385,7 @@ for (i = 0; i < max; ++i) { (*get_mtrr) (i, &lbase, &lsize, <ype); - if ( (lbase == base) && (lsize == size) ) + if (lbase == base && lsize == size) { reg = i; break; @@ -1329,7 +1394,7 @@ if (reg < 0) { up(&main_lock); - printk ("mtrr: no MTRR for %lx,%lx found\n", base, size); + printk ("mtrr: no MTRR for %lx000,%lx000 found\n", base, size); return -EINVAL; } } @@ -1365,12 +1430,46 @@ compute_ascii (); up (&main_lock); return reg; -} /* End Function mtrr_del */ +} /* End Function mtrr_del_page */ + +/** + * mtrr_del - delete a memory type region + * @reg: Register returned by mtrr_add + * @base: Physical base address + * @size: Size of region + * + * If register is supplied then base and size are ignored. This is + * how drivers should call it. + * + * Releases an MTRR region. If the usage count drops to zero the + * register is freed and the region returns to default state. + * On success the register is returned, on failure a negative error + * code. + */ + +int mtrr_del (int reg, unsigned long base, unsigned long size) +/* [SUMMARY] Delete MTRR/decrement usage count. + The register. If this is less than 0 then <> and <> must + be supplied. + The base address of the region. This is ignored if <> is >= 0. + The size of the region. This is ignored if <> is >= 0. + [RETURNS] The register on success, else a negative number indicating + the error code. +*/ +{ + if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) + { + printk ("mtrr: size and base must be multiples of 4 kiB\n"); + printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base); + return -EINVAL; + } + return mtrr_del_page(reg, base >> PAGE_SHIFT, size >> PAGE_SHIFT); +} #ifdef USERSPACE_INTERFACE static int mtrr_file_add (unsigned long base, unsigned long size, - unsigned int type, char increment, struct file *file) + unsigned int type, char increment, struct file *file, int page) { int reg, max; unsigned int *fcount = file->private_data; @@ -1386,18 +1485,38 @@ memset (fcount, 0, max * sizeof *fcount); file->private_data = fcount; } - reg = mtrr_add (base, size, type, 1); + if (!page) { + if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) + { + printk ("mtrr: size and base must be multiples of 4 kiB\n"); + printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base); + return -EINVAL; + } + base >>= PAGE_SHIFT; + size >>= PAGE_SHIFT; + } + reg = mtrr_add_page (base, size, type, 1); if (reg >= 0) ++fcount[reg]; return reg; } /* End Function mtrr_file_add */ static int mtrr_file_del (unsigned long base, unsigned long size, - struct file *file) + struct file *file, int page) { int reg; unsigned int *fcount = file->private_data; - reg = mtrr_del (-1, base, size); + if (!page) { + if ( (base & (PAGE_SIZE - 1)) || (size & (PAGE_SIZE - 1)) ) + { + printk ("mtrr: size and base must be multiples of 4 kiB\n"); + printk ("mtrr: size: 0x%lx base: 0x%lx\n", size, base); + return -EINVAL; + } + base >>= PAGE_SHIFT; + size >>= PAGE_SHIFT; + } + reg = mtrr_del_page (-1, base, size); if (reg < 0) return reg; if (fcount == NULL) return reg; if (fcount[reg] < 1) return -EINVAL; @@ -1418,12 +1537,13 @@ static ssize_t mtrr_write (struct file *file, const char *buf, size_t len, loff_t *ppos) /* Format of control line: - "base=%lx size=%lx type=%s" OR: + "base=%Lx size=%Lx type=%s" OR: "disable=%d" */ { int i, err; - unsigned long reg, base, size; + unsigned long reg; + unsigned long long base, size; char *ptr; char line[LINE_SIZE]; @@ -1438,7 +1558,7 @@ if ( !strncmp (line, "disable=", 8) ) { reg = simple_strtoul (line + 8, &ptr, 0); - err = mtrr_del (reg, 0, 0); + err = mtrr_del_page (reg, 0, 0); if (err < 0) return err; return len; } @@ -1447,14 +1567,20 @@ printk ("mtrr: no \"base=\" in line: \"%s\"\n", line); return -EINVAL; } - base = simple_strtoul (line + 5, &ptr, 0); + base = simple_strtoull (line + 5, &ptr, 0); for (; isspace (*ptr); ++ptr); if ( strncmp (ptr, "size=", 5) ) { printk ("mtrr: no \"size=\" in line: \"%s\"\n", line); return -EINVAL; } - size = simple_strtoul (ptr + 5, &ptr, 0); + size = simple_strtoull (ptr + 5, &ptr, 0); + if ( (base & 0xfff) || (size & 0xfff) ) + { + printk ("mtrr: size and base must be multiples of 4 kiB\n"); + printk ("mtrr: size: 0x%Lx base: 0x%Lx\n", size, base); + return -EINVAL; + } for (; isspace (*ptr); ++ptr); if ( strncmp (ptr, "type=", 5) ) { @@ -1466,7 +1592,9 @@ for (i = 0; i < MTRR_NUM_TYPES; ++i) { if ( strcmp (ptr, mtrr_strings[i]) ) continue; - err = mtrr_add (base, size, i, 1); + base >>= PAGE_SHIFT; + size >>= PAGE_SHIFT; + err = mtrr_add_page ((unsigned long)base, (unsigned long)size, i, 1); if (err < 0) return err; return len; } @@ -1490,7 +1618,7 @@ if ( !suser () ) return -EPERM; if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) ) return -EFAULT; - err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file); + err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 0); if (err < 0) return err; break; case MTRRIOC_SET_ENTRY: @@ -1504,7 +1632,7 @@ if ( !suser () ) return -EPERM; if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) ) return -EFAULT; - err = mtrr_file_del (sentry.base, sentry.size, file); + err = mtrr_file_del (sentry.base, sentry.size, file, 0); if (err < 0) return err; break; case MTRRIOC_KILL_ENTRY: @@ -1519,7 +1647,54 @@ return -EFAULT; if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL; (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type); + + /* Hide entries that go above 4GB */ + if (gentry.base + gentry.size > 0x100000 || gentry.size == 0x100000) + gentry.base = gentry.size = gentry.type = 0; + else { + gentry.base <<= PAGE_SHIFT; + gentry.size <<= PAGE_SHIFT; + gentry.type = type; + } + + if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) ) + return -EFAULT; + break; + case MTRRIOC_ADD_PAGE_ENTRY: + if ( !suser () ) return -EPERM; + if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) ) + return -EFAULT; + err = mtrr_file_add (sentry.base, sentry.size, sentry.type, 1, file, 1); + if (err < 0) return err; + break; + case MTRRIOC_SET_PAGE_ENTRY: + if ( !suser () ) return -EPERM; + if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) ) + return -EFAULT; + err = mtrr_add_page (sentry.base, sentry.size, sentry.type, 0); + if (err < 0) return err; + break; + case MTRRIOC_DEL_PAGE_ENTRY: + if ( !suser () ) return -EPERM; + if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) ) + return -EFAULT; + err = mtrr_file_del (sentry.base, sentry.size, file, 1); + if (err < 0) return err; + break; + case MTRRIOC_KILL_PAGE_ENTRY: + if ( !suser () ) return -EPERM; + if ( copy_from_user (&sentry, (void *) arg, sizeof sentry) ) + return -EFAULT; + err = mtrr_del_page (-1, sentry.base, sentry.size); + if (err < 0) return err; + break; + case MTRRIOC_GET_PAGE_ENTRY: + if ( copy_from_user (&gentry, (void *) arg, sizeof gentry) ) + return -EFAULT; + if ( gentry.regnum >= get_num_var_ranges () ) return -EINVAL; + (*get_mtrr) (gentry.regnum, &gentry.base, &gentry.size, &type); gentry.type = type; + if ( copy_to_user ( (void *) arg, &gentry, sizeof gentry) ) return -EFAULT; break; @@ -1578,24 +1753,24 @@ for (i = 0; i < max; i++) { (*get_mtrr) (i, &base, &size, &type); - if (size < 1) usage_table[i] = 0; + if (size == 0) usage_table[i] = 0; else { - if (size < 0x100000) + if (size < (0x100000 >> PAGE_SHIFT)) { - /* 1MB */ - factor = 'k'; - size >>= 10; + /* less than 1MB */ + factor = 'K'; + size <<= PAGE_SHIFT - 10; } else { factor = 'M'; - size >>= 20; + size >>= 20 - PAGE_SHIFT; } sprintf (ascii_buffer + ascii_buf_bytes, - "reg%02i: base=0x%08lx (%4liMB), size=%4li%cB: %s, count=%d\n", - i, base, base>>20, size, factor, + "reg%02i: base=0x%05lx000 (%4liMB), size=%4li%cB: %s, count=%d\n", + i, base, base >> (20 - PAGE_SHIFT), size, factor, attrib_to_str (type), usage_table[i]); ascii_buf_bytes += strlen (ascii_buffer + ascii_buf_bytes); } @@ -1762,11 +1937,38 @@ mtrr_if = MTRR_IF_INTEL; get_mtrr = intel_get_mtrr; set_mtrr_up = intel_set_mtrr_up; + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_AMD: + /* The original Athlon docs said that + total addressable memory is 44 bits wide. + It was not really clear whether its MTRRs + follow this or not. (Read: 44 or 36 bits). + However, "x86-64_overview.pdf" explicitly + states that "previous implementations support + 36 bit MTRRs" and also provides a way to + query the width (in bits) of the physical + addressable memory on the Hammer family. + */ + if (boot_cpu_data.x86 == 7 && (cpuid_eax(0x80000000) >= 0x80000008)) { + u32 phys_addr; + phys_addr = cpuid_eax(0x80000008) & 0xff ; + size_or_mask = ~((1 << (phys_addr - PAGE_SHIFT)) - 1); + size_and_mask = ~size_or_mask & 0xfff00000; + break; + } + default: + /* Intel, etc. */ + size_or_mask = 0xff000000; /* 36 bits */ + size_and_mask = 0x00f00000; + break; + } } else if ( test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) ) { /* Pre-Athlon (K6) AMD CPU MTRRs */ mtrr_if = MTRR_IF_AMD_K6; get_mtrr = amd_get_mtrr; set_mtrr_up = amd_set_mtrr_up; + size_or_mask = 0xfff00000; /* 32 bits */ + size_and_mask = 0; } else if ( test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ) { /* Cyrix ARRs */ mtrr_if = MTRR_IF_CYRIX_ARR; @@ -1774,12 +1976,16 @@ set_mtrr_up = cyrix_set_arr_up; get_free_region = cyrix_get_free_region; cyrix_arr_init(); + size_or_mask = 0xfff00000; /* 32 bits */ + size_and_mask = 0; } else if ( test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) { /* Centaur MCRs */ mtrr_if = MTRR_IF_CENTAUR_MCR; get_mtrr = centaur_get_mcr; set_mtrr_up = centaur_set_mcr_up; centaur_mcr_init(); + size_or_mask = 0xfff00000; /* 32 bits */ + size_and_mask = 0; } else { /* No supported MTRR interface */ mtrr_if = MTRR_IF_NONE; diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c --- v2.4.0-test11/linux/arch/i386/kernel/pci-irq.c Sun Nov 19 18:44:03 2000 +++ linux/arch/i386/kernel/pci-irq.c Mon Dec 11 17:45:09 2000 @@ -176,7 +176,6 @@ pci_read_config_byte(router, reg, &x); x = (x & 0xe0) | val; /* clear the level->edge transform */ pci_write_config_byte(router, reg, x); - eisa_set_level_irq(irq); } static int pirq_ali_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) @@ -196,7 +195,6 @@ pirq_ali_ide_interrupt(router, 0x75, val, irq); break; } - eisa_set_level_irq(irq); return 1; } return 0; @@ -279,6 +277,54 @@ return 1; } +static int pirq_sis_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + u8 x; + int reg = 0x41 + (pirq - 'A') ; + + pci_read_config_byte(router, reg, &x); + return (x & 0x80) ? 0 : (x & 0x0f); +} + +static int pirq_sis_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +{ + u8 x; + int reg = 0x41 + (pirq - 'A') ; + + pci_read_config_byte(router, reg, &x); + x = (pirq & 0x20) ? 0 : (irq & 0x0f); + pci_write_config_byte(router, reg, x); + + return 1; +} + +/* + * VLSI: nibble offset 0x74 - educated guess due to routing table and + * config space of VLSI 82C534 PCI-bridge/router (1004:0102) + * Tested on HP OmniBook 800 covering PIRQ 1, 2, 4, 8 for onboard + * devices, PIRQ 3 for non-pci(!) soundchip and (untested) PIRQ 6 + * for the busbridge to the docking station. + */ + +static int pirq_vlsi_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + if (pirq > 8) { + printk("VLSI router pirq escape (%d)\n", pirq); + return 0; + } + return read_config_nybble(router, 0x74, pirq-1); +} + +static int pirq_vlsi_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +{ + if (pirq > 8) { + printk("VLSI router pirq escape (%d)\n", pirq); + return 0; + } + write_config_nybble(router, 0x74, pirq-1, irq); + return 1; +} + #ifdef CONFIG_PCI_BIOS static int pirq_bios_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) @@ -309,7 +355,8 @@ { "OPTI", PCI_VENDOR_ID_OPTI, PCI_DEVICE_ID_OPTI_82C700, pirq_opti_get, pirq_opti_set }, { "NatSemi", PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5520, pirq_cyrix_get, pirq_cyrix_set }, - + { "SIS", PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503, pirq_sis_get, pirq_sis_set }, + { "VLSI 82C534", PCI_VENDOR_ID_VLSI, PCI_DEVICE_ID_VLSI_82C534, pirq_vlsi_get, pirq_vlsi_set }, { "default", 0, 0, NULL, NULL } }; @@ -355,7 +402,7 @@ pirq_router_dev->slot_name); } -static struct irq_info *pirq_get_info(struct pci_dev *dev, int pin) +static struct irq_info *pirq_get_info(struct pci_dev *dev) { struct irq_routing_table *rt = pirq_table; int entries = (rt->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info); @@ -373,25 +420,28 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign) { + u8 pin; struct irq_info *info; - int i, pirq, pin, newirq; + int i, pirq, newirq; int irq = 0; u32 mask; struct irq_router *r = pirq_router; - struct pci_dev *dev2, *d; + struct pci_dev *dev2; char *msg = NULL; if (!pirq_table) return 0; /* Find IRQ routing entry */ - pin = pci_get_interrupt_pin(dev, &d); - if (pin < 0) { + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (!pin) { DBG(" -> no interrupt pin\n"); return 0; } - DBG("IRQ for %s(%d) via %s", dev->slot_name, pin, d->slot_name); - info = pirq_get_info(d, pin); + pin = pin - 1; + + DBG("IRQ for %s:%d", dev->slot_name, pin); + info = pirq_get_info(dev); if (!info) { DBG(" -> not found in routing table\n"); return 0; @@ -405,9 +455,12 @@ DBG(" -> PIRQ %02x, mask %04x, excl %04x", pirq, mask, pirq_table->exclusive_irqs); mask &= pcibios_irq_mask; - /* Find the best IRQ to assign */ - newirq = 0; - if (assign) { + /* + * Find the best IRQ to assign: use the one + * reported by the device if possible. + */ + newirq = dev->irq; + if (!newirq && assign) { for (i = 0; i < 16; i++) { if (!(mask & (1 << i))) continue; @@ -417,16 +470,22 @@ newirq = i; } } - DBG(" -> newirq=%d", newirq); } + DBG(" -> newirq=%d", newirq); /* Try to get current IRQ */ - if (r->get && (irq = r->get(pirq_router_dev, d, pirq))) { + if (r->get && (irq = r->get(pirq_router_dev, dev, pirq))) { DBG(" -> got IRQ %d\n", irq); msg = "Found"; + /* We refuse to override the dev->irq information. Give a warning! */ + if (dev->irq && dev->irq != irq) { + printk("IRQ routing conflict in pirq table! Try 'pci=autoirq'\n"); + return 0; + } } else if (newirq && r->set && (dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { DBG(" -> assigning IRQ %d", newirq); - if (r->set(pirq_router_dev, d, pirq, newirq)) { + if (r->set(pirq_router_dev, dev, pirq, newirq)) { + eisa_set_level_irq(newirq); DBG(" ... OK\n"); msg = "Assigned"; irq = newirq; @@ -445,9 +504,14 @@ /* Update IRQ for all devices with the same pirq value */ pci_for_each_dev(dev2) { - if ((pin = pci_get_interrupt_pin(dev2, &d)) >= 0 && - (info = pirq_get_info(d, pin)) && - info->irq[pin].link == pirq) { + pci_read_config_byte(dev2, PCI_INTERRUPT_PIN, &pin); + if (!pin) + continue; + pin--; + info = pirq_get_info(dev2); + if (!info) + continue; + if (info->irq[pin].link == pirq) { dev2->irq = irq; pirq_penalty[irq]++; if (dev != dev2) @@ -556,19 +620,17 @@ void pcibios_enable_irq(struct pci_dev *dev) { - if (!dev->irq) { - u8 pin; - pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); - if (pin && !pcibios_lookup_irq(dev, 1)) { - char *msg; - if (io_apic_assign_pci_irqs) - msg = " Probably buggy MP table."; - else if (pci_probe & PCI_BIOS_IRQ_SCAN) - msg = ""; - else - msg = " Please try using pci=biosirq."; - printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", - 'A' + pin - 1, dev->slot_name, msg); - } + u8 pin; + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) { + char *msg; + if (io_apic_assign_pci_irqs) + msg = " Probably buggy MP table."; + else if (pci_probe & PCI_BIOS_IRQ_SCAN) + msg = ""; + else + msg = " Please try using pci=biosirq."; + printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n", + 'A' + pin - 1, dev->slot_name, msg); } } diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c --- v2.4.0-test11/linux/arch/i386/kernel/process.c Sun Oct 8 10:50:06 2000 +++ linux/arch/i386/kernel/process.c Fri Nov 24 18:32:20 2000 @@ -496,9 +496,9 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm) { struct mm_struct * old_mm = current->mm; - void * old_ldt = old_mm->segments, * ldt = old_ldt; + void * old_ldt = old_mm->segments, * ldt; - if (!old_mm->segments) { + if (!old_ldt) { /* * default LDT - use the one from init_task */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.4.0-test11/linux/arch/i386/kernel/setup.c Sun Nov 19 18:44:03 2000 +++ linux/arch/i386/kernel/setup.c Wed Dec 6 21:00:12 2000 @@ -126,7 +126,7 @@ */ struct drive_info_struct { char dummy[32]; } drive_info; struct screen_info screen_info; -struct apm_bios_info apm_bios_info; +struct apm_info apm_info; struct sys_desc_table_struct { unsigned short length; unsigned char table[0]; @@ -608,7 +608,7 @@ ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV); drive_info = DRIVE_INFO; screen_info = SCREEN_INFO; - apm_bios_info = APM_BIOS_INFO; + apm_info.bios = APM_BIOS_INFO; if( SYS_DESC_TABLE.length != 0 ) { MCA_bus = SYS_DESC_TABLE.table[3] &0x2; machine_id = SYS_DESC_TABLE.table[0]; @@ -1531,8 +1531,32 @@ dh = des >> 4; dl = des & 0x0F; + /* Black magic... */ + switch ( dh ) { + case 0: + switch ( dl ) { + case 6: + /* L1 I cache */ + l1i += 8; + break; + case 8: + /* L1 I cache */ + l1i += 16; + break; + case 10: + /* L1 D cache */ + l1d += 8; + break; + case 12: + /* L1 D cache */ + l1d += 16; + break; + default: + /* TLB, or unknown */ + } + break; case 2: if ( dl ) { /* L3 cache */ @@ -1541,6 +1565,16 @@ } break; case 4: + if ( c->x86 > 6 && dl ) { + /* P4 family */ + if ( dl ) { + /* L3 cache */ + cs = 128 << (dl-1); + l3 += cs; + break; + } + } + /* else same as 8 - fall through */ case 8: if ( dl ) { /* L2 cache */ @@ -1556,9 +1590,16 @@ } break; case 7: - /* L1 I cache */ - cs = dl ? (16 << (dl-1)) : 12; - l1i += cs; + if ( dl >= 8 ) + { + /* L2 cache */ + cs = 64<<(dl-8); + l2 += cs; + } else { + /* L0 I cache, count as L1 */ + cs = dl ? (16 << (dl-1)) : 12; + l1i += cs; + } break; default: /* TLB, or something else we don't know about */ @@ -2066,8 +2107,8 @@ /* Intel-defined */ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", - "pat", "pse36", "pn", "clflsh", NULL, "dtes", "acpi", "mmx", - "fxsr", "sse", "sse2", "selfsnoop", NULL, "acc", "ia64", NULL, + "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", + "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL, /* AMD-defined */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -2113,7 +2154,7 @@ p += sprintf(p, "stepping\t: unknown\n"); if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) { - p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n", + p += sprintf(p, "cpu MHz\t\t: %lu.%03lu\n", cpu_khz / 1000, (cpu_khz % 1000)); } @@ -2131,7 +2172,7 @@ "fpu_exception\t: %s\n" "cpuid level\t: %d\n" "wp\t\t: %s\n" - "features\t:", + "flags\t\t:", c->fdiv_bug ? "yes" : "no", c->hlt_works_ok ? "no" : "yes", c->f00f_bug ? "yes" : "no", diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c --- v2.4.0-test11/linux/arch/i386/kernel/smpboot.c Sun Nov 19 18:44:03 2000 +++ linux/arch/i386/kernel/smpboot.c Sun Dec 3 17:48:19 2000 @@ -886,8 +886,10 @@ /* * If we couldn't find a local APIC, then get out of here now! */ - if (!verify_local_APIC()) { - printk(KERN_ERR "BIOS bug, local APIC at 0x%lX not detected!...\n", mp_lapic_addr); + if (APIC_INTEGRATED(apic_version[boot_cpu_id]) && + !test_bit(X86_FEATURE_APIC, boot_cpu_data.x86_capability)) { + printk(KERN_ERR "BIOS bug, local APIC #%d not detected!...\n", + boot_cpu_id); printk(KERN_ERR "... forcing use of dummy APIC emulation. (tell your hw vendor)\n"); #ifndef CONFIG_VISWS io_apic_irqs = 0; @@ -896,6 +898,8 @@ smp_num_cpus = 1; goto smp_done; } + + verify_local_APIC(); /* * If SMP should be disabled, then really disable it! diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.4.0-test11/linux/arch/i386/kernel/traps.c Sun Nov 19 18:44:03 2000 +++ linux/arch/i386/kernel/traps.c Sun Dec 3 17:48:19 2000 @@ -62,19 +62,7 @@ */ struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, }; -extern int console_loglevel; extern void bust_spinlocks(void); - -static inline void console_silent(void) -{ - console_loglevel = 0; -} - -static inline void console_verbose(void) -{ - if (console_loglevel) - console_loglevel = 15; -} asmlinkage void divide_error(void); asmlinkage void debug(void); diff -u --recursive --new-file v2.4.0-test11/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- v2.4.0-test11/linux/arch/i386/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/mm/init.c Tue Nov 28 22:43:39 2000 @@ -198,7 +198,7 @@ void show_mem(void) { - int i,free = 0, total = 0, reserved = 0; + int i, total = 0, reserved = 0; int shared = 0, cached = 0; int highmem = 0; @@ -214,9 +214,7 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!page_count(mem_map+i)) - free++; - else + else if (page_count(mem_map+i)) shared += page_count(mem_map+i) - 1; } printk("%d pages of RAM\n", total); @@ -437,7 +435,7 @@ } /* - * paging_init() sets up the page tables - note that the first 4MB are + * paging_init() sets up the page tables - note that the first 8MB are * already mapped by head.S. * * This routines also unmaps the page at virtual kernel address 0, so diff -u --recursive --new-file v2.4.0-test11/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c --- v2.4.0-test11/linux/arch/ia64/kernel/irq.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ia64/kernel/irq.c Sun Dec 3 17:45:20 2000 @@ -181,7 +181,7 @@ #ifdef CONFIG_SMP unsigned int global_irq_holder = NO_PROC_ID; -volatile unsigned int global_irq_lock; +volatile unsigned long global_irq_lock; /* long for set_bit --RR */ extern void show_stack(unsigned long* esp); diff -u --recursive --new-file v2.4.0-test11/linux/arch/ia64/mm/init.c linux/arch/ia64/mm/init.c --- v2.4.0-test11/linux/arch/ia64/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ia64/mm/init.c Tue Nov 28 22:43:39 2000 @@ -245,7 +245,7 @@ void show_mem (void) { - int i,free = 0,total = 0,reserved = 0; + int i, total = 0, reserved = 0; int shared = 0, cached = 0; printk("Mem-info:\n"); @@ -258,9 +258,7 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!page_count(mem_map + i)) - free++; - else + else if (page_count(mem_map + i)) shared += page_count(mem_map + i) - 1; } printk("%d pages of RAM\n", total); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/amiga/amiga_ksyms.c linux/arch/m68k/amiga/amiga_ksyms.c --- v2.4.0-test11/linux/arch/m68k/amiga/amiga_ksyms.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/amiga/amiga_ksyms.c Mon Nov 27 17:57:34 2000 @@ -25,7 +25,6 @@ EXPORT_SYMBOL(amiga_audio_min_period); EXPORT_SYMBOL(amiga_do_irq); EXPORT_SYMBOL(amiga_do_irq_list); -EXPORT_SYMBOL(amiga_intena_vals); #ifdef CONFIG_AMIGA_PCMCIA EXPORT_SYMBOL(pcmcia_reset); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/amiga/amiints.c linux/arch/m68k/amiga/amiints.c --- v2.4.0-test11/linux/arch/m68k/amiga/amiints.c Mon Jun 19 12:56:08 2000 +++ linux/arch/m68k/amiga/amiints.c Mon Nov 27 17:57:34 2000 @@ -58,7 +58,7 @@ /* irq node variables for amiga interrupt sources */ static irq_node_t *ami_irq_list[AMI_STD_IRQS]; -unsigned short amiga_intena_vals[AMI_STD_IRQS] = { +static unsigned short amiga_intena_vals[AMI_STD_IRQS] = { IF_VERTB, IF_COPER, IF_AUD0, IF_AUD1, IF_AUD2, IF_AUD3, IF_BLIT, IF_DSKSYN, IF_DSKBLK, IF_RBF, IF_TBE, IF_SOFT, IF_PORTS, IF_EXTER }; @@ -106,7 +106,7 @@ /* turn off PCMCIA interrupts */ if (AMIGAHW_PRESENT(PCMCIA)) - pcmcia_disable_irq(); + gayle.inten = GAYLE_IRQ_IDE; /* turn off all interrupts and enable the master interrupt bit */ custom.intena = 0x7fff; @@ -352,67 +352,16 @@ ami_irq_list[irq]->handler(irq, ami_irq_list[irq]->dev_id, fp); } -void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server) +void amiga_do_irq_list(int irq, struct pt_regs *fp) { - irq_node_t *node, *slow_nodes; - unsigned short flags, intena; + irq_node_t *node; kstat.irqs[0][SYS_IRQS + irq]++; - if (server->count++) - server->reentrance = 1; - - intena = amiga_intena_vals[irq]; - custom.intreq = intena; - - /* serve fast handler if present - there can only be one of these */ - node = ami_irq_list[irq]; - /* - * Timer interrupts show up like this - */ - if (!node) { - server->count--; - return; - } + custom.intreq = amiga_intena_vals[irq]; - if (node && (node->flags & SA_INTERRUPT)) { - save_flags(flags); - cli(); + for (node = ami_irq_list[irq]; node; node = node->next) node->handler(irq, node->dev_id, fp); - restore_flags(flags); - - server->count--; - return; - } - - /* - * Disable the interrupt source in question and reenable all - * other interrupts. No interrupt handler should ever touch - * the intena flags directly! - */ - custom.intena = intena; - save_flags(flags); -#if 0 /* def CPU_M68060_ONLY */ - sti(); -#else - restore_flags((flags & ~0x0700) | (fp->sr & 0x0700)); -#endif - - slow_nodes = node; - for (;;) { - for (; node; node = node->next) - node->handler(irq, node->dev_id, fp); - - if (!server->reentrance) { - server->count--; - restore_flags(flags); - custom.intena = IF_SETCLR | intena; - return; - } - - server->reentrance = 0; - node = slow_nodes; - } } /* @@ -445,7 +394,6 @@ static void ami_int3(int irq, void *dev_id, struct pt_regs *fp) { unsigned short ints = custom.intreqr & custom.intenar; - static struct irq_server server = {0, 0}; /* if a blitter interrupt */ if (ints & IF_BLIT) { @@ -461,7 +409,7 @@ /* if a vertical blank interrupt */ if (ints & IF_VERTB) - amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server); + amiga_do_irq_list(IRQ_AMIGA_VERTB, fp); } static void ami_int4(int irq, void *dev_id, struct pt_regs *fp) diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/amiga/amisound.c linux/arch/m68k/amiga/amisound.c --- v2.4.0-test11/linux/arch/m68k/amiga/amisound.c Fri Jul 14 12:20:22 2000 +++ linux/arch/m68k/amiga/amisound.c Mon Nov 27 17:57:34 2000 @@ -8,6 +8,7 @@ * for more details. */ +#include #include #include #include @@ -42,7 +43,9 @@ void __init amiga_init_sound(void) { - snd_data = amiga_chip_alloc(sizeof(sine_data), "Beep"); + static struct resource beep_res = { "Beep" }; + + snd_data = amiga_chip_alloc_res(sizeof(sine_data), &beep_res); if (!snd_data) { printk (KERN_CRIT "amiga init_sound: failed to allocate chipmem\n"); return; @@ -51,6 +54,11 @@ /* setup divisor */ clock_constant = (amiga_colorclock+DATA_SIZE/2)/DATA_SIZE; + + /* without amifb, turn video off and enable high quality sound */ +#ifndef CONFIG_FB_AMIGA + amifb_video_off(); +#endif } static void nosound( unsigned long ignored ); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/amiga/chipram.c linux/arch/m68k/amiga/chipram.c --- v2.4.0-test11/linux/arch/m68k/amiga/chipram.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/amiga/chipram.c Mon Nov 27 17:57:34 2000 @@ -3,173 +3,127 @@ ** ** Modified 03-May-94 by Geert Uytterhoeven ** - 64-bit aligned allocations for full AGA compatibility +** +** Rewritten 15/9/2000 by Geert to use resource management */ +#include #include #include #include #include +#include #include -struct chip_desc { - unsigned first : 1; - unsigned last : 1; - unsigned alloced : 1; - unsigned length : 24; - long pad; /* We suppose this makes this struct 64 bits long!! */ -}; +unsigned long amiga_chip_size; -#define DP(ptr) ((struct chip_desc *)(ptr)) - -u_long amiga_chip_size; +static struct resource chipram_res = { "Chip RAM", CHIP_PHYSADDR }; static unsigned long chipavail; -static struct resource chipram = { "Chip RAM", 0 }; -unsigned long amiga_chip_avail( void ) +void __init amiga_chip_init(void) { -#ifdef DEBUG - printk("chip_avail : %ld bytes\n",chipavail); + if (!AMIGAHW_PRESENT(CHIP_RAM)) + return; + +#ifndef CONFIG_APUS_FAST_EXCEPT + /* + * Remove the first 4 pages where PPC exception handlers will be located + */ + amiga_chip_size -= 0x4000; #endif - return chipavail; -} + chipram_res.end = amiga_chip_size-1; + request_resource(&iomem_resource, &chipram_res); + chipavail = amiga_chip_size; +} -void __init amiga_chip_init (void) + +void *amiga_chip_alloc(unsigned long size, const char *name) { - struct chip_desc *dp; - - if (!AMIGAHW_PRESENT(CHIP_RAM)) - return; - - chipram.end = amiga_chip_size-1; - request_resource(&iomem_resource, &chipram); + struct resource *res; - /* initialize start boundary */ - - dp = DP(chipaddr); - dp->first = 1; - - dp->alloced = 0; - dp->length = amiga_chip_size - 2*sizeof(*dp); - - /* initialize end boundary */ - dp = DP(chipaddr + amiga_chip_size) - 1; - dp->last = 1; - - dp->alloced = 0; - dp->length = amiga_chip_size - 2*sizeof(*dp); - chipavail = dp->length; /*MILAN*/ + /* round up */ + size = PAGE_ALIGN(size); #ifdef DEBUG - printk ("chipram end boundary is %p, length is %d\n", dp, - dp->length); + printk("amiga_chip_alloc: allocate %ld bytes\n", size); #endif -} - -void *amiga_chip_alloc(long size, const char *name) -{ - /* last chunk */ - struct chip_desc *dp; - void *ptr; - - /* round off */ - size = (size + 7) & ~7; + res = kmalloc(sizeof(struct resource), GFP_KERNEL); + if (!res) + return NULL; + memset(res, 0, sizeof(struct resource)); + res->name = name; + if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { + kfree(res); + return NULL; + } + chipavail -= size; #ifdef DEBUG - printk("amiga_chip_alloc: allocate %ld bytes\n", size); + printk("amiga_chip_alloc: returning %lx\n", res->start); #endif + return (void *)ZTWO_VADDR(res->start); +} - /* - * get pointer to descriptor for last chunk by - * going backwards from end chunk - */ - dp = DP(chipaddr + amiga_chip_size) - 1; - dp = DP((unsigned long)dp - dp->length) - 1; - - while ((dp->alloced || dp->length < size) - && !dp->first) - dp = DP ((unsigned long)dp - dp[-1].length) - 2; - if (dp->alloced || dp->length < size) { - printk ("no chipmem available for %ld allocation\n", size); - return NULL; - } + /* + * Warning: + * amiga_chip_alloc_res is meant only for drivers that need to allocate + * Chip RAM before kmalloc() is functional. As a consequence, those + * drivers must not free that Chip RAM afterwards. + */ - if (dp->length < (size + 2*sizeof(*dp))) { - /* length too small to split; allocate the whole thing */ - dp->alloced = 1; - ptr = (void *)(dp+1); - dp = DP((unsigned long)ptr + dp->length); - dp->alloced = 1; -#ifdef DEBUG - printk ("amiga_chip_alloc: no split\n"); -#endif - } else { - /* split the extent; use the end part */ - long newsize = dp->length - (2*sizeof(*dp) + size); +void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res) +{ + unsigned long start; + + /* round up */ + size = PAGE_ALIGN(size); + /* dmesg into chipmem prefers memory at the safe end */ + start = CHIP_PHYSADDR + chipavail - size; #ifdef DEBUG - printk ("amiga_chip_alloc: splitting %d to %ld\n", dp->length, - newsize); + printk("amiga_chip_alloc_res: allocate %ld bytes\n", size); #endif - dp->length = newsize; - dp = DP((unsigned long)(dp+1) + newsize); - dp->first = dp->last = 0; - dp->alloced = 0; - dp->length = newsize; - dp++; - dp->first = dp->last = 0; - dp->alloced = 1; - dp->length = size; - ptr = (void *)(dp+1); - dp = DP((unsigned long)ptr + size); - dp->alloced = 1; - dp->length = size; - } - + if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { + printk("amiga_chip_alloc_res: first alloc failed!\n"); + if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) + return NULL; + } + chipavail -= size; #ifdef DEBUG - printk ("amiga_chip_alloc: returning %p\n", ptr); + printk("amiga_chip_alloc_res: returning %lx\n", res->start); #endif - - if ((unsigned long)ptr & 7) - panic("amiga_chip_alloc: alignment violation\n"); - - chipavail -= size + (2*sizeof(*dp)); /*MILAN*/ - - if (!request_mem_region(ZTWO_PADDR(ptr), size, name)) - printk(KERN_WARNING "amiga_chip_alloc: region of size %ld at 0x%08lx " - "is busy\n", size, ZTWO_PADDR(ptr)); - - return ptr; + return (void *)ZTWO_VADDR(res->start); } -void amiga_chip_free (void *ptr) +void amiga_chip_free(void *ptr) { - struct chip_desc *sdp = DP(ptr) - 1, *dp2; - struct chip_desc *edp = DP((unsigned long)ptr + sdp->length); + unsigned long start = ZTWO_PADDR(ptr); + struct resource **p, *res; + unsigned long size; + + for (p = &chipram_res.child; (res = *p); p = &res->sibling) { + if (res->start != start) + continue; + *p = res->sibling; + size = res->end-start; +#ifdef DEBUG + printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr); +#endif + chipavail += size; + kfree(res); + return; + } + printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr); +} - chipavail += sdp->length + (2* sizeof(sdp)); /*MILAN*/ + +unsigned long amiga_chip_avail(void) +{ #ifdef DEBUG - printk("chip_free: free %ld bytes at %p\n",sdp->length,ptr); + printk("amiga_chip_avail : %ld bytes\n", chipavail); #endif - /* deallocate the chunk */ - sdp->alloced = edp->alloced = 0; - release_mem_region(ZTWO_PADDR(ptr), sdp->length); - - /* check if we should merge with the previous chunk */ - if (!sdp->first && !sdp[-1].alloced) { - dp2 = DP((unsigned long)sdp - sdp[-1].length) - 2; - dp2->length += sdp->length + 2*sizeof(*sdp); - edp->length = dp2->length; - sdp = dp2; - } - - /* check if we should merge with the following chunk */ - if (!edp->last && !edp[1].alloced) { - dp2 = DP((unsigned long)edp + edp[1].length) + 2; - dp2->length += edp->length + 2*sizeof(*sdp); - sdp->length = dp2->length; - edp = dp2; - } + return chipavail; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c --- v2.4.0-test11/linux/arch/m68k/amiga/cia.c Sun Aug 15 11:47:29 1999 +++ linux/arch/m68k/amiga/cia.c Mon Nov 27 17:57:34 2000 @@ -27,18 +27,17 @@ u_short int_mask; int handler_irq, cia_irq, server_irq; char *name; - struct irq_server server; irq_handler_t irq_list[CIA_IRQS]; } ciaa_base = { &ciaa, 0, 0, IF_PORTS, IRQ_AMIGA_AUTO_2, IRQ_AMIGA_CIAA, IRQ_AMIGA_PORTS, - "CIAA handler", {0, 0} + "CIAA handler" }, ciab_base = { &ciab, 0, 0, IF_EXTER, IRQ_AMIGA_AUTO_6, IRQ_AMIGA_CIAB, IRQ_AMIGA_EXTER, - "CIAB handler", {0, 0} + "CIAB handler" }; /* @@ -136,7 +135,7 @@ } ints >>= 1; } - amiga_do_irq_list(base->server_irq, fp, &base->server); + amiga_do_irq_list(base->server_irq, fp); } void __init cia_init_IRQ(struct ciabase *base) diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c --- v2.4.0-test11/linux/arch/m68k/amiga/config.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/amiga/config.c Mon Nov 27 17:57:34 2000 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -43,17 +44,36 @@ unsigned char amiga_psfreq; struct amiga_hw_present amiga_hw_present; -static const char *amiga_models[] = { - "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000", - "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco" +static const char s_a500[] __initdata = "A500"; +static const char s_a500p[] __initdata = "A500+"; +static const char s_a600[] __initdata = "A600"; +static const char s_a1000[] __initdata = "A1000"; +static const char s_a1200[] __initdata = "A1200"; +static const char s_a2000[] __initdata = "A2000"; +static const char s_a2500[] __initdata = "A2500"; +static const char s_a3000[] __initdata = "A3000"; +static const char s_a3000t[] __initdata = "A3000T"; +static const char s_a3000p[] __initdata = "A3000+"; +static const char s_a4000[] __initdata = "A4000"; +static const char s_a4000t[] __initdata = "A4000T"; +static const char s_cdtv[] __initdata = "CDTV"; +static const char s_cd32[] __initdata = "CD32"; +static const char s_draco[] __initdata = "Draco"; +static const char *amiga_models[] __initdata = { + s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000, + s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco, }; +static char amiga_model_name[13] = "Amiga "; + extern char m68k_debug_device[]; static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *)); /* amiga specific keyboard functions */ extern int amiga_keyb_init(void); extern int amiga_kbdrate (struct kbd_repeat *); +extern int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep, + char raw_mode); /* amiga specific irq functions */ extern void amiga_init_IRQ (void); extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *); @@ -127,6 +147,8 @@ NULL, 0x00dc0000, 0x00dcffff }; +static struct resource ram_resource[NUM_MEMINFO]; + /* * Parse an Amiga-specific record in the bootinfo @@ -200,8 +222,10 @@ memset(&amiga_hw_present, 0, sizeof(amiga_hw_present)); printk("Amiga hardware found: "); - if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) + if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) { printk("[%s] ", amiga_models[amiga_model-AMI_500]); + strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]); + } switch(amiga_model) { case AMI_UNKNOWN: @@ -367,6 +391,8 @@ mach_sched_init = amiga_sched_init; mach_keyb_init = amiga_keyb_init; mach_kbdrate = amiga_kbdrate; + mach_kbd_translate = amiga_kbd_translate; + SYSRQ_KEY = 0xff; mach_init_IRQ = amiga_init_IRQ; mach_default_handler = &amiga_default_handler; mach_request_irq = amiga_request_irq; @@ -447,6 +473,17 @@ disabled_z2mem>>10); } + /* request all RAM */ + for (i = 0; i < m68k_num_memory; i++) { + ram_resource[i].name = + (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" : + (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" : + "16-bit Slow RAM"; + ram_resource[i].start = m68k_memory[i].addr; + ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1; + request_resource(&iomem_resource, &ram_resource[i]); + } + /* initialize chipram allocator */ amiga_chip_init (); @@ -478,8 +515,11 @@ static void __init amiga_sched_init(void (*timer_routine)(int, void *, struct pt_regs *)) { + static struct resource sched_res = { "timer" }; jiffy_ticks = (amiga_eclock+HZ/2)/HZ; + if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer")) + printk("Cannot allocate ciab.ta{lo,hi}\n"); ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */ ciab.talo = jiffy_ticks % 256; ciab.tahi = jiffy_ticks / 256; @@ -827,7 +867,9 @@ static void amiga_savekmsg_init(void) { - savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug"); + static struct resource debug_res = { "Debug" }; + + savekmsg = amiga_chip_alloc_res(SAVEKMSG_MAXMEM, &debug_res); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; savekmsg->magicptr = virt_to_phys(savekmsg); @@ -933,9 +975,7 @@ static void amiga_get_model(char *model) { - strcpy(model, "Amiga "); - if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) - strcat(model, amiga_models[amiga_model-AMI_500]); + strcpy(model, amiga_model_name); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c --- v2.4.0-test11/linux/arch/m68k/atari/atakeyb.c Fri Jul 14 12:20:22 2000 +++ linux/arch/m68k/atari/atakeyb.c Tue Dec 5 12:43:47 2000 @@ -13,6 +13,7 @@ * enhanced by Bjoern Brauel and Roman Hodek */ +#include #include #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include @@ -362,7 +364,7 @@ if (acia_stat & ACIA_RDRF) /* received a character */ { scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */ - mark_bh(KEYBOARD_BH); + tasklet_schedule(&keyboard_tasklet); interpret_scancode: switch (kb_state.state) { @@ -860,3 +862,16 @@ return( 0 ); } + +int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) +{ +#ifdef CONFIG_MAGIC_SYSRQ + /* ALT+HELP pressed? */ + if ((keycode == 98) && ((shift_state & 0xff) == 8)) + *keycodep = 0xff; + else +#endif + *keycodep = keycode; + return 1; +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c --- v2.4.0-test11/linux/arch/m68k/atari/config.c Wed Jan 26 12:44:20 2000 +++ linux/arch/m68k/atari/config.c Mon Nov 27 17:57:34 2000 @@ -60,6 +60,8 @@ /* atari specific keyboard functions */ extern int atari_keyb_init(void); extern int atari_kbdrate (struct kbd_repeat *); +extern int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, + char raw_mode); extern void atari_kbd_leds (unsigned int); /* atari specific irq functions */ extern void atari_init_IRQ (void); @@ -253,6 +255,8 @@ mach_sched_init = atari_sched_init; mach_keyb_init = atari_keyb_init; mach_kbdrate = atari_kbdrate; + mach_kbd_translate = atari_kbd_translate; + SYSRQ_KEY = 0xff; mach_kbd_leds = atari_kbd_leds; mach_init_IRQ = atari_init_IRQ; mach_request_irq = atari_request_irq; diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c --- v2.4.0-test11/linux/arch/m68k/atari/stram.c Mon Aug 7 21:02:27 2000 +++ linux/arch/m68k/atari/stram.c Mon Nov 27 17:57:34 2000 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -33,6 +34,7 @@ #ifdef CONFIG_STRAM_SWAP #define MAJOR_NR Z2RAM_MAJOR +#define do_z2_request do_stram_request #include #undef DEVICE_NAME #define DEVICE_NAME "stram" @@ -123,6 +125,10 @@ unswap_by_move disabled because it does not handle swapped shm pages. */ +/* 2000-05-01: ++andreas + Integrated with bootmem. Remove all traces of unswap_by_move. +*/ + #ifdef CONFIG_STRAM_SWAP #define ALIGN_IF_SWAP(x) PAGE_ALIGN(x) #else @@ -130,10 +136,10 @@ #endif /* get index of swap page at address 'addr' */ -#define SWAP_NR(addr) (((unsigned long)(addr)-swap_start) >> PAGE_SHIFT) +#define SWAP_NR(addr) (((addr) - swap_start) >> PAGE_SHIFT) /* get address of swap page #'nr' */ -#define SWAP_ADDR(nr) ((void *)(swap_start + ((nr)<> PAGE_SHIFT) @@ -144,11 +150,8 @@ #define MAX_STRAM_FRACTION_NOM 1 #define MAX_STRAM_FRACTION_DENOM 3 -/* Start and end of the (pre-mem_init) reserved ST-RAM region */ -static unsigned long rsvd_stram_beg, rsvd_stram_end; - /* Start and end (virtual) of ST-RAM */ -static unsigned long stram_start, stram_end; +static void *stram_start, *stram_end; /* set after memory_init() executed and allocations via start_mem aren't * possible anymore */ @@ -159,7 +162,7 @@ typedef struct stram_block { struct stram_block *next; - unsigned long start; + void *start; unsigned long size; unsigned flags; const char *owner; @@ -168,7 +171,6 @@ /* values for flags field */ #define BLOCK_FREE 0x01 /* free structure in the BLOCKs pool */ #define BLOCK_KMALLOCED 0x02 /* structure allocated by kmalloc() */ -#define BLOCK_STATIC 0x04 /* pre-mem_init() allocated block */ #define BLOCK_GFP 0x08 /* block allocated with __get_dma_pages() */ #define BLOCK_INSWAP 0x10 /* block allocated in swap space */ @@ -191,7 +193,7 @@ static int max_swap_size = -1; /* start and end of swapping area */ -static unsigned long swap_start, swap_end; +static void *swap_start, *swap_end; /* The ST-RAM's swap info structure */ static struct swap_info_struct *stram_swap_info; @@ -215,7 +217,6 @@ #ifdef DO_PROC static unsigned stat_swap_read = 0; static unsigned stat_swap_write = 0; -static unsigned stat_swap_move = 0; static unsigned stat_swap_force = 0; #endif /* DO_PROC */ @@ -224,21 +225,19 @@ /***************************** Prototypes *****************************/ #ifdef CONFIG_STRAM_SWAP -static int swap_init( unsigned long start_mem, unsigned long swap_data ); +static int swap_init(void *start_mem, void *swap_data); static void *get_stram_region( unsigned long n_pages ); static void free_stram_region( unsigned long offset, unsigned long n_pages ); -static int in_some_region( unsigned long addr ); +static int in_some_region(void *addr); static unsigned long find_free_region( unsigned long n_pages, unsigned long *total_free, unsigned long *region_free ); -static void do_stram_request( void ); +static void do_stram_request(request_queue_t *); static int stram_open( struct inode *inode, struct file *filp ); static int stram_release( struct inode *inode, struct file *filp ); -static void do_z2_request( void ); #endif -static int get_gfp_order( unsigned long size ); -static void reserve_region( unsigned long addr, unsigned long end ); +static void reserve_region(void *start, void *end); static BLOCK *add_region( void *addr, unsigned long size ); static BLOCK *find_region( void *addr ); static int remove_region( BLOCK *block ); @@ -264,14 +263,12 @@ /* determine whether kernel code resides in ST-RAM (then ST-RAM is the * first memory block at virtual 0x0) */ - stram_start = (unsigned long)phys_to_virt(0); + stram_start = phys_to_virt(0); kernel_in_stram = (stram_start == 0); for( i = 0; i < m68k_num_memory; ++i ) { if (m68k_memory[i].addr == 0) { /* skip first 2kB or page (supervisor-only!) */ - rsvd_stram_beg = stram_start + ALIGN_IF_SWAP(0x800); - rsvd_stram_end = rsvd_stram_beg; stram_end = stram_start + m68k_memory[i].size; return; } @@ -282,10 +279,10 @@ /* - * This function is called from mem_init() to reserve the pages needed for + * This function is called from setup_arch() to reserve the pages needed for * ST-RAM management. */ -void __init atari_stram_reserve_pages(unsigned long start_mem) +void __init atari_stram_reserve_pages(void *start_mem) { #ifdef CONFIG_STRAM_SWAP /* if max_swap_size is negative (i.e. no stram_swap= option given), @@ -299,42 +296,24 @@ max_swap_size = (!MACH_IS_HADES && (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <= - max_mapnr*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0; + (high_memory>>PAGE_SHIFT)*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0; DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size ); #endif /* always reserve first page of ST-RAM, the first 2 kB are * supervisor-only! */ - set_bit( PG_reserved, &virt_to_page(stram_start)->flags ); + if (!kernel_in_stram) + reserve_bootmem (0, PAGE_SIZE); #ifdef CONFIG_STRAM_SWAP - if (!max_swap_size) { - fallback: -#endif - DPRINTK( "atari_stram_reserve_pages: swapping disabled\n" ); - if (!kernel_in_stram) { - /* Reserve all pages that have been marked by pre-mem_init - * stram_alloc() (e.g. for the screen memory). */ - reserve_region( rsvd_stram_beg, rsvd_stram_end ); - DPRINTK( "atari_stram_reserve_pages: reseverved %08lx-%08lx\n", - rsvd_stram_beg, rsvd_stram_end ); - } - /* else (kernel in ST-RAM): nothing to do, ST-RAM buffers are - * kernel data */ -#ifdef CONFIG_STRAM_SWAP - } - else { - unsigned long swap_data; - BLOCK *p; + { + void *swap_data; - /* determine first page to use as swap: - * if the kernel is in TT-RAM, this is the first page of (usable) - * ST-RAM; else if there were already some allocations (probable...), - * use the lowest address of these (the list is sorted by address!); - * otherwise just use the end of kernel data (= start_mem) */ - swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : - alloc_list ? alloc_list->start : - start_mem; + start_mem = (void *) PAGE_ALIGN ((unsigned long) start_mem); + /* determine first page to use as swap: if the kernel is + in TT-RAM, this is the first page of (usable) ST-RAM; + otherwise just use the end of kernel data (= start_mem) */ + swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem; /* decrement by one page, rest of kernel assumes that first swap page * is always reserved and maybe doesn't handle SWP_ENTRY == 0 * correctly */ @@ -343,7 +322,7 @@ if (swap_end-swap_start > max_swap_size) swap_end = swap_start + max_swap_size; DPRINTK( "atari_stram_reserve_pages: swapping enabled; " - "swap=%08lx-%08lx\n", swap_start, swap_end ); + "swap=%p-%p\n", swap_start, swap_end); /* reserve some amount of memory for maintainance of * swapping itself: one page for each 2048 (PAGE_SIZE/2) @@ -352,24 +331,18 @@ start_mem += ((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1) >> (PAGE_SHIFT-1)) << PAGE_SHIFT; /* correct swap_start if necessary */ - if (swap_start == swap_data) - swap_start = start_mem; + if (swap_start + PAGE_SIZE == swap_data) + swap_start = start_mem - PAGE_SIZE; if (!swap_init( start_mem, swap_data )) { printk( KERN_ERR "ST-RAM swap space initialization failed\n" ); max_swap_size = 0; - goto fallback; + return; } /* reserve region for swapping meta-data */ - reserve_region( swap_data, start_mem ); + reserve_region(swap_data, start_mem); /* reserve swapping area itself */ - reserve_region( swap_start+PAGE_SIZE, swap_end ); - - /* Formerly static areas have been included in the swap area. */ - for( p = alloc_list; p; p = p->next ) { - if (p->flags & BLOCK_STATIC) - p->flags = (p->flags & ~BLOCK_STATIC) | BLOCK_INSWAP; - } + reserve_region(swap_start + PAGE_SIZE, swap_end); /* * If the whole ST-RAM is used for swapping, there are no allocatable @@ -387,15 +360,12 @@ * You just will get non-DMA-able memory... */ mach_max_dma_address = 0xffffffff; - - /* - * Ok, num_physpages needs not be really exact, but it's better to - * subtract the pages set aside for swapping. - */ - num_physpages -= SWAP_NR(swap_end)-1; } #endif - +} + +void atari_stram_mem_init_hook (void) +{ mem_init_done = 1; } @@ -420,68 +390,33 @@ * likely to fail :-( * */ -void *atari_stram_alloc( long size, unsigned long *start_mem, - const char *owner ) +void *atari_stram_alloc(long size, const char *owner) { void *addr = NULL; BLOCK *block; int flags; - DPRINTK( "atari_stram_alloc(size=%08lx,*start_mem=%08lx,owner=%s)\n", - size, start_mem ? *start_mem : 0xffffffff, owner ); - - if (start_mem && mem_init_done) { - printk( KERN_ERR "atari_stram_alloc called with start_mem!=NULL " - "after mem_init() from %p\n", __builtin_return_address(0) ); - return( NULL ); - } - if (!start_mem && !mem_init_done) { - printk( KERN_ERR "atari_stram_alloc called with start_mem==NULL " - "before mem_init() from %p\n", __builtin_return_address(0) ); - return( NULL ); - } + DPRINTK("atari_stram_alloc(size=%08lx,owner=%s)\n", size, owner); size = ALIGN_IF_SWAP(size); DPRINTK( "atari_stram_alloc: rounded size = %08lx\n", size ); - if (!mem_init_done) { - /* before mem_init(): allocate "statically", i.e. either in the kernel - * data space (current end in *start_mem), or at the end of currently - * reserved ST-RAM. */ - if (kernel_in_stram) { - /* Get memory from kernel data space */ - *start_mem = ALIGN_IF_SWAP(*start_mem); - addr = (void *)*start_mem; - *start_mem += size; - DPRINTK( "atari_stram_alloc: pre-mem_init and k/ST: " - "shifted start_mem to %08lx, addr=%p\n", - *start_mem, addr ); - } - else { - /* Get memory from rsvd_stram_beg */ - if (rsvd_stram_end + size < stram_end) { - addr = (void *) rsvd_stram_end; - rsvd_stram_end += size; - DPRINTK( "atari_stram_alloc: pre-mem_init and k/TT: " - "shifted rsvd_stram_end to %08lx, addr=%p\n", - rsvd_stram_end, addr ); - } - } - flags = BLOCK_STATIC; - } #ifdef CONFIG_STRAM_SWAP - else if (max_swap_size) { - /* If swapping is active (can only be the case after mem_init()!): - * make some free space in the swap "device". */ + if (max_swap_size) { + /* If swapping is active: make some free space in the swap + "device". */ DPRINTK( "atari_stram_alloc: after mem_init, swapping ok, " "calling get_region\n" ); addr = get_stram_region( N_PAGES(size) ); flags = BLOCK_INSWAP; } + else #endif + if (!mem_init_done) + return alloc_bootmem_low(size); else { /* After mem_init() and no swapping: can only resort to * __get_dma_pages() */ - addr = (void *)__get_dma_pages(GFP_KERNEL, get_gfp_order(size)); + addr = (void *)__get_dma_pages(GFP_KERNEL, get_order(size)); flags = BLOCK_GFP; DPRINTK( "atari_stram_alloc: after mem_init, swapping off, " "get_pages=%p\n", addr ); @@ -492,14 +427,12 @@ /* out of memory for BLOCK structure :-( */ DPRINTK( "atari_stram_alloc: out of mem for BLOCK -- " "freeing again\n" ); - if (flags == BLOCK_STATIC) - rsvd_stram_end -= size; #ifdef CONFIG_STRAM_SWAP - else if (flags == BLOCK_INSWAP) + if (flags == BLOCK_INSWAP) free_stram_region( SWAP_NR(addr), N_PAGES(size) ); -#endif else - free_pages( (unsigned long)addr, get_gfp_order(size)); +#endif + free_pages((unsigned long)addr, get_order(size)); return( NULL ); } block->owner = owner; @@ -527,15 +460,15 @@ if (!max_swap_size) { #endif if (block->flags & BLOCK_GFP) { - DPRINTK( "atari_stram_free: is kmalloced, order_size=%d\n", - get_gfp_order(block->size) ); - free_pages( (unsigned long)addr, get_gfp_order(block->size) ); + DPRINTK("atari_stram_free: is kmalloced, order_size=%d\n", + get_order(block->size)); + free_pages((unsigned long)addr, get_order(block->size)); } else goto fail; #ifdef CONFIG_STRAM_SWAP } - else if (block->flags & (BLOCK_INSWAP|BLOCK_STATIC)) { + else if (block->flags & BLOCK_INSWAP) { DPRINTK( "atari_stram_free: is swap-alloced\n" ); free_stram_region( SWAP_NR(block->start), N_PAGES(block->size) ); } @@ -563,17 +496,18 @@ * Initialize ST-RAM swap device * (lots copied and modified from sys_swapon() in mm/swapfile.c) */ -static int __init swap_init(unsigned long start_mem, unsigned long swap_data) +static int __init swap_init(void *start_mem, void *swap_data) { - static struct dentry fake_dentry[3]; + static struct dentry fake_dentry; + static struct vfsmount fake_vfsmnt; struct swap_info_struct *p; struct inode swap_inode; unsigned int type; - unsigned long addr; + void *addr; int i, j, k, prev; - DPRINTK( "swap_init(start_mem=%08lx, swap_data=%08lx)\n", - start_mem, swap_data ); + DPRINTK("swap_init(start_mem=%p, swap_data=%p)\n", + start_mem, swap_data); /* need at least one page for swapping to (and this also isn't very * much... :-) */ @@ -598,18 +532,16 @@ stram_swap_type = type; /* fake some dir cache entries to give us some name in /dev/swaps */ - fake_dentry[0].d_covers = &fake_dentry[1]; - fake_dentry[0].d_parent = &fake_dentry[0]; - fake_dentry[1].d_parent = &fake_dentry[2]; - fake_dentry[1].d_name.name = "stram (internal)"; - fake_dentry[1].d_name.len = 16; - fake_dentry[2].d_covers = &fake_dentry[2]; - fake_dentry[2].d_parent = &fake_dentry[2]; + fake_dentry.d_parent = &fake_dentry; + fake_dentry.d_name.name = "stram (internal)"; + fake_dentry.d_name.len = 16; + fake_vfsmnt.mnt_parent = &fake_vfsmnt; p->flags = SWP_USED; - p->swap_file = &fake_dentry[0]; + p->swap_file = &fake_dentry; + p->swap_vfsmnt = &fake_vfsmnt; p->swap_device = 0; - p->swap_map = (unsigned short *)swap_data; + p->swap_map = swap_data; p->cluster_nr = 0; p->next = -1; p->prio = 0x7ff0; /* a rather high priority, but not the higest @@ -628,7 +560,7 @@ k = 0; /* # of already allocated pages (from pre-mem_init stram_alloc()) */ p->lowest_bit = 0; p->highest_bit = 0; - for( i = 1, addr = (unsigned long)SWAP_ADDR(1); i < p->max; + for( i = 1, addr = SWAP_ADDR(1); i < p->max; i++, addr += PAGE_SIZE ) { if (in_some_region( addr )) { p->swap_map[i] = SWAP_MAP_BAD; @@ -685,8 +617,8 @@ * what to do if a write is requested later. */ static inline void unswap_pte(struct vm_area_struct * vma, unsigned long - address, pte_t *dir, unsigned long entry, - unsigned long page /*, int isswap */) + address, pte_t *dir, swp_entry_t entry, + struct page *page) { pte_t pte = *dir; @@ -698,34 +630,25 @@ memory */ if (pte_page(pte) != page) return; - if (0 /* isswap */) - virt_to_page(pte_page(pte))->offset = page; - else - /* We will be removing the swap cache in a moment, so... */ - set_pte(dir, pte_mkdirty(pte)); + /* We will be removing the swap cache in a moment, so... */ + set_pte(dir, pte_mkdirty(pte)); return; } - if (pte_val(pte) != entry) + if (pte_val(pte) != entry.val) return; - if (0 /* isswap */) { - DPRINTK( "unswap_pte: replacing entry %08lx by %08lx", entry, page ); - set_pte(dir, __pte(page)); - } - else { - DPRINTK( "unswap_pte: replacing entry %08lx by new page %08lx", - entry, page ); - set_pte(dir, pte_mkdirty(__mk_pte(page,vma->vm_page_prot))); - atomic_inc(&virt_to_page(page)->count); - ++vma->vm_mm->rss; - } + DPRINTK("unswap_pte: replacing entry %08lx by new page %p", + entry.val, page); + set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot))); swap_free(entry); + get_page(page); + ++vma->vm_mm->rss; } static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long size, - unsigned long offset, unsigned long entry, - unsigned long page /* , int isswap */) + unsigned long offset, swp_entry_t entry, + struct page *page) { pte_t * pte; unsigned long end; @@ -733,7 +656,7 @@ if (pmd_none(*dir)) return; if (pmd_bad(*dir)) { - printk("unswap_pmd: bad pmd (%08lx)\n", pmd_val(*dir)); + pmd_ERROR(*dir); pmd_clear(dir); return; } @@ -744,8 +667,7 @@ if (end > PMD_SIZE) end = PMD_SIZE; do { - unswap_pte(vma, offset+address-vma->vm_start, pte, entry, - page /* , isswap */); + unswap_pte(vma, offset+address-vma->vm_start, pte, entry, page); address += PAGE_SIZE; pte++; } while (address < end); @@ -753,8 +675,7 @@ static inline void unswap_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long size, - unsigned long entry, unsigned long page - /* , int isswap */) + swp_entry_t entry, struct page *page) { pmd_t * pmd; unsigned long offset, end; @@ -762,7 +683,7 @@ if (pgd_none(*dir)) return; if (pgd_bad(*dir)) { - printk("unswap_pgd: bad pgd (%08lx)\n", pgd_val(*dir)); + pgd_ERROR(*dir); pgd_clear(dir); return; } @@ -774,28 +695,26 @@ end = PGDIR_SIZE; do { unswap_pmd(vma, pmd, address, end - address, offset, entry, - page /* , isswap */); + page); address = (address + PMD_SIZE) & PMD_MASK; pmd++; } while (address < end); } static void unswap_vma(struct vm_area_struct * vma, pgd_t *pgdir, - unsigned long entry, unsigned long page - /* , int isswap */) + swp_entry_t entry, struct page *page) { unsigned long start = vma->vm_start, end = vma->vm_end; - while (start < end) { - unswap_pgd(vma, pgdir, start, end - start, entry, page - /* , isswap */); + do { + unswap_pgd(vma, pgdir, start, end - start, entry, page); start = (start + PGDIR_SIZE) & PGDIR_MASK; pgdir++; - } + } while (start < end); } -static void unswap_process(struct mm_struct * mm, unsigned long entry, - unsigned long page /* , int isswap */) +static void unswap_process(struct mm_struct * mm, swp_entry_t entry, + struct page *page) { struct vm_area_struct* vma; @@ -806,110 +725,18 @@ return; for (vma = mm->mmap; vma; vma = vma->vm_next) { pgd_t * pgd = pgd_offset(mm, vma->vm_start); - unswap_vma(vma, pgd, entry, page /* , isswap */); + unswap_vma(vma, pgd, entry, page); } } -#if 0 -static int unswap_by_move(unsigned short *map, unsigned long max, - unsigned long start, unsigned long n_pages) -{ - struct task_struct *p; - unsigned long entry, rover = (start == 1) ? n_pages+1 : 1; - unsigned long i, j; - - DPRINTK( "unswapping %lu..%lu by moving in swap\n", - start, start+n_pages-1 ); - - /* can free the allocated pages by moving them to other swap pages */ - for( i = start; i < start+n_pages; ++i ) { - if (!map[i]) { - map[i] = SWAP_MAP_BAD; - DPRINTK( "unswap: page %lu was free\n", i ); - continue; - } - else if (map[i] == SWAP_MAP_BAD) { - printk( KERN_ERR "get_stram_region: page %lu already " - "reserved??\n", i ); - } - DPRINTK( "unswap: page %lu is alloced, count=%u\n", i, map[i] ); - - /* find a free page not in our region */ - for( j = rover; j != rover-1; j = (j == max-1) ? 1 : j+1 ) { - if (j >= start && j < start+n_pages) - continue; - if (!map[j]) { - rover = j+1; - break; - } - } - if (j == rover-1) { - printk( KERN_ERR "get_stram_region: not enough free swap " - "pages now??\n" ); - return( -ENOMEM ); - } - DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n", - i, map[i], j, map[j], nr_swap_pages ); - - --nr_swap_pages; - entry = SWP_ENTRY( stram_swap_type, j ); - if (stram_swap_info->lowest_bit == j) - stram_swap_info->lowest_bit++; - if (stram_swap_info->highest_bit == j) - stram_swap_info->highest_bit--; - - memcpy( SWAP_ADDR(j), SWAP_ADDR(i), PAGE_SIZE ); -#ifdef DO_PROC - stat_swap_move++; -#endif - - while( map[i] ) { - read_lock(&tasklist_lock); - for_each_task(p) { - if (unswap_process( p->mm, SWP_ENTRY( stram_swap_type, i ), - entry, 1 )) { - read_unlock(&tasklist_lock); - map[j]++; - goto repeat; - } - } - read_unlock(&tasklist_lock); - if (map[i] && map[i] != SWAP_MAP_MAX) { - printk( KERN_ERR "get_stram_region: ST-RAM swap page %lu " - "not used by any process\n", i ); - /* quit while loop and overwrite bad map entry */ - break; - } - else if (!map[i]) { - /* somebody else must have swapped in that page, so free the - * new one (we're moving to) */ - DPRINTK( "unswap: map[i] became 0, also clearing map[j]\n" ); - map[j] = 0; - } - repeat: - } - - DPRINTK( "unswap: map[i=%lu]=%u map[j=%lu]=%u nr_swap=%u\n", - i, map[i], j, map[j], nr_swap_pages ); - map[i] = SWAP_MAP_BAD; - if (stram_swap_info->lowest_bit == i) - stram_swap_info->lowest_bit++; - if (stram_swap_info->highest_bit == i) - stram_swap_info->highest_bit--; - --nr_swap_pages; - } - return( 0 ); -} -#endif - static int unswap_by_read(unsigned short *map, unsigned long max, unsigned long start, unsigned long n_pages) { struct task_struct *p; - unsigned long entry, page; + struct page *page; + swp_entry_t entry; unsigned long i; - struct page *page_map; DPRINTK( "unswapping %lu..%lu by reading in\n", start, start+n_pages-1 ); @@ -932,28 +759,24 @@ /* Get a page for the entry, using the existing swap cache page if there is one. Otherwise, get a clean page and read the swap into it. */ - page_map = read_swap_cache(entry); - if (page_map) { - page = (unsigned long) page_address(page_map); - read_lock(&tasklist_lock); - for_each_task(p) - unswap_process(p->mm, entry, page - /* , 0 */); - read_unlock(&tasklist_lock); - shm_unuse(entry, page); - /* Now get rid of the extra reference to - the temporary page we've been using. */ - if (PageSwapCache(page_map)) - delete_from_swap_cache(page_map); - __free_page(page_map); - #ifdef DO_PROC - stat_swap_force++; - #endif - } - else { + page = read_swap_cache(entry); + if (!page) { swap_free(entry); return -ENOMEM; } + read_lock(&tasklist_lock); + for_each_task(p) + unswap_process(p->mm, entry, page); + read_unlock(&tasklist_lock); + shm_unuse(entry, page); + /* Now get rid of the extra reference to the + temporary page we've been using. */ + if (PageSwapCache(page)) + delete_from_swap_cache(page); + __free_page(page); + #ifdef DO_PROC + stat_swap_force++; + #endif } DPRINTK( "unswap: map[i=%lu]=%u nr_swap=%u\n", @@ -998,14 +821,7 @@ DPRINTK( "get_stram_region: region starts at %lu, has %lu free pages\n", start, region_free ); -#if 0 - err = ((total_free-region_free >= n_pages-region_free) ? - unswap_by_move( map, max, start, n_pages ) : - unswap_by_read( map, max, start, n_pages )); -#else err = unswap_by_read(map, max, start, n_pages); -#endif - if (err) goto end; @@ -1062,7 +878,7 @@ /* is addr in some of the allocated regions? */ -static int in_some_region( unsigned long addr ) +static int in_some_region(void *addr) { BLOCK *p; @@ -1164,17 +980,13 @@ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static int refcnt = 0; -static void do_stram_request( void ) +static void do_stram_request(request_queue_t *q) { - unsigned long start, len; + void *start; + unsigned long len; - while( !QUEUE_EMPTY ) { - if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) - panic("stram: request list destroyed"); - if (CURRENT->bh) { - if (!buffer_locked(CURRENT->bh)) - panic("stram: block not locked"); - } + while (1) { + INIT_REQUEST; start = swap_start + (CURRENT->sector << 9); len = CURRENT->current_nr_sectors << 9; @@ -1188,13 +1000,13 @@ } if (CURRENT->cmd == READ) { - memcpy( CURRENT->buffer, (char *)start, len ); + memcpy(CURRENT->buffer, start, len); #ifdef DO_PROC stat_swap_read += N_PAGES(len); #endif } else { - memcpy( (char *)start, CURRENT->buffer, len ); + memcpy(start, CURRENT->buffer, len); #ifdef DO_PROC stat_swap_write += N_PAGES(len); #endif @@ -1251,19 +1063,15 @@ return( -ENXIO ); } - blk_dev[STRAM_MAJOR].request_fn = do_stram_request; + blk_init_queue(BLK_DEFAULT_QUEUE(STRAM_MAJOR), do_stram_request); blksize_size[STRAM_MAJOR] = stram_blocksizes; stram_sizes[STRAM_MINOR] = (swap_end - swap_start)/1024; blk_size[STRAM_MAJOR] = stram_sizes; register_disk(NULL, MKDEV(STRAM_MAJOR, STRAM_MINOR), 1, &stram_fops, (swap_end-swap_start)>>9); - do_z2_request(); /* to avoid warning */ return( 0 ); } -/* to avoid warning */ -static void do_z2_request( void ) { } - #endif /* CONFIG_STRAM_SWAP */ @@ -1271,30 +1079,10 @@ /* Misc Utility Functions */ /* ------------------------------------------------------------------------ */ - -/* return log2 of #pages for size */ -static int get_gfp_order( unsigned long size ) +/* reserve a range of pages */ +static void reserve_region(void *start, void *end) { - int order; - - size = N_PAGES( size + PAGE_SIZE -1 ); - order = -1; - do { - size >>= 1; - order++; - } while (size); - - return( order ); -} - - -/* reserve a range of pages in mem_map[] */ -static void reserve_region( unsigned long addr, unsigned long end ) -{ - mem_map_t *mapp = virt_to_page(addr); - - for( ; addr < end; addr += PAGE_SIZE, ++mapp ) - set_bit( PG_reserved, &mapp->flags ); + reserve_bootmem (virt_to_phys(start), end - start); } @@ -1328,11 +1116,11 @@ printk( KERN_ERR "Out of memory for ST-RAM descriptor blocks\n" ); return( NULL ); } - n->start = (unsigned long)addr; + n->start = addr; n->size = size; for( p = &alloc_list; *p; p = &((*p)->next) ) - if ((*p)->start > (unsigned long)addr) break; + if ((*p)->start > addr) break; n->next = *p; *p = n; @@ -1346,9 +1134,9 @@ BLOCK *p; for( p = alloc_list; p; p = p->next ) { - if (p->start == (unsigned long)addr) + if (p->start == addr) return( p ); - if (p->start > (unsigned long)addr) + if (p->start > addr) break; } return( NULL ); @@ -1405,14 +1193,13 @@ ++used; } PRINT_PROC( - "Total ST-RAM: %8lu kB\n" + "Total ST-RAM: %8u kB\n" "Total ST-RAM swap: %8lu kB\n" "Free swap: %8u kB\n" "Used swap: %8u kB\n" "Allocated swap: %8u kB\n" "Swap Reads: %8u\n" "Swap Writes: %8u\n" - "Swap Moves: %8u\n" "Swap Forced Reads: %8u\n", (stram_end - stram_start) >> 10, (max-1) << (PAGE_SHIFT-10), @@ -1421,17 +1208,13 @@ rsvd << (PAGE_SHIFT-10), stat_swap_read, stat_swap_write, - stat_swap_move, stat_swap_force ); } else { #endif PRINT_PROC( "ST-RAM swapping disabled\n" ); - PRINT_PROC( - "Total ST-RAM: %8lu kB\n" - "Reserved ST-RAM: %8lu kB\n", - (stram_end - stram_start) >> 10, - (rsvd_stram_end - rsvd_stram_beg) >> 10 ); + PRINT_PROC("Total ST-RAM: %8u kB\n", + (stram_end - stram_start) >> 10); #ifdef CONFIG_STRAM_SWAP } #endif @@ -1441,12 +1224,10 @@ if (len + 50 >= PAGE_SIZE) break; PRINT_PROC("0x%08lx-0x%08lx: %s (", - virt_to_phys((void *)p->start), - virt_to_phys((void *)p->start+p->size-1), + virt_to_phys(p->start), + virt_to_phys(p->start+p->size-1), p->owner); - if (p->flags & BLOCK_STATIC) - PRINT_PROC( "static)\n" ); - else if (p->flags & BLOCK_GFP) + if (p->flags & BLOCK_GFP) PRINT_PROC( "page-alloced)\n" ); else if (p->flags & BLOCK_INSWAP) PRINT_PROC( "in swap)\n" ); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/fpsp040/bindec.S linux/arch/m68k/fpsp040/bindec.S --- v2.4.0-test11/linux/arch/m68k/fpsp040/bindec.S Fri Apr 26 02:12:35 1996 +++ linux/arch/m68k/fpsp040/bindec.S Mon Nov 27 17:11:26 2000 @@ -484,7 +484,7 @@ fmovex (%a0),%fp0 |load X from memory fabsx %fp0 |use abs(X) tstw %d5 |LAMBDA is in lower word of d5 - bnes sc_mul |if neg (LAMBDA = 1), scale by mul + bne sc_mul |if neg (LAMBDA = 1), scale by mul fdivx %fp1,%fp0 |calculate X / SCALE -> Y to fp0 bras A10_st |branch to A10 diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/fpsp040/decbin.S linux/arch/m68k/fpsp040/decbin.S --- v2.4.0-test11/linux/arch/m68k/fpsp040/decbin.S Fri Apr 26 02:12:35 1996 +++ linux/arch/m68k/fpsp040/decbin.S Mon Nov 27 17:11:26 2000 @@ -230,7 +230,7 @@ | m_sign: btst #31,(%a0) |test sign of the mantissa - beqs ap_st_z |if clear, go to append/strip zeros + beq ap_st_z |if clear, go to append/strip zeros fnegx %fp0 |if set, negate fp0 | @@ -288,7 +288,7 @@ cmpl #27,%d1 |test is with 27 ble pwrten |if abs(expA) <28, skip ap/st zeros btst #30,(%a0) |check sign of exp - bnes ap_st_n |if neg, go to neg side + bne ap_st_n |if neg, go to neg side clrl %d1 |zero count reg movel (%a0),%d4 |load lword 1 to d4 bfextu %d4{#28:#4},%d0 |get M16 in d0 @@ -336,7 +336,7 @@ tstl %d0 |check if d0 is zero bnes ap_p_el |if not, get next bit fmulx %fp1,%fp0 |mul mantissa by 10**(no_bits_shifted) - bras pwrten |go calc pwrten + bra pwrten |go calc pwrten | | This section handles a negative adjusted exponent. | diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/fpsp040/do_func.S linux/arch/m68k/fpsp040/do_func.S --- v2.4.0-test11/linux/arch/m68k/fpsp040/do_func.S Tue Apr 23 21:31:24 1996 +++ linux/arch/m68k/fpsp040/do_func.S Mon Nov 27 17:11:26 2000 @@ -77,7 +77,7 @@ movew CMDREG1B(%a6),%d0 andl #0x7F,%d0 cmpil #0x38,%d0 |if the extension is >= $38, - bges serror |it is illegal + bge serror |it is illegal bfextu STAG(%a6){#0:#3},%d1 lsll #3,%d0 |make room for STAG addl %d1,%d0 |combine for final index into table diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/fpsp040/get_op.S linux/arch/m68k/fpsp040/get_op.S --- v2.4.0-test11/linux/arch/m68k/fpsp040/get_op.S Fri Apr 26 02:12:35 1996 +++ linux/arch/m68k/fpsp040/get_op.S Mon Nov 27 17:11:26 2000 @@ -171,7 +171,7 @@ get_op: clrb DY_MO_FLG(%a6) tstb UFLG_TMP(%a6) |test flag for unsupp/unimp state - beqs uni_getop + beq uni_getop uns_getop: btstb #direction_bit,CMDREG1B(%a6) diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/fpsp040/util.S linux/arch/m68k/fpsp040/util.S --- v2.4.0-test11/linux/arch/m68k/fpsp040/util.S Fri Apr 26 02:12:35 1996 +++ linux/arch/m68k/fpsp040/util.S Mon Nov 27 17:11:26 2000 @@ -138,20 +138,20 @@ | ovf_fsgl: clrl %d0 - bras ovf_res + bra ovf_res ovff_sgl: movel #0x00000001,%d0 |set single - bras ovf_res + bra ovf_res ovff_dbl: movel #0x00000002,%d0 |set double - bras ovf_res + bra ovf_res | | The precision is in the fpcr. | ovf_fpcr: bfextu FPCR_MODE(%a6){#0:#2},%d0 |set round precision - bras ovf_res + bra ovf_res | | diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/fpsp040/x_store.S linux/arch/m68k/fpsp040/x_store.S --- v2.4.0-test11/linux/arch/m68k/fpsp040/x_store.S Fri Apr 26 02:12:35 1996 +++ linux/arch/m68k/fpsp040/x_store.S Mon Nov 27 17:11:26 2000 @@ -92,7 +92,7 @@ cmpil #0,%d0 |if dest format is extended beq dest_ext |then branch cmpil #1,%d0 |if dest format is single - beqs dest_sgl |then branch + beq dest_sgl |then branch | | fall through to dest_dbl | diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/ifpsp060/os.S linux/arch/m68k/ifpsp060/os.S --- v2.4.0-test11/linux/arch/m68k/ifpsp060/os.S Thu Feb 12 16:30:12 1998 +++ linux/arch/m68k/ifpsp060/os.S Mon Nov 27 17:11:26 2000 @@ -85,21 +85,20 @@ | .global _060_dmem_write _060_dmem_write: + subq.l #1,%d0 btst #0x5,0x4(%a6) | check for supervisor state beqs user_write super_write: move.b (%a0)+,(%a1)+ | copy 1 byte - subq.l #0x1,%d0 | decr byte counter - bnes super_write | quit if ctr = 0 + dbra %d0,super_write | quit if --ctr < 0 clr.l %d1 | return success rts user_write: - move.l %d0,-(%sp) | pass: counter - move.l %a1,-(%sp) | pass: user dst - move.l %a0,-(%sp) | pass: supervisor src - bsr.l _copyout | write byte to user mem - move.l %d0,%d1 | return success - add.l #0xc, %sp | clear 3 lw params + move.b (%a0)+,%d1 | copy 1 byte +copyoutae: + movs.b %d1,(%a1)+ + dbra %d0,user_write | quit if --ctr < 0 + clr.l %d1 | return success rts | @@ -119,21 +118,20 @@ .global _060_dmem_read _060_imem_read: _060_dmem_read: + subq.l #1,%d0 btst #0x5,0x4(%a6) | check for supervisor state beqs user_read super_read: move.b (%a0)+,(%a1)+ | copy 1 byte - subq.l #0x1,%d0 | decr byte counter - bnes super_read | quit if ctr = 0 + dbra %d0,super_read | quit if --ctr < 0 clr.l %d1 | return success rts user_read: - move.l %d0,-(%sp) | pass: counter - move.l %a1,-(%sp) | pass: super dst - move.l %a0,-(%sp) | pass: user src - bsr.l _copyin | read byte from user mem - move.l %d0,%d1 | return success - add.l #0xc,%sp | clear 3 lw params +copyinae: + movs.b (%a0)+,%d1 + move.b %d1,(%a1)+ | copy 1 byte + dbra %d0,user_read | quit if --ctr < 0 + clr.l %d1 | return success rts | @@ -150,14 +148,13 @@ | .global _060_dmem_read_byte _060_dmem_read_byte: + clr.l %d0 | clear whole longword + clr.l %d1 | assume success btst #0x5,0x4(%a6) | check for supervisor state bnes dmrbs | supervisor -dmrbu: clr.l %d0 | clear whole longword dmrbuae:movs.b (%a0),%d0 | fetch user byte - bras dmrbr -dmrbs: clr.l %d0 | clear whole longword - move.b (%a0),%d0 | fetch super byte -dmrbr: clr.l %d1 | return success + rts +dmrbs: move.b (%a0),%d0 | fetch super byte rts | @@ -187,14 +184,13 @@ .global _060_imem_read_word _060_dmem_read_word: _060_imem_read_word: + clr.l %d1 | assume success + clr.l %d0 | clear whole longword btst #0x5,0x4(%a6) | check for supervisor state bnes dmrws | supervisor -dmrwu: clr.l %d0 | clear whole longword dmrwuae:movs.w (%a0), %d0 | fetch user word - bras dmrwr -dmrws: clr.l %d0 | clear whole longword - move.w (%a0), %d0 | fetch super word -dmrwr: clr.l %d1 | return success + rts +dmrws: move.w (%a0), %d0 | fetch super word rts | @@ -224,13 +220,12 @@ .global _060_imem_read_long _060_dmem_read_long: _060_imem_read_long: + clr.l %d1 | assume success btst #0x5,0x4(%a6) | check for supervisor state bnes dmrls | supervisor -dmrlu: dmrluae:movs.l (%a0),%d0 | fetch user longword - bras dmrlr + rts dmrls: move.l (%a0),%d0 | fetch super longword -dmrlr: clr.l %d1 | return success rts | @@ -247,13 +242,12 @@ | .global _060_dmem_write_byte _060_dmem_write_byte: + clr.l %d1 | assume success btst #0x5,0x4(%a6) | check for supervisor state bnes dmwbs | supervisor -dmwbu: dmwbuae:movs.b %d0,(%a0) | store user byte - bras dmwbr + rts dmwbs: move.b %d0,(%a0) | store super byte -dmwbr: clr.l %d1 | return success rts | @@ -270,6 +264,7 @@ | .global _060_dmem_write_word _060_dmem_write_word: + clr.l %d1 | assume success btst #0x5,0x4(%a6) | check for supervisor state bnes dmwws | supervisor dmwwu: @@ -293,16 +288,16 @@ | .global _060_dmem_write_long _060_dmem_write_long: + clr.l %d1 | assume success btst #0x5,0x4(%a6) | check for supervisor state bnes dmwls | supervisor -dmwlu: dmwluae:movs.l %d0,(%a0) | store user longword - bra dmwlr + rts dmwls: move.l %d0,(%a0) | store super longword -dmwlr: clr.l %d1 | return success rts +#if 0 |############################################### | @@ -323,7 +318,7 @@ move.l 4(%sp),%a0 | source move.l 8(%sp),%a1 | destination move.l 12(%sp),%d0 | count - subq.l #1,%d0 + subq.l #1,%d0 moreout: move.b (%a0)+,%d1 | fetch supervisor byte copyoutae: @@ -348,6 +343,7 @@ dbra %d0,morein | are we through yet? moveq #0,%d0 | return success rts +#endif |########################################################################### diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S --- v2.4.0-test11/linux/arch/m68k/kernel/entry.S Fri Aug 11 14:29:04 2000 +++ linux/arch/m68k/kernel/entry.S Mon Nov 27 18:02:06 2000 @@ -28,6 +28,9 @@ * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so * all pointers that used to be 'current' are now entry * number 0 in the 'current_set' list. + * + * 6/05/00 RZ: addedd writeback completion after return from sighandler + * for 68040 */ #include @@ -104,8 +107,18 @@ jbsr SYMBOL_NAME(syscall_trace) SYMBOL_NAME_LABEL(ret_from_signal) - RESTORE_SWITCH_STACK + RESTORE_SWITCH_STACK + addql #4,%sp +/* on 68040 complete pending writebacks if any */ +#ifdef CONFIG_M68040 + bfextu %sp@(PT_VECTOR){#0,#4},%d0 + subql #7,%d0 | bus error frame ? + jbne 1f + movel %sp,%sp@- + jbsr SYMBOL_NAME(berr_040cleanup) addql #4,%sp +1: +#endif jra SYMBOL_NAME(ret_from_exception) ENTRY(system_call) @@ -115,7 +128,7 @@ | save top of frame movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) - btst #PF_TRACESYS_BIT,%curptr@(TASK_FLAGS+PF_TRACESYS_OFF) + btst #PT_TRACESYS_BIT,%curptr@(TASK_PTRACE+PT_TRACESYS_OFF) jne do_trace cmpl #NR_syscalls,%d0 jcc badsys @@ -136,7 +149,7 @@ jeq 2f #endif | check for delayed trace - bclr #PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF) + bclr #PT_DTRACE_BIT,%curptr@(TASK_PTRACE+PT_DTRACE_OFF) jne do_delayed_trace 5: tstl %curptr@(TASK_STATE) | state @@ -578,7 +591,7 @@ .long SYMBOL_NAME(sys_mremap) .long SYMBOL_NAME(sys_setresuid16) .long SYMBOL_NAME(sys_getresuid16) /* 165 */ - .long SYMBOL_NAME(sys_ni_syscall) /* for vm86 */ + .long SYMBOL_NAME(sys_getpagesize) .long SYMBOL_NAME(sys_query_module) .long SYMBOL_NAME(sys_poll) .long SYMBOL_NAME(sys_nfsservctl) diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/ints.c linux/arch/m68k/kernel/ints.c --- v2.4.0-test11/linux/arch/m68k/kernel/ints.c Fri Aug 4 16:15:37 2000 +++ linux/arch/m68k/kernel/ints.c Mon Nov 27 17:11:26 2000 @@ -71,6 +71,8 @@ unsigned long, const char *, void *) = dummy_request_irq; void (*mach_free_irq) (unsigned int, void *) = dummy_free_irq; +void init_irq_proc(void); + /* * void init_IRQ(void) * @@ -257,3 +259,9 @@ len += mach_get_irq_list(buf+len); return len; } + +void init_irq_proc(void) +{ + /* Insert /proc/irq driver here */ +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/m68k_defs.c linux/arch/m68k/kernel/m68k_defs.c --- v2.4.0-test11/linux/arch/m68k/kernel/m68k_defs.c Mon Aug 9 12:27:30 1999 +++ linux/arch/m68k/kernel/m68k_defs.c Mon Nov 27 18:02:06 2000 @@ -24,6 +24,7 @@ /* offsets into the task struct */ DEFINE(TASK_STATE, offsetof(struct task_struct, state)); DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags)); + DEFINE(TASK_PTRACE, offsetof(struct task_struct, ptrace)); DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending)); DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched)); DEFINE(TASK_THREAD, offsetof(struct task_struct, thread)); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c --- v2.4.0-test11/linux/arch/m68k/kernel/m68k_ksyms.c Fri Aug 4 16:15:37 2000 +++ linux/arch/m68k/kernel/m68k_ksyms.c Mon Nov 27 17:11:26 2000 @@ -21,6 +21,7 @@ asmlinkage long long __ashrdi3 (long long, int); asmlinkage long long __lshrdi3 (long long, int); +asmlinkage long long __muldi3 (long long, long long); extern char m68k_debug_device[]; extern void dump_thread(struct pt_regs *, struct user *); @@ -72,6 +73,7 @@ EXPORT_SYMBOL_NOVERS(memset); EXPORT_SYMBOL_NOVERS(memcmp); EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL_NOVERS(__muldi3); EXPORT_SYMBOL_NOVERS(__down_failed); EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c --- v2.4.0-test11/linux/arch/m68k/kernel/ptrace.c Wed Jan 26 12:44:20 2000 +++ linux/arch/m68k/kernel/ptrace.c Mon Nov 27 18:02:06 2000 @@ -97,10 +97,10 @@ ret = -EPERM; if (request == PTRACE_TRACEME) { /* are we already being traced? */ - if (current->flags & PF_PTRACED) + if (current->ptrace & PT_PTRACED) goto out; /* set the ptrace bit in the process flags. */ - current->flags |= PF_PTRACED; + current->ptrace |= PT_PTRACED; ret = 0; goto out; } @@ -126,9 +126,9 @@ (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) goto out; /* the same process cannot be attached many times */ - if (child->flags & PF_PTRACED) + if (child->ptrace & PT_PTRACED) goto out; - child->flags |= PF_PTRACED; + child->ptrace |= PT_PTRACED; write_lock_irqsave(&tasklist_lock, flags); if (child->p_pptr != current) { @@ -143,7 +143,7 @@ goto out; } ret = -ESRCH; - if (!(child->flags & PF_PTRACED)) + if (!(child->ptrace & PT_PTRACED)) goto out; if (child->state != TASK_STOPPED) { if (request != PTRACE_KILL) @@ -250,9 +250,9 @@ if ((unsigned long) data > _NSIG) goto out; if (request == PTRACE_SYSCALL) - child->flags |= PF_TRACESYS; + child->ptrace |= PT_TRACESYS; else - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; child->exit_code = data; /* make sure the single step bit is not set. */ tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16); @@ -287,7 +287,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->flags &= ~PF_TRACESYS; + child->ptrace &= ~PT_TRACESYS; tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16); put_reg(child, PT_SR, tmp); @@ -304,7 +304,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) goto out; - child->flags &= ~(PF_PTRACED|PF_TRACESYS); + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); child->exit_code = data; write_lock_irqsave(&tasklist_lock, flags); REMOVE_LINKS(child); @@ -384,8 +384,8 @@ asmlinkage void syscall_trace(void) { lock_kernel(); - if ((current->flags & (PF_PTRACED|PF_TRACESYS)) - != (PF_PTRACED|PF_TRACESYS)) + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) + != (PT_PTRACED|PT_TRACESYS)) goto out; current->exit_code = SIGTRAP; current->state = TASK_STOPPED; diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c --- v2.4.0-test11/linux/arch/m68k/kernel/setup.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/kernel/setup.c Mon Nov 27 17:57:34 2000 @@ -73,6 +73,8 @@ int (*mach_keyb_init) (void) __initdata = NULL; int (*mach_kbdrate) (struct kbd_repeat *) = NULL; void (*mach_kbd_leds) (unsigned int) = NULL; +int (*mach_kbd_translate)(unsigned char scancode, unsigned char *keycode, char raw_mode) = NULL; +unsigned int SYSRQ_KEY; /* machine dependent irq functions */ void (*mach_init_IRQ) (void) __initdata = NULL; void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL; diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/signal.c linux/arch/m68k/kernel/signal.c --- v2.4.0-test11/linux/arch/m68k/kernel/signal.c Sun Sep 3 11:50:52 2000 +++ linux/arch/m68k/kernel/signal.c Mon Nov 27 18:02:06 2000 @@ -1043,7 +1043,7 @@ if (!signr) break; - if ((current->flags & PF_PTRACED) && signr != SIGKILL) { + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { current->exit_code = signr; current->state = TASK_STOPPED; regs->sr &= ~PS_T; diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c --- v2.4.0-test11/linux/arch/m68k/kernel/sys_m68k.c Wed Jul 5 11:31:00 2000 +++ linux/arch/m68k/kernel/sys_m68k.c Mon Nov 27 17:11:26 2000 @@ -24,6 +24,7 @@ #include #include #include +#include /* * sys_pipe() is the normal C calling standard for creating @@ -659,6 +660,11 @@ out: unlock_kernel(); return ret; +} + +asmlinkage int sys_getpagesize(void) +{ + return PAGE_SIZE; } /* diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c --- v2.4.0-test11/linux/arch/m68k/kernel/traps.c Mon Jan 31 10:32:53 2000 +++ linux/arch/m68k/kernel/traps.c Mon Nov 27 18:02:06 2000 @@ -5,6 +5,7 @@ * * 68040 fixes by Michael Rausch * 68040 fixes by Martin Apel + * 68040 fixes and writeback by Richard Zidlicky * 68060 fixes by Roman Hodek * 68060 fixes by Jesper Skov * @@ -34,7 +35,7 @@ #include #include #include -#include +#include #include #include @@ -195,6 +196,7 @@ void die_if_kernel(char *,struct pt_regs *,int); asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code); +int send_fault_sig(struct pt_regs *regs); asmlinkage void trap_c(struct frame *fp); @@ -214,26 +216,33 @@ "movec %/d0,%/cacr" : : : "d0" ); /* return if there's no other error */ - if ((!(fslw & MMU060_ERR_BITS)) && !(fslw & MMU060_SEE)) + if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE)) return; } if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) { unsigned long errorcode; unsigned long addr = fp->un.fmt4.effaddr; - errorcode = ((fslw & MMU060_WP) ? 1 : 0) | - ((fslw & MMU060_W) ? 2 : 0); + + if (fslw & MMU060_MA) + addr = (addr + 7) & -8; + + errorcode = 1; + if (fslw & MMU060_DESC_ERR) { + __flush_tlb040_one(addr); + errorcode = 0; + } + if (fslw & MMU060_W) + errorcode |= 2; #ifdef DEBUG printk("errorcode = %d\n", errorcode ); #endif - if (fslw & MMU060_MA) - addr = PAGE_ALIGN(addr); do_page_fault(&fp->ptregs, addr, errorcode); } else if (fslw & (MMU060_SEE)){ - /* Software Emulation Error. Probably an instruction - * using an unsupported addressing mode + /* Software Emulation Error. + * fault during mem_read/mem_write in ifpsp060/os.S */ - send_sig (SIGSEGV, current, 1); + send_fault_sig(&fp->ptregs); } else { printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); printk( "68060 access error, fslw=%lx\n", fslw ); @@ -243,74 +252,113 @@ #endif /* CONFIG_M68060 */ #if defined (CONFIG_M68040) -static inline unsigned long probe040 (int iswrite, int fc, unsigned long addr) +static inline unsigned long probe040(int iswrite, unsigned long addr) { unsigned long mmusr; - mm_segment_t fs = get_fs(); - set_fs (MAKE_MM_SEG(fc)); + asm volatile (".chip 68040"); if (iswrite) - /* write */ - asm volatile (".chip 68040\n\t" - "ptestw (%1)\n\t" - "movec %%mmusr,%0\n\t" - ".chip 68k" - : "=r" (mmusr) - : "a" (addr)); + asm volatile ("ptestw (%0)" : : "a" (addr)); else - asm volatile (".chip 68040\n\t" - "ptestr (%1)\n\t" - "movec %%mmusr,%0\n\t" - ".chip 68k" - : "=r" (mmusr) - : "a" (addr)); + asm volatile ("ptestr (%0)" : : "a" (addr)); + + asm volatile ("movec %%mmusr,%0" : "=r" (mmusr)); - set_fs (fs); + asm volatile (".chip 68k"); return mmusr; } -static inline void do_040writeback (unsigned short ssw, - unsigned short wbs, - unsigned long wba, - unsigned long wbd, - struct frame *fp) +static inline int do_040writeback1(unsigned short wbs, unsigned long wba, + unsigned long wbd) { - mm_segment_t fs = get_fs (); - unsigned long mmusr; - unsigned long errorcode; + int res = 0; - /* - * No special handling for the second writeback anymore. - * It misinterpreted the misaligned status sometimes. - * This way an extra page-fault may be caused (Martin Apel). - */ + set_fs(MAKE_MM_SEG(wbs)); - mmusr = probe040 (1, wbs & WBTM_040, wba); - errorcode = (mmusr & MMU_R_040) ? 3 : 2; - if (do_page_fault (&fp->ptregs, wba, errorcode)) - /* just return if we can't perform the writeback */ - return; - - set_fs (MAKE_MM_SEG(wbs & WBTM_040)); switch (wbs & WBSIZ_040) { - case BA_SIZE_BYTE: - put_user (wbd & 0xff, (char *)wba); + case BA_SIZE_BYTE: + res = put_user(wbd & 0xff, (char *)wba); break; - case BA_SIZE_WORD: - put_user (wbd & 0xffff, (short *)wba); + case BA_SIZE_WORD: + res = put_user(wbd & 0xffff, (short *)wba); break; - case BA_SIZE_LONG: - put_user (wbd, (int *)wba); + case BA_SIZE_LONG: + res = put_user(wbd, (int *)wba); break; } - set_fs (fs); + +#ifdef DEBUG + printk("do_040writeback1, res=%d\n",res); +#endif + + return res; } -static inline void access_error040 (struct frame *fp) +/* after an exception in a writeback the stack frame coresponding + * to that exception is discarded, set a few bits in the old frame + * to simulate what it should look like + */ +static inline void fix_xframe040(struct frame *fp, unsigned short wbs) +{ + fp->un.fmt7.faddr = current->thread.faddr; + fp->un.fmt7.ssw = wbs & 0xff; +} + +static inline void do_040writebacks(struct frame *fp) +{ + int res = 0; +#if 0 + if (fp->un.fmt7.wb1s & WBV_040) + printk("access_error040: cannot handle 1st writeback. oops.\n"); +#endif + + if ((fp->un.fmt7.wb2s & WBV_040) && + !(fp->un.fmt7.wb2s & WBTT_040)) { + res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, + fp->un.fmt7.wb2d); + if (res) + fix_xframe040(fp, fp->un.fmt7.wb2s); + else + fp->un.fmt7.wb2s = 0; + } + + /* do the 2nd wb only if the first one was succesful (except for a kernel wb) */ + if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) { + res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, + fp->un.fmt7.wb3d); + if (res) + fix_xframe040(fp, fp->un.fmt7.wb3s); + else + fp->un.fmt7.wb3s = 0; + } + + if (res) + send_fault_sig(&fp->ptregs); +} + +/* + * called from sigreturn(), must ensure userspace code didn't + * manipulate exception frame to circumvent protection, then complete + * pending writebacks + * we just clear TM2 to turn it into an userspace access + */ +asmlinkage void berr_040cleanup(struct frame *fp) +{ + mm_segment_t old_fs = get_fs(); + + fp->un.fmt7.wb2s &= ~4; + fp->un.fmt7.wb3s &= ~4; + + do_040writebacks(fp); + set_fs(old_fs); +} + +static inline void access_error040(struct frame *fp) { unsigned short ssw = fp->un.fmt7.ssw; + mm_segment_t old_fs = get_fs(); unsigned long mmusr; #ifdef DEBUG @@ -322,7 +370,6 @@ fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); #endif - if (ssw & ATC_040) { unsigned long addr = fp->un.fmt7.faddr; unsigned long errorcode; @@ -332,56 +379,50 @@ * has been corrected if there was a misaligned access (MA). */ if (ssw & MA_040) - addr = PAGE_ALIGN (addr); + addr = (addr + 7) & -8; + set_fs(MAKE_MM_SEG(ssw)); /* MMU error, get the MMUSR info for this access */ - mmusr = probe040 (!(ssw & RW_040), ssw & TM_040, addr); + mmusr = probe040(!(ssw & RW_040), addr); #ifdef DEBUG printk("mmusr = %lx\n", mmusr); #endif - errorcode = ((mmusr & MMU_R_040) ? 1 : 0) | - ((ssw & RW_040) ? 0 : 2); -#ifdef CONFIG_FTRACE - { - unsigned long flags; - - save_flags(flags); - cli(); - do_ftrace(0xfa000000 | errorcode); - do_ftrace(mmusr); - restore_flags(flags); + errorcode = 1; + if (!(mmusr & MMU_R_040)) { + /* clear the invalid atc entry */ + __flush_tlb040_one(addr); + errorcode = 0; } + if (!(ssw & RW_040)) + errorcode |= 2; + if (do_page_fault(&fp->ptregs, addr, errorcode)) { +#ifdef DEBUG + printk("do_page_fault() !=0 \n"); #endif - do_page_fault (&fp->ptregs, addr, errorcode); + if (user_mode(&fp->ptregs)){ + /* delay writebacks after signal delivery */ +#ifdef DEBUG + printk(".. was usermode - return\n"); +#endif + return; + } + /* disable writeback into user space from kernel + * (if do_page_fault didn't fix the mapping, + * the writeback won't do good) + */ +#ifdef DEBUG + printk(".. disabling wb2\n"); +#endif + if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) + fp->un.fmt7.wb2s &= ~WBV_040; + } } else { - printk ("68040 access error, ssw=%x\n", ssw); - trap_c (fp); + printk("68040 access error, ssw=%x\n", ssw); + trap_c(fp); } -#if 0 - if (fp->un.fmt7.wb1s & WBV_040) - printk("access_error040: cannot handle 1st writeback. oops.\n"); -#endif - -/* - * We may have to do a couple of writebacks here. - * - * MR: we can speed up the thing a little bit and let do_040writeback() - * not produce another page fault as wb2 corresponds to the address that - * caused the fault. on write faults no second fault is generated, but - * on read faults for security reasons (although per definitionem impossible) - */ - - if (fp->un.fmt7.wb2s & WBV_040 && (fp->un.fmt7.wb2s & - WBTT_040) != BA_TT_MOVE16) - do_040writeback (ssw, - fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, - fp->un.fmt7.wb2d, fp); - - if (fp->un.fmt7.wb3s & WBV_040) - do_040writeback (ssw, fp->un.fmt7.wb3s, - fp->un.fmt7.wb3a, fp->un.fmt7.wb3d, - fp); + do_040writebacks(fp); + set_fs(old_fs); } #endif /* CONFIG_M68040 */ @@ -470,12 +511,14 @@ else if (buserr_type & SUN3_BUSERR_INVALID) errorcode = 0x00; else { +#ifdef DEBUG printk ("*** unexpected busfault type=%#04x\n", buserr_type); printk ("invalid %s access at %#lx from pc %#lx\n", !(ssw & RW) ? "write" : "read", addr, fp->ptregs.pc); +#endif die_if_kernel ("Oops", &fp->ptregs, buserr_type); - force_sig (SIGSEGV, current); + force_sig (SIGBUS, current); return; } @@ -596,7 +639,7 @@ printk ("mmusr is %#x for addr %#lx in task %p\n", mmusr, addr, current); printk ("descriptor address is %#lx, contents %#lx\n", - mm_ptov(desc), *(unsigned long *)mm_ptov(desc)); + __va(desc), *(unsigned long *)__va(desc)); #endif errorcode = (mmusr & MMU_I) ? 0 : 1; @@ -694,7 +737,7 @@ printk ("mmusr is %#x for addr %#lx in task %p\n", mmusr, addr, current); printk ("descriptor address is %#lx, contents %#lx\n", - mm_ptov(desc), *(unsigned long *)mm_ptov(desc)); + __va(desc), *(unsigned long *)__va(desc)); #endif if (mmusr & MMU_I) @@ -904,7 +947,7 @@ if (fp->ptregs.sr & PS_S) { if ((fp->ptregs.vector >> 2) == VEC_TRACE) { /* traced a trapping instruction */ - current->flags |= PF_DTRACE; + current->ptrace |= PT_DTRACE; } else bad_super_trap(fp); return; diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/lib/Makefile linux/arch/m68k/lib/Makefile --- v2.4.0-test11/linux/arch/m68k/lib/Makefile Thu Mar 30 16:56:04 2000 +++ linux/arch/m68k/lib/Makefile Mon Nov 27 17:11:26 2000 @@ -6,6 +6,6 @@ $(CC) $(AFLAGS) -traditional -c $< -o $@ L_TARGET = lib.a -L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o +L_OBJS = ashrdi3.o lshrdi3.o checksum.o memcpy.o memcmp.o memset.o semaphore.o muldi3.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/lib/muldi3.c linux/arch/m68k/lib/muldi3.c --- v2.4.0-test11/linux/arch/m68k/lib/muldi3.c Wed Dec 31 16:00:00 1969 +++ linux/arch/m68k/lib/muldi3.c Mon Nov 27 17:11:26 2000 @@ -0,0 +1,63 @@ +/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and + gcc-2.7.2.3/longlong.h which is: */ +/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC 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 GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#define BITS_PER_UNIT 8 + +#define umul_ppmm(w1, w0, u, v) \ + __asm__ ("mulu%.l %3,%1:%0" \ + : "=d" ((USItype)(w0)), \ + "=d" ((USItype)(w1)) \ + : "%0" ((USItype)(u)), \ + "dmi" ((USItype)(v))) + +#define __umulsidi3(u, v) \ + ({DIunion __w; \ + umul_ppmm (__w.s.high, __w.s.low, u, v); \ + __w.ll; }) + +typedef int SItype __attribute__ ((mode (SI))); +typedef unsigned int USItype __attribute__ ((mode (SI))); +typedef int DItype __attribute__ ((mode (DI))); +typedef int word_type __attribute__ ((mode (__word__))); + +struct DIstruct {SItype high, low;}; + +typedef union +{ + struct DIstruct s; + DItype ll; +} DIunion; + +DItype +__muldi3 (DItype u, DItype v) +{ + DIunion w; + DIunion uu, vv; + + uu.ll = u, + vv.ll = v; + + w.ll = __umulsidi3 (uu.s.low, vv.s.low); + w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high + + (USItype) uu.s.high * (USItype) vv.s.low); + + return w.ll; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mac/baboon.c linux/arch/m68k/mac/baboon.c --- v2.4.0-test11/linux/arch/m68k/mac/baboon.c Tue Feb 15 22:39:01 2000 +++ linux/arch/m68k/mac/baboon.c Sun Dec 3 17:48:19 2000 @@ -27,8 +27,6 @@ void baboon_irq(int, void *, struct pt_regs *); -extern int console_loglevel; - extern int macide_ack_intr(ide_hwif_t *); /* diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c --- v2.4.0-test11/linux/arch/m68k/mac/config.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/mac/config.c Sun Dec 3 17:48:19 2000 @@ -61,10 +61,6 @@ /* The phys. video addr. - might be bogus on some machines */ unsigned long mac_orig_videoaddr; -/* Mac specific keyboard functions */ -extern int mackbd_init_hw(void); -extern void mackbd_leds(unsigned int leds); - /* Mac specific timer functions */ extern void mac_gettod (int *, int *, int *, int *, int *, int *); extern unsigned long mac_gettimeoffset (void); @@ -91,20 +87,21 @@ extern void mac_debug_init(void); extern void mac_debugging_long(int, long); -#ifdef CONFIG_MAGIC_SYSRQ -static char mac_sysrq_xlate[128] = - "\000sdfghzxcv\000bqwer" /* 0x00 - 0x0f */ - "yt123465=97-80)o" /* 0x10 - 0x1f */ - "u(ip\rlj'k;\\,/nm." /* 0x20 - 0x2f */ - "\t `\000\033\000\000\000\000\000\000\000\000\000\000\000" /* 0x30 - 0x3f */ - "\000.\000*\000+\000\000\000\000\000/\r\000-\000" /* 0x40 - 0x4f */ - "\000\00001234567a89\000\000\000" /* 0x50 - 0x5f */ - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x60 - 0x6f */ - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */ -#endif - extern void (*kd_mksound)(unsigned int, unsigned int); +extern int mackbd_init_hw(void); +extern void mackbd_leds(unsigned int leds); +extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode); + +extern void mac_hid_init_hw(void); +extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode, char raw_mode); + +#ifdef CONFIG_MAGIC_SYSRQ +extern unsigned char mac_hid_kbd_sysrq_xlate[128]; +extern unsigned char pckbd_sysrq_xlate[128]; +extern unsigned char mackbd_sysrq_xlate[128]; +#endif /* CONFIG_MAGIC_SYSRQ */ + static void mac_get_model(char *str); void mac_bang(int irq, void *vector, struct pt_regs *p) @@ -118,8 +115,6 @@ via_init_clock(vector); } -extern int console_loglevel; - #if 0 void mac_waitbut (void) { @@ -213,76 +208,93 @@ void __init config_mac(void) { - - if (!MACH_IS_MAC) { - printk("ERROR: no Mac, but config_mac() called!! \n"); - } - - mach_sched_init = mac_sched_init; - mach_keyb_init = mackbd_init_hw; - mach_kbd_leds = mackbd_leds; - mach_init_IRQ = mac_init_IRQ; - mach_request_irq = mac_request_irq; - mach_free_irq = mac_free_irq; - enable_irq = mac_enable_irq; - disable_irq = mac_disable_irq; - mach_get_model = mac_get_model; - mach_default_handler = &mac_handlers; - mach_get_irq_list = mac_get_irq_list; - mach_gettimeoffset = mac_gettimeoffset; - mach_gettod = mac_gettod; - mach_hwclk = mac_hwclk; - mach_set_clock_mmss = mac_set_clock_mmss; + if (!MACH_IS_MAC) { + printk("ERROR: no Mac, but config_mac() called!! \n"); + } + +#ifdef CONFIG_VT +#ifdef CONFIG_INPUT_ADBHID + mach_keyb_init = mac_hid_init_hw; + mach_kbd_translate = mac_hid_kbd_translate; +#ifdef CONFIG_MAGIC_SYSRQ +#ifdef CONFIG_MAC_ADBKEYCODES + if (!keyboard_sends_linux_keycodes) { + mach_sysrq_xlate = mac_hid_kbd_sysrq_xlate; + SYSRQ_KEY = 0x69; + } else +#endif /* CONFIG_MAC_ADBKEYCODES */ + { + mach_sysrq_xlate = pckbd_sysrq_xlate; + SYSRQ_KEY = 0x54; + } +#endif /* CONFIG_MAGIC_SYSRQ */ +#elif defined(CONFIG_ADB_KEYBOARD) + mach_keyb_init = mackbd_init_hw; + mach_kbd_leds = mackbd_leds; + mach_kbd_translate = mackbd_translate; + mach_sysrq_xlate = mackbd_sysrq_xlate; + SYSRQ_KEY = 0x69; +#endif /* CONFIG_INPUT_ADBHID */ +#endif /* CONFIG_VT */ + + mach_sched_init = mac_sched_init; + mach_init_IRQ = mac_init_IRQ; + mach_request_irq = mac_request_irq; + mach_free_irq = mac_free_irq; + enable_irq = mac_enable_irq; + disable_irq = mac_disable_irq; + mach_get_model = mac_get_model; + mach_default_handler = &mac_handlers; + mach_get_irq_list = mac_get_irq_list; + mach_gettimeoffset = mac_gettimeoffset; + mach_gettod = mac_gettod; + mach_hwclk = mac_hwclk; + mach_set_clock_mmss = mac_set_clock_mmss; #if 0 - mach_mksound = mac_mksound; + mach_mksound = mac_mksound; #endif - mach_reset = mac_reset; - mach_halt = mac_poweroff; - mach_power_off = mac_poweroff; - conswitchp = &dummy_con; - mach_max_dma_address = 0xffffffff; + mach_reset = mac_reset; + mach_halt = mac_poweroff; + mach_power_off = mac_poweroff; + conswitchp = &dummy_con; + mach_max_dma_address = 0xffffffff; #if 0 - mach_debug_init = mac_debug_init; -#endif - kd_mksound = mac_mksound; -#ifdef CONFIG_MAGIC_SYSRQ - mach_sysrq_key = 114; /* HELP */ - mach_sysrq_shift_state = 8; /* Alt */ - mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */ - mach_sysrq_xlate = mac_sysrq_xlate; + mach_debug_init = mac_debug_init; #endif + kd_mksound = mac_mksound; #ifdef CONFIG_HEARTBEAT #if 0 - mach_heartbeat = mac_heartbeat; - mach_heartbeat_irq = IRQ_MAC_TIMER; + mach_heartbeat = mac_heartbeat; + mach_heartbeat_irq = IRQ_MAC_TIMER; #endif #endif - /* - * Determine hardware present - */ + /* + * Determine hardware present + */ - mac_identify(); - mac_report_hardware(); + mac_identify(); + mac_report_hardware(); - /* AFAIK only the IIci takes a cache card. The IIfx has onboard - cache ... someone needs to figure out how to tell if it's on or - not. */ - if (macintosh_config->ident == MAC_MODEL_IICI - || macintosh_config->ident == MAC_MODEL_IIFX) { - mach_l2_flush = mac_cache_card_flush; - } + /* AFAIK only the IIci takes a cache card. The IIfx has onboard + cache ... someone needs to figure out how to tell if it's on or + not. */ + + if (macintosh_config->ident == MAC_MODEL_IICI + || macintosh_config->ident == MAC_MODEL_IIFX) { + mach_l2_flush = mac_cache_card_flush; + } #ifdef MAC_DEBUG_SOUND - /* goes on forever if timers broken */ - mac_mksound(1000,10); + /* goes on forever if timers broken */ + mac_mksound(1000,10); #endif - /* - * Check for machine specific fixups. - */ + /* + * Check for machine specific fixups. + */ #ifdef OLD_NUBUS_CODE - nubus_sweep_video(); + nubus_sweep_video(); #endif } diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c --- v2.4.0-test11/linux/arch/m68k/mac/macints.c Sun Feb 13 11:21:42 2000 +++ linux/arch/m68k/mac/macints.c Sun Dec 3 17:48:19 2000 @@ -211,8 +211,6 @@ * console_loglevel determines NMI handler function */ -extern int console_loglevel; - extern void mac_bang(int, void *, struct pt_regs *); void mac_nmi_handler(int, void *, struct pt_regs *); diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mac/oss.c linux/arch/m68k/mac/oss.c --- v2.4.0-test11/linux/arch/m68k/mac/oss.c Sun Feb 13 11:21:42 2000 +++ linux/arch/m68k/mac/oss.c Sun Dec 3 17:48:19 2000 @@ -35,7 +35,6 @@ extern void via1_irq(int, void *, struct pt_regs *); extern void mac_scc_dispatch(int, void *, struct pt_regs *); -extern int console_loglevel; /* * Initialize the OSS diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mac/psc.c linux/arch/m68k/mac/psc.c --- v2.4.0-test11/linux/arch/m68k/mac/psc.c Sun Feb 13 11:21:42 2000 +++ linux/arch/m68k/mac/psc.c Sun Dec 3 17:48:19 2000 @@ -32,8 +32,6 @@ void psc_irq(int, void *, struct pt_regs *); -extern int console_loglevel; - /* * Debugging dump, used in various places to see what's going on. */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mac/via.c linux/arch/m68k/mac/via.c --- v2.4.0-test11/linux/arch/m68k/mac/via.c Sun Feb 13 11:21:42 2000 +++ linux/arch/m68k/mac/via.c Sun Dec 3 17:45:20 2000 @@ -74,7 +74,6 @@ extern void mac_bang(int, void *, struct pt_regs *); extern void mac_scc_dispatch(int, void *, struct pt_regs *); -extern int console_loglevel; extern int oss_present; /* diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mm/fault.c linux/arch/m68k/mm/fault.c --- v2.4.0-test11/linux/arch/m68k/mm/fault.c Mon Apr 24 15:51:29 2000 +++ linux/arch/m68k/mm/fault.c Mon Nov 27 17:11:26 2000 @@ -19,6 +19,55 @@ extern void die_if_kernel(char *, struct pt_regs *, long); extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */ +int send_fault_sig(struct pt_regs *regs) +{ + siginfo_t siginfo = { 0, 0, 0, }; + + siginfo.si_signo = current->thread.signo; + siginfo.si_code = current->thread.code; + siginfo.si_addr = (void *)current->thread.faddr; + printk("send_fault_sig: %p,%d,%d\n", siginfo.si_addr, siginfo.si_signo, siginfo.si_code); + + if (user_mode(regs)) { + force_sig_info(siginfo.si_signo, + &siginfo, current); + } else { + unsigned long fixup; + + /* Are we prepared to handle this kernel fault? */ + if ((fixup = search_exception_table(regs->pc))) { + struct pt_regs *tregs; + /* Create a new four word stack frame, discarding the old + one. */ + regs->stkadj = frame_extra_sizes[regs->format]; + tregs = (struct pt_regs *)((ulong)regs + regs->stkadj); + tregs->vector = regs->vector; + tregs->format = 0; + tregs->pc = fixup; + tregs->sr = regs->sr; + return -1; + } + + //if (siginfo.si_signo == SIGBUS) + // force_sig_info(siginfo.si_signo, + // &siginfo, current); + + /* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ + if ((unsigned long)siginfo.si_addr < PAGE_SIZE) + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + else + printk(KERN_ALERT "Unable to handle kernel access"); + printk(" at virtual address %p\n", siginfo.si_addr); + die_if_kernel("Oops", regs, 0 /*error_code*/); + do_exit(SIGKILL); + } + + return 1; +} + /* * This routine handles page faults. It determines the problem, and * then passes it off to one of the appropriate routines. @@ -30,16 +79,15 @@ * If this routine detects a bad access, it returns 1, otherwise it * returns 0. */ -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, +int do_page_fault(struct pt_regs *regs, unsigned long address, unsigned long error_code) { struct mm_struct *mm = current->mm; struct vm_area_struct * vma; - unsigned long fixup; int write, fault; #ifdef DEBUG - printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", + printk ("do page fault:\nregs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n", regs->sr, regs->pc, address, error_code, current->mm->pgd); #endif @@ -55,43 +103,46 @@ vma = find_vma(mm, address); if (!vma) - goto bad_area; + goto map_err; if (vma->vm_flags & VM_IO) - goto bad_area; + goto acc_err; if (vma->vm_start <= address) goto good_area; if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; + goto map_err; if (user_mode(regs)) { /* Accessing the stack below usp is always a bug. The "+ 256" is there due to some instructions doing pre-decrement on the stack and that doesn't show up until later. */ if (address + 256 < rdusp()) - goto bad_area; + goto map_err; } if (expand_stack(vma, address)) - goto bad_area; + goto map_err; /* * Ok, we have a good vm_area for this memory access, so * we can handle it.. */ good_area: +#ifdef DEBUG + printk("do_page_fault: good_area\n"); +#endif write = 0; switch (error_code & 3) { default: /* 3: write, present */ /* fall through */ case 2: /* write, not present */ if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; + goto acc_err; write++; break; case 1: /* read, present */ - goto bad_area; + goto acc_err; case 0: /* read, not present */ if (!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; + goto acc_err; } /* @@ -100,87 +151,56 @@ * the fault. */ fault = handle_mm_fault(mm, vma, address, write); +#ifdef DEBUG + printk("handle_mm_fault returns %d\n",fault); +#endif if (fault < 0) goto out_of_memory; if (!fault) - goto do_sigbus; + goto bus_err; /* There seems to be a missing invalidate somewhere in do_no_page. * Until I found it, this one cures the problem and makes * 1.2 run on the 68040 (Martin Apel). */ + #warning should be obsolete now... if (CPU_IS_040_OR_060) flush_tlb_page(vma, address); up(&mm->mmap_sem); return 0; /* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - up(&mm->mmap_sem); - - /* User mode accesses just cause a SIGSEGV */ - if (user_mode(regs)) { - siginfo_t info; - info.si_signo = SIGSEGV; - info.si_code = SEGV_MAPERR; - info.si_addr = (void *)address; - force_sig_info(SIGSEGV, &info, current); - return 1; - } - -no_context: - /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(regs->pc)) != 0) { - struct pt_regs *tregs; - /* Create a new four word stack frame, discarding the old - one. */ - regs->stkadj = frame_extra_sizes[regs->format]; - tregs = (struct pt_regs *)((ulong)regs + regs->stkadj); - tregs->vector = regs->vector; - tregs->format = 0; - tregs->pc = fixup; - tregs->sr = regs->sr; - return -1; - } - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - if ((unsigned long) address < PAGE_SIZE) { - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); - } else - printk(KERN_ALERT "Unable to handle kernel access"); - printk(" at virtual address %08lx\n",address); - die_if_kernel("Oops", regs, error_code); - do_exit(SIGKILL); - -/* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */ out_of_memory: - up(&mm->mmap_sem); printk("VM: killing process %s\n", current->comm); - if (error_code & 4) + if (user_mode(regs)) do_exit(SIGKILL); - goto no_context; -do_sigbus: - up(&mm->mmap_sem); - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - force_sig(SIGBUS, current); - - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; +no_context: + current->thread.signo = SIGBUS; + current->thread.faddr = address; + return send_fault_sig(regs); + +bus_err: + current->thread.signo = SIGBUS; + current->thread.code = BUS_ADRERR; + current->thread.faddr = address; + goto send_sig; + +map_err: + current->thread.signo = SIGSEGV; + current->thread.code = SEGV_MAPERR; + current->thread.faddr = address; + goto send_sig; + +acc_err: + current->thread.signo = SIGSEGV; + current->thread.code = SEGV_ACCERR; + current->thread.faddr = address; - return 1; +send_sig: + up(&mm->mmap_sem); + return send_fault_sig(regs); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c --- v2.4.0-test11/linux/arch/m68k/mvme147/config.c Mon Jan 31 10:32:53 2000 +++ linux/arch/m68k/mvme147/config.c Mon Nov 27 17:11:26 2000 @@ -201,15 +201,6 @@ /*------------------- Serial console stuff ------------------------*/ -void m147_scc_write(struct console *co, const char *str, unsigned cnt); - - -void mvme147_init_console_port (struct console *co, int cflag) -{ - co->write = m147_scc_write; -} - - static void scc_delay (void) { int n; @@ -250,3 +241,31 @@ restore_flags(flags); } + +static int m147_scc_wait_key (struct console *co) +{ + volatile unsigned char *p = (volatile char *)M147_SCC_A_ADDR; + unsigned long flags; + int c; + + /* wait for rx buf filled */ + while ((*p & 0x01) == 0) + ; + + save_flags(flags); + cli(); + + *p = 8; + scc_delay(); + c = *p; + + restore_flags(flags); + return c; +} + + +void mvme147_init_console_port (struct console *co, int cflag) +{ + co->write = m147_scc_write; + co->wait_key = m147_scc_wait_key; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/q40/README linux/arch/m68k/q40/README --- v2.4.0-test11/linux/arch/m68k/q40/README Sun Aug 15 11:47:29 1999 +++ linux/arch/m68k/q40/README Mon Nov 27 17:11:26 2000 @@ -56,8 +56,7 @@ This will save kernel startup msgs into SRAM, the screen will display only the penguin - and shell prompt if it gets that far.. -Serial console works and can also be used for debugging, provided serial -initialisation works. +Serial console works and can also be used for debugging, see loader_txt Most problems seem to be caused by fawlty or badly configured io-cards or harddrives anyway..there are so many things that can go wrong here. @@ -82,8 +81,9 @@ or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs. The Q40 custom chip is programmable to provide 2 periodic timers: - - 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!! - - 10 or 20 KHz - level 4 (and possibly 6 - hardware decoding..) + - 50 or 200 Hz - level 2, + - 10 or 20 KHz - level 4 + !!THIS CANT BE DISABLED!! Linux uses the 200 Hz interrupt for timer and beep by default. @@ -92,9 +92,6 @@ ========== q40 master chip handles only level triggered interrupts :-(( -further limitation is no disabling etc. There is NO WAY to remove -an ISA irq request other than serve the HW specific control register, -the ISA irq lines are connected straight to the CPU ipl1 pin.. IRQ sharing is not yet implemented but this should be only a minor problem.. @@ -102,12 +99,17 @@ Linux has some requirements wrt interrupt architecture, these are to my knowledge: (a) interrupt handler must not be reentered even when sti() is called + from within handler (b) working enable/disable_irq Luckily these requirements are only important for drivers shared with other architectures - ide,serial,parallel, ethernet.. -q40ints.c now contains a trivial hack for (a), however (b) could -be only solved by driver-specific code +q40ints.c now contains a trivial hack for (a), (b) is more difficult +because only irq's 4-15 can be disabled - and only all o them at once. +Thus disable_irq() can effectively block the machine if the driver goes +asleep. +One thing to keep in minde when hacking around the interrupt code is +that there is no way to find out which IRQ caused a request. Keyboard ======== diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c --- v2.4.0-test11/linux/arch/m68k/q40/config.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/q40/config.c Mon Nov 27 17:57:34 2000 @@ -13,6 +13,7 @@ */ #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -34,8 +36,8 @@ #include #include -extern void fd_floppy_eject(void); -extern void fd_floppy_setup(char *str, int *ints); +extern void floppy_eject(void); +extern void floppy_setup(char *str, int *ints); extern void q40_process_int (int level, struct pt_regs *regs); extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *); /* added just for debugging */ @@ -65,9 +67,12 @@ extern char m68k_debug_device[]; static void q40_mem_console_write(struct console *co, const char *b, unsigned int count); +#if 0 +extern int ql_ticks=0; +extern int sound_ticks=0; +#endif -static int ql_ticks=0; -static int sound_ticks=0; +extern int ql_ticks; static unsigned char bcd2bin (unsigned char b); static unsigned char bin2bcd (unsigned char b); @@ -81,16 +86,16 @@ }; -/* Save tick handler routine pointer, will point to do_timer() in - * kernel/sched.c */ - -/* static void (*tick_handler)(int, void *, struct pt_regs *); */ - - /* early debugging function:*/ extern char *q40_mem_cptr; /*=(char *)0xff020000;*/ static int _cpleft; +int q40_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) +{ + *keycodep = keycode; + return 1; +} + static void q40_mem_console_write(struct console *co, const char *s, unsigned int count) { @@ -140,6 +145,41 @@ sprintf(model, "Q40"); } +/* pasted code to make parport_pc happy */ +extern __inline__ int __get_order(unsigned long size) +{ + int order; + + size = (size-1) >> (PAGE_SHIFT-1); + order = -1; + do { + size >>= 1; + order++; + } while (size); + return order; +} +void *pci_alloc_consistent(void *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + int gfp = GFP_ATOMIC; + + ret = (void *)__get_free_pages(gfp, __get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_bus(ret); + } + return ret; +} + +void pci_free_consistent(void *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, __get_order(size)); +} +/* end pasted code */ + /* No hardware options on Q40? */ @@ -149,12 +189,23 @@ return 0; } +static unsigned int serports[]={0x3f8,0x2f8,0x3e8,0x2e8,0}; +void q40_disable_irqs(void) +{ + unsigned i,j; + + j=0; + while((i=serports[j++])) outb(0,i+UART_IER); + master_outb(0,EXT_ENABLE_REG); + master_outb(0,KEY_IRQ_ENABLE_REG); +} void __init config_q40(void) { mach_sched_init = q40_sched_init; /* ok */ /*mach_kbdrate = q40_kbdrate;*/ /* unneeded ?*/ mach_keyb_init = q40_keyb_init; /* OK */ + mach_kbd_translate = q40_kbd_translate; mach_init_IRQ = q40_init_IRQ; mach_gettimeoffset = q40_gettimeoffset; mach_gettod = q40_gettod; @@ -177,13 +228,14 @@ mach_sysrq_key = 0x54; #endif conswitchp = &dummy_con; -#ifdef CONFIG_BLK_DEV_FD - mach_floppy_setup = fd_floppy_setup; - mach_floppy_eject = fd_floppy_eject; +#if 0 /*def CONFIG_BLK_DEV_FD*/ + mach_floppy_setup = floppy_setup; + mach_floppy_eject = floppy_eject; /**/ #endif - mach_max_dma_address = 0; /* no DMA at all */ + q40_disable_irqs(); + mach_max_dma_address = 32*1024*1024; /* no DMA at all, but ide-scsi requires it.. */ /* userfull for early debuging stages writes kernel messages into SRAM */ @@ -203,6 +255,7 @@ return 1; /* unknown */ } +#if 0 #define DAC_LEFT ((unsigned char *)0xff008000) #define DAC_RIGHT ((unsigned char *)0xff008004) void q40_mksound(unsigned int hz, unsigned int ticks) @@ -258,7 +311,11 @@ #endif q40_timer_routine(irq, dev_id, fp); } +#endif +#if 0 +extern void (*q40_timer_routine)(int, void *, struct pt_regs *); +extern void q40_timer_int(); void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *)) { @@ -289,7 +346,7 @@ #endif #endif } - +#endif unsigned long q40_gettimeoffset (void) { diff -u --recursive --new-file v2.4.0-test11/linux/arch/m68k/q40/q40ints.c linux/arch/m68k/q40/q40ints.c --- v2.4.0-test11/linux/arch/m68k/q40/q40ints.c Tue Aug 17 10:39:32 1999 +++ linux/arch/m68k/q40/q40ints.c Mon Nov 27 17:11:26 2000 @@ -7,18 +7,22 @@ * License. See the file COPYING in the main directory of this archive * for more details. * - * losely based on bvme6000ints.c + * .. used to be losely based on bvme6000ints.c * */ +#include #include #include #include #include +#include +#include #include #include #include +#include #include #include @@ -71,13 +75,16 @@ * the q40 IRQ handling routines. */ +static int disabled=0; + void q40_init_IRQ (void) { int i; + disabled=0; for (i = 0; i <= Q40_IRQ_MAX; i++) { irq_tab[i].handler = q40_defhand; - irq_tab[i].flags = IRQ_FLG_STD; + irq_tab[i].flags = 0; irq_tab[i].dev_id = NULL; /* irq_tab[i].next = NULL;*/ irq_tab[i].devname[0] = 0; @@ -87,14 +94,10 @@ } /* setup handler for ISA ints */ - sys_request_irq(IRQ2,q40_irq2_handler, IRQ_FLG_LOCK, "q40 ISA and master chip", NULL); + sys_request_irq(IRQ2,q40_irq2_handler, 0, "q40 ISA and master chip", NULL); /* now enable some ints.. */ - -#if 0 /* has been abandoned */ - master_outb(1,SER_ENABLE_REG); -#endif - master_outb(1,EXT_ENABLE_REG); + master_outb(1,EXT_ENABLE_REG); /* hm, aint that too early? */ /* would be spurious ints by now, q40kbd_init_hw() does that */ master_outb(0,KEY_IRQ_ENABLE_REG); @@ -124,24 +127,20 @@ default: } - if (irq4 && irq<=15 && mext_disabled) + { + /*aliased_irq++;*/ + goto iirq; + } if (irq_tab[irq].handler == q40_defhand ) { printk("handler for IRQ %d not defined\n",irq); continue; /* ignore uninited INTs :-( */ } - if ( irq_tab[irq].state & IRQ_INPROGRESS ) { + /* some handlers do sti() for irq latency reasons, */ + /* however reentering an active irq handler is not permitted */ +#ifdef IP_USE_DISABLE + /* in theory this is the better way to do it because it still */ + /* lets through eg the serial irqs, unfortunately it crashes */ + disable_irq(irq); + disabled=1; +#else /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */ - - /*saved_mask = fp->sr;*/ - fp->sr = (fp->sr & (~0x700))+0x200; + fp->sr = (((fp->sr) & (~0x700))+0x200); disabled=1; - return; +#endif + goto iirq; } + irq_tab[irq].count++; irq_tab[irq].state |= IRQ_INPROGRESS; irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); + irq_tab[irq].state &= ~IRQ_INPROGRESS; /* naively enable everything, if that fails than */ /* this function will be reentered immediately thus */ /* getting another chance to disable the IRQ */ - irq_tab[irq].state &= ~IRQ_INPROGRESS; if ( disabled ) { +#ifdef IP_USE_DISABLE + if (irq>4){ + disabled=0; + /*dd_count--;*/ + enable_irq(irq);} +#else + disabled=0; /*printk("reenabling irq %d\n",irq); */ - fp->sr = (fp->sr & (~0x700)); /*saved_mask; */ - disabled=0; +#if 0 + fp->sr = ((fp->sr) & (~0x700)); /* unneeded ?! */ +#endif +#endif } - else if ( fp->sr &0x200 ) - printk("exiting irq handler: fp->sr &0x200 !!\n"); - - return; + goto repeat; /* return; */ } } - if (ccleirq>0) + if (mer && ccleirq>0 && !aliased_irq) printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; } - else + iirq: + mir=master_inb(IIRQ_REG); + if (mir&IRQ_FRAME_MASK) { - /* internal */ - - for (i=0; iirqs[i].mask; i++) + do_tint++; + master_outb(-1,FRAME_CLEAR_REG); + } + for(;do_tint>0;do_tint--) { - if (mir&(iirqs[i].mask)) - { - irq=iirqs[i].irq; - irq_tab[irq].count++; - if (irq_tab[irq].handler == q40_defhand ) - continue; /* ignore uninited INTs :-( */ - - /* the INPROGRESS stuff should be completely useless*/ - /* for internal ints, nevertheless test it..*/ - if ( irq_tab[irq].state & IRQ_INPROGRESS ) + irq_tab[Q40_IRQ_FRAME].count++; + irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); + } + if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/ { - /*disable_irq(irq); - return;*/ - printk("rentering handler for IRQ %d !!\n",irq); - } - irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); - irq_tab[irq].state &= ~IRQ_INPROGRESS; - /*enable_irq(irq);*/ /* better not try luck !*/ - return; - } - } - if (cclirq>0) - printk("internal level 2 interrupt from unknown source ? IIRQ_REG=%x\n",mir),cclirq--; + irq_tab[Q40_IRQ_KEYBOARD].count++; + irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); } } @@ -335,9 +445,11 @@ { int i, len = 0; - for (i = 0; i <= Q40_IRQ_MAX; i++) { + for (i = 0; i <= Q40_IRQ_MAX; i++) + { if (irq_tab[i].count) - len += sprintf (buf+len, "Vec 0x%02x: %8d %s%s\n", + len += sprintf (buf+len, "%sIRQ %02d: %8d %s%s\n", + (i<=15) ? "ISA-" : " " , i, irq_tab[i].count, irq_tab[i].devname[0] ? irq_tab[i].devname : "?", irq_tab[i].handler == q40_defhand ? @@ -370,30 +482,17 @@ sys_default_handler,sys_default_handler,sys_default_handler,sys_default_handler }; -int irq_disabled=0; + void q40_enable_irq (unsigned int irq) { - /* enable ISA iqs */ - if ( irq>=0 && irq<=15 ) /* the moderately bad case */ + if ( irq>=5 && irq<=15 ) + { + mext_disabled--; + if (mext_disabled>0) + printk("q40_enable_irq : nested disable/enable\n"); + if (mext_disabled==0) master_outb(1,EXT_ENABLE_REG); -#if 0 - unsigned long flags; - int i; - - if (irq>=10 && irq <= 15) - { - if ( !(--q40_ablecount[irq])) - for (i=10,irq_disabled=0; i<=15; i++) - { - irq_disabled |= (q40_ablecount[irq] !=0); - } - if ( !irq_disabled ) - { - save_flags(flags); - restore_flags(flags & (~0x700)); - } } -#endif } @@ -404,19 +503,12 @@ * Any driver should not attempt to sleep accross disable_irq !! */ - if ( irq>=10 && irq<=15 ) /* the moderately bad case */ - master_outb(0,EXT_ENABLE_REG); -#if 0 - unsigned long flags; - - if (irq>=10 && irq <= 15) + if ( irq>=5 && irq<=15 ) { - save_flags(flags); - restore_flags(flags | 0x200 ); - irq_disabled=1; - q40_ablecount[irq]++; + master_outb(0,EXT_ENABLE_REG); + mext_disabled++; + if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled); } -#endif } unsigned long q40_probe_irq_on (void) @@ -428,3 +520,7 @@ { return -1; } +/* + * Local variables: + * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c" + */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c --- v2.4.0-test11/linux/arch/mips/ddb5074/pci.c Mon Aug 7 14:31:40 2000 +++ linux/arch/mips/ddb5074/pci.c Mon Nov 27 17:51:34 2000 @@ -286,7 +286,6 @@ pci_scan_bus(0, &nile4_pci_ops, NULL); ddb5074_pci_fixup(); pci_assign_unassigned_resources(); - pci_set_bus_ranges(); pcibios_fixup_irqs(); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c --- v2.4.0-test11/linux/arch/mips/kernel/traps.c Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/kernel/traps.c Sun Dec 3 17:48:19 2000 @@ -27,19 +27,6 @@ #include #include -extern int console_loglevel; - -static inline void console_silent(void) -{ - console_loglevel = 0; -} - -static inline void console_verbose(void) -{ - if (console_loglevel) - console_loglevel = 15; -} - /* * Machine specific interrupt handlers */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile --- v2.4.0-test11/linux/arch/mips/lib/Makefile Sun Jul 9 22:18:15 2000 +++ linux/arch/mips/lib/Makefile Tue Dec 5 23:15:12 2000 @@ -1,4 +1,3 @@ -# $Id: Makefile,v 1.11 1999/10/17 19:55:22 harald Exp $ # # Makefile for MIPS-specific library files.. # diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S --- v2.4.0-test11/linux/arch/mips/lib/memcpy.S Sat May 13 08:29:14 2000 +++ linux/arch/mips/lib/memcpy.S Tue Dec 5 23:15:12 2000 @@ -3,8 +3,6 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * $Id: memcpy.S,v 1.3 1998/07/10 01:14:49 ralf Exp $ - * * Unified implementation of memcpy, memmove and the __copy_user backend. * For __rmemcpy and memmove an exception is always a kernel bug, therefore * they're not protected. In order to keep the exception fixup routine @@ -410,6 +408,7 @@ sltu t0, v0, a1 # dst + len < src -> non- bnez t0, __memcpy # overlapping, can use memcpy move v0, a0 /* return value */ + beqz a2, r_out END(memmove) LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S --- v2.4.0-test11/linux/arch/mips/lib/memset.S Sat May 13 08:29:14 2000 +++ linux/arch/mips/lib/memset.S Tue Dec 5 23:15:12 2000 @@ -1,13 +1,9 @@ /* - * include/asm-mips/types.h - * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 1998 by Ralf Baechle - * - * $Id: memset.S,v 1.2 1998/04/25 17:01:45 ralf Exp $ */ #include #include diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/Makefile linux/arch/mips64/Makefile --- v2.4.0-test11/linux/arch/mips64/Makefile Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/Makefile Wed Dec 6 20:32:41 2000 @@ -12,6 +12,7 @@ # # Select the object file format to substitute into the linker script. # +CPP=$(CC) -E ifdef CONFIG_CPU_LITTLE_ENDIAN tool-prefix = mips64el-linux- else @@ -32,6 +33,7 @@ # machines may also. Since BFD is incredibly buggy with respect to # crossformat linking we rely on the elf2ecoff tool for format conversion. # +CFLAGS += -I $(TOPDIR)/include/asm $(CFLAGS) CFLAGS += -mabi=64 -G 0 -mno-abicalls -fno-pic -Wa,--trap -pipe LINKFLAGS += -G 0 -static # -N MODFLAGS += -mlong-calls @@ -129,6 +131,10 @@ 64bit-bfd = elf64-bigmips endif +vmlinux: arch/mips64/ld.script.elf32 +arch/mips64/ld.script.elf32: arch/mips64/ld.script.elf32.S + $(CPP) -C -P -I$(HPATH) -imacros $(HPATH)/asm-mips64/sn/mapped_kernel.h -Umips arch/mips64/ld.script.elf32.S > arch/mips64/ld.script.elf32 + ifdef CONFIG_MAPPED_KERNEL vmlinux.64: vmlinux $(OBJCOPY) -O $(64bit-bfd) --change-addresses=0xbfffffff40000000 $< $@ @@ -149,7 +155,7 @@ @$(MAKEBOOT) clean $(MAKE) -C arch/$(ARCH)/kernel clean $(MAKE) -C arch/$(ARCH)/tools clean - rm -f vmlinux.64 + rm -f vmlinux.64 arch/$(ARCH)/ld.script.elf32 archmrproper: @$(MAKEBOOT) mrproper diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/arc/Makefile linux/arch/mips64/arc/Makefile --- v2.4.0-test11/linux/arch/mips64/arc/Makefile Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/Makefile Tue Nov 28 21:42:04 2000 @@ -1,11 +1,14 @@ -# $Id: Makefile,v 1.1 1999/08/20 21:13:32 ralf Exp $ # # Makefile for the ARC prom monitor library routines under Linux. # L_TARGET = arclib.a -L_OBJS = console.o init.o printf.o tree.o env.o cmdline.o misc.o time.o \ +L_OBJS = init.o printf.o tree.o env.o cmdline.o misc.o time.o \ file.o identify.o + +ifndef CONFIG_SGI_IP27 +L_OBJS += console.o +endif ifdef CONFIG_ARC_MEMORY L_OBJS += memory.o diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/arc/console.c linux/arch/mips64/arc/console.c --- v2.4.0-test11/linux/arch/mips64/arc/console.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/console.c Tue Nov 28 21:42:04 2000 @@ -1,17 +1,14 @@ -/* $Id: console.c,v 1.3 1999/10/19 20:51:44 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * ARC console code. - * * Copyright (C) 1996 David S. Miller (dm@sgi.com) */ #include #include -void __init prom_putchar(char c) +void prom_putchar(char c) { ULONG cnt; CHAR it = c; diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/arc/printf.c linux/arch/mips64/arc/printf.c --- v2.4.0-test11/linux/arch/mips64/arc/printf.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/arc/printf.c Tue Nov 28 21:42:04 2000 @@ -15,7 +15,7 @@ static char ppbuf[1024]; -void __init prom_printf(char *fmt, ...) +void prom_printf(char *fmt, ...) { va_list args; char ch, *bptr; diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.4.0-test11/linux/arch/mips64/config.in Sun Nov 19 18:44:03 2000 +++ linux/arch/mips64/config.in Tue Nov 28 21:42:04 2000 @@ -21,7 +21,7 @@ bool ' Mapped kernel support' CONFIG_MAPPED_KERNEL bool ' Kernel text replication support' CONFIG_REPLICATE_KTEXT bool ' Exception handler replication support' CONFIG_REPLICATE_EXHANDLERS - bool ' Multi-Processing support (Experimental)' CONFIG_SMP + bool ' Multi-Processing support' CONFIG_SMP #bool ' IP27 XXL' CONFIG_SGI_SN0_XXL fi endmenu diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/defconfig linux/arch/mips64/defconfig --- v2.4.0-test11/linux/arch/mips64/defconfig Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/defconfig Tue Nov 28 21:42:04 2000 @@ -13,18 +13,20 @@ # CONFIG_SGI_IP22 is not set CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set -# CONFIG_DISCONTIGMEM is not set +CONFIG_DISCONTIGMEM=y # CONFIG_NUMA is not set # CONFIG_MAPPED_KERNEL is not set # CONFIG_REPLICATE_KTEXT is not set # CONFIG_REPLICATE_EXHANDLERS is not set -# CONFIG_SMP is not set +CONFIG_SMP=y CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y CONFIG_PCI=y CONFIG_QL_ISP_A64=y # CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_MCA is not set # CONFIG_SBUS is not set # @@ -72,17 +74,24 @@ # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set # CONFIG_MD_RAID1 is not set # CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -98,10 +107,8 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set @@ -136,7 +143,7 @@ # CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set +CONFIG_CHR_DEV_ST=y # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set @@ -145,8 +152,8 @@ # # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y # # SCSI low-level drivers @@ -163,6 +170,7 @@ # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set @@ -176,8 +184,6 @@ # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set @@ -189,6 +195,8 @@ CONFIG_SCSI_QLOGIC_ISP=y # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set @@ -215,6 +223,7 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # @@ -227,6 +236,7 @@ # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_DEPCA is not set +# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -235,6 +245,7 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_PLIP is not set @@ -304,6 +315,10 @@ # Joysticks # # CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# # CONFIG_QIC02_TAPE is not set # @@ -313,11 +328,6 @@ # CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -326,14 +336,19 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_DRM is not set # CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set # # File systems # # CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set @@ -375,12 +390,13 @@ # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -403,7 +419,10 @@ # CONFIG_AMIGA_PARTITION is not set # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -419,6 +438,11 @@ # USB support # # CONFIG_USB is not set + +# +# Input core support +# +# CONFIG_INPUT is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22 --- v2.4.0-test11/linux/arch/mips64/defconfig-ip22 Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/defconfig-ip22 Tue Nov 28 21:42:04 2000 @@ -18,7 +18,9 @@ CONFIG_ARC_MEMORY=y CONFIG_SGI=y # CONFIG_ISA is not set +# CONFIG_EISA is not set # CONFIG_PCI is not set +# CONFIG_MCA is not set # CONFIG_SBUS is not set # @@ -62,17 +64,24 @@ # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set # CONFIG_MD_RAID1 is not set # CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -88,10 +97,8 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set @@ -142,6 +149,7 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # @@ -153,6 +161,7 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_PLIP is not set @@ -223,6 +232,10 @@ # Joysticks # # CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# # CONFIG_QIC02_TAPE is not set # @@ -232,11 +245,6 @@ # CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -245,8 +253,13 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_DRM is not set # CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set # # File systems @@ -342,6 +355,11 @@ # USB support # # CONFIG_USB is not set + +# +# Input core support +# +# CONFIG_INPUT is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27 --- v2.4.0-test11/linux/arch/mips64/defconfig-ip27 Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/defconfig-ip27 Tue Nov 28 21:42:04 2000 @@ -13,18 +13,20 @@ # CONFIG_SGI_IP22 is not set CONFIG_SGI_IP27=y # CONFIG_SGI_SN0_N_MODE is not set -# CONFIG_DISCONTIGMEM is not set +CONFIG_DISCONTIGMEM=y # CONFIG_NUMA is not set # CONFIG_MAPPED_KERNEL is not set # CONFIG_REPLICATE_KTEXT is not set # CONFIG_REPLICATE_EXHANDLERS is not set -# CONFIG_SMP is not set +CONFIG_SMP=y CONFIG_BOOT_ELF64=y CONFIG_ARC64=y CONFIG_COHERENT_IO=y CONFIG_PCI=y CONFIG_QL_ISP_A64=y # CONFIG_ISA is not set +# CONFIG_EISA is not set +# CONFIG_MCA is not set # CONFIG_SBUS is not set # @@ -72,17 +74,24 @@ # CONFIG_BLK_DEV_XD is not set # CONFIG_PARIDE is not set # CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set # CONFIG_BLK_DEV_MD is not set # CONFIG_MD_LINEAR is not set # CONFIG_MD_RAID0 is not set # CONFIG_MD_RAID1 is not set # CONFIG_MD_RAID5 is not set -# CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -98,10 +107,8 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y # CONFIG_IP_PNP_RARP is not set -# CONFIG_IP_ROUTER is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set -# CONFIG_IP_ALIAS is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set @@ -136,7 +143,7 @@ # CONFIG_BLK_DEV_SD=y CONFIG_SD_EXTRA_DEVS=40 -# CONFIG_CHR_DEV_ST is not set +CONFIG_CHR_DEV_ST=y # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set @@ -145,8 +152,8 @@ # # CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y # # SCSI low-level drivers @@ -163,6 +170,7 @@ # CONFIG_SCSI_AM53C974 is not set # CONFIG_SCSI_MEGARAID is not set # CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_DTC3280 is not set # CONFIG_SCSI_EATA is not set @@ -176,8 +184,6 @@ # CONFIG_SCSI_PPA is not set # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_SIM710 is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set # CONFIG_SCSI_SYM53C8XX is not set @@ -189,6 +195,8 @@ CONFIG_SCSI_QLOGIC_ISP=y # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_T128 is not set # CONFIG_SCSI_U14_34F is not set @@ -215,6 +223,7 @@ # CONFIG_DUMMY is not set # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set # CONFIG_NET_SB1000 is not set # @@ -227,6 +236,7 @@ # CONFIG_NET_VENDOR_SMC is not set # CONFIG_NET_VENDOR_RACAL is not set # CONFIG_DEPCA is not set +# CONFIG_HP100 is not set # CONFIG_NET_ISA is not set # CONFIG_NET_PCI is not set # CONFIG_NET_POCKET is not set @@ -235,6 +245,7 @@ # Ethernet (1000 Mbit) # # CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set # CONFIG_SK98LIN is not set # CONFIG_FDDI is not set # CONFIG_PLIP is not set @@ -304,6 +315,10 @@ # Joysticks # # CONFIG_JOYSTICK is not set + +# +# Input core support is needed for joysticks +# # CONFIG_QIC02_TAPE is not set # @@ -313,11 +328,6 @@ # CONFIG_INTEL_RNG is not set # CONFIG_NVRAM is not set # CONFIG_RTC is not set - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -326,14 +336,19 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set -# CONFIG_DRM is not set # CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set # # File systems # # CONFIG_QUOTA is not set -# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS_FS=y # CONFIG_AUTOFS4_FS is not set # CONFIG_ADFS_FS is not set # CONFIG_ADFS_FS_RW is not set @@ -375,12 +390,13 @@ # # CONFIG_CODA_FS is not set CONFIG_NFS_FS=y -# CONFIG_NFS_V3 is not set +CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y # CONFIG_NFSD is not set # CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y # CONFIG_SMB_FS is not set # CONFIG_NCP_FS is not set # CONFIG_NCPFS_PACKET_SIGNING is not set @@ -403,7 +419,10 @@ # CONFIG_AMIGA_PARTITION is not set # CONFIG_ATARI_PARTITION is not set # CONFIG_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set CONFIG_SGI_PARTITION=y # CONFIG_ULTRIX_PARTITION is not set # CONFIG_SUN_PARTITION is not set @@ -419,6 +438,11 @@ # USB support # # CONFIG_USB is not set + +# +# Input core support +# +# CONFIG_INPUT is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/ioctl32.c linux/arch/mips64/kernel/ioctl32.c --- v2.4.0-test11/linux/arch/mips64/kernel/ioctl32.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/kernel/ioctl32.c Tue Nov 28 21:42:04 2000 @@ -3,28 +3,65 @@ * * Copyright (C) 2000 Silicon Graphics, Inc. * Written by Ulf Carlsson (ulfc@engr.sgi.com) + * Copyright (C) 2000 Ralf Baechle * - * Mostly from the sparc64 ioctl32 implementation. + * Mostly stolen from the sparc64 ioctl32 implementation. */ - #include #include #include #include #include +#include #include #include #include #include #include #include +#include +#include +#include +#include +#include +#include #include #include -#define A(__x) ((unsigned long)(__x)) - long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); +static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; + + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user((unsigned int) val, (u32 *)arg)) + return -EFAULT; + return err; +} + +static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + int err; + unsigned long val; + + if (get_user(val, (u32 *)arg)) + return -EFAULT; + set_fs(KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&val); + set_fs (old_fs); + if (!err && put_user(val, (u32 *)arg)) + return -EFAULT; + return err; +} + +#define A(__x) ((unsigned long)(__x)) + struct timeval32 { int tv_sec; int tv_usec; @@ -283,20 +320,217 @@ return sys_ioctl(fd, cmd, arg); } -static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg) +struct hd_geometry32 { + unsigned char heads; + unsigned char sectors; + unsigned short cylinders; + u32 start; +}; + +static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); + struct hd_geometry geo; int err; - unsigned long val; - + set_fs (KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long)&val); + err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo); set_fs (old_fs); - if (!err && put_user((unsigned int) val, (u32 *)arg)) - return -EFAULT; + if (!err) { + err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4); + err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start)); + } + + return err ? -EFAULT : 0; +} + +static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + unsigned long kval; + unsigned int *uvp; + int error; + + set_fs(KERNEL_DS); + error = sys_ioctl(fd, cmd, (long)&kval); + set_fs(old_fs); + + if (error == 0) { + uvp = (unsigned int *)arg; + if (put_user(kval, uvp)) + error = -EFAULT; + } + + return error; +} + +struct blkpg_ioctl_arg32 { + int op; + int flags; + int datalen; + u32 data; +}; + +static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, + struct blkpg_ioctl_arg32 *arg) +{ + struct blkpg_ioctl_arg a; + struct blkpg_partition p; + int err; + mm_segment_t old_fs = get_fs(); + + err = get_user(a.op, &arg->op); + err |= __get_user(a.flags, &arg->flags); + err |= __get_user(a.datalen, &arg->datalen); + err |= __get_user((long)a.data, &arg->data); + if (err) return err; + switch (a.op) { + case BLKPG_ADD_PARTITION: + case BLKPG_DEL_PARTITION: + if (a.datalen < sizeof(struct blkpg_partition)) + return -EINVAL; + if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition))) + return -EFAULT; + a.data = &p; + set_fs (KERNEL_DS); + err = sys_ioctl(fd, cmd, (unsigned long)&a); + set_fs (old_fs); + default: + return -EINVAL; + } return err; } +struct mtget32 { + __u32 mt_type; + __u32 mt_resid; + __u32 mt_dsreg; + __u32 mt_gstat; + __u32 mt_erreg; + __kernel_daddr_t32 mt_fileno; + __kernel_daddr_t32 mt_blkno; +}; +#define MTIOCGET32 _IOR('m', 2, struct mtget32) + +struct mtpos32 { + __u32 mt_blkno; +}; +#define MTIOCPOS32 _IOR('m', 3, struct mtpos32) + +struct mtconfiginfo32 { + __u32 mt_type; + __u32 ifc_type; + __u16 irqnr; + __u16 dmanr; + __u16 port; + __u32 debug; + __u32 have_dens:1; + __u32 have_bsf:1; + __u32 have_fsr:1; + __u32 have_bsr:1; + __u32 have_eod:1; + __u32 have_seek:1; + __u32 have_tell:1; + __u32 have_ras1:1; + __u32 have_ras2:1; + __u32 have_ras3:1; + __u32 have_qfa:1; + __u32 pad1:5; + char reserved[10]; +}; +#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32) +#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32) + +static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs = get_fs(); + struct mtconfiginfo info; + struct mtget get; + struct mtpos pos; + unsigned long kcmd; + void *karg; + int err = 0; + + switch(cmd) { + case MTIOCPOS32: + kcmd = MTIOCPOS; + karg = &pos; + break; + case MTIOCGET32: + kcmd = MTIOCGET; + karg = &get; + break; + case MTIOCGETCONFIG32: + kcmd = MTIOCGETCONFIG; + karg = &info; + break; + case MTIOCSETCONFIG32: + kcmd = MTIOCSETCONFIG; + karg = &info; + err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); + err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); + err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); + err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); + err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port); + err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); + err |= __copy_from_user((char *)&info.debug + sizeof(info.debug), + (char *)&((struct mtconfiginfo32 *)arg)->debug + + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32)); + if (err) + return -EFAULT; + break; + default: + do { + static int count = 0; + if (++count <= 20) + printk("mt_ioctl: Unknown cmd fd(%d) " + "cmd(%08x) arg(%08x)\n", + (int)fd, (unsigned int)cmd, (unsigned int)arg); + } while(0); + return -EINVAL; + } + set_fs (KERNEL_DS); + err = sys_ioctl (fd, kcmd, (unsigned long)karg); + set_fs (old_fs); + if (err) + return err; + switch (cmd) { + case MTIOCPOS32: + err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno); + break; + case MTIOCGET32: + err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); + err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid); + err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg); + err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat); + err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg); + err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno); + err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno); + break; + case MTIOCGETCONFIG32: + err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); + err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); + err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); + err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); + err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port); + err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); + err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug + + sizeof(((struct mtconfiginfo32 *)arg)->debug), + (char *)&info.debug + sizeof(info.debug), sizeof(__u32)); + break; + case MTIOCSETCONFIG32: + break; + } + return err ? -EFAULT: 0; +} + +#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int) + +static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg); +} + struct ioctl32_handler { unsigned int cmd; int (*function)(unsigned int, unsigned int, unsigned long); @@ -437,8 +671,66 @@ IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl), IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl), - IOCTL32_HANDLER(BLKGETSIZE, w_long) - + IOCTL32_HANDLER(HDIO_GETGEO, hdio_getgeo), /* hdreg.h ioctls */ + IOCTL32_HANDLER(HDIO_GET_UNMASKINTR, hdio_ioctl_trans), + IOCTL32_HANDLER(HDIO_GET_MULTCOUNT, hdio_ioctl_trans), + // HDIO_OBSOLETE_IDENTITY + IOCTL32_HANDLER(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans), + IOCTL32_HANDLER(HDIO_GET_32BIT, hdio_ioctl_trans), + IOCTL32_HANDLER(HDIO_GET_NOWERR, hdio_ioctl_trans), + IOCTL32_HANDLER(HDIO_GET_DMA, hdio_ioctl_trans), + IOCTL32_HANDLER(HDIO_GET_NICE, hdio_ioctl_trans), + IOCTL32_DEFAULT(HDIO_GET_IDENTITY), + IOCTL32_DEFAULT(HDIO_DRIVE_RESET), + // HDIO_TRISTATE_HWIF /* not implemented */ + // HDIO_DRIVE_TASK /* To do, need specs */ + IOCTL32_DEFAULT(HDIO_DRIVE_CMD), + IOCTL32_DEFAULT(HDIO_SET_MULTCOUNT), + IOCTL32_DEFAULT(HDIO_SET_UNMASKINTR), + IOCTL32_DEFAULT(HDIO_SET_KEEPSETTINGS), + IOCTL32_DEFAULT(HDIO_SET_32BIT), + IOCTL32_DEFAULT(HDIO_SET_NOWERR), + IOCTL32_DEFAULT(HDIO_SET_DMA), + IOCTL32_DEFAULT(HDIO_SET_PIO_MODE), + IOCTL32_DEFAULT(HDIO_SCAN_HWIF), + IOCTL32_DEFAULT(HDIO_SET_NICE), + //HDIO_UNREGISTER_HWIF + + IOCTL32_DEFAULT(BLKROSET), /* fs.h ioctls */ + IOCTL32_DEFAULT(BLKROGET), + IOCTL32_DEFAULT(BLKRRPART), + IOCTL32_HANDLER(BLKGETSIZE, w_long), + + IOCTL32_DEFAULT(BLKFLSBUF), + IOCTL32_DEFAULT(BLKRASET), + IOCTL32_HANDLER(BLKRAGET, w_long), + IOCTL32_DEFAULT(BLKFRASET), + IOCTL32_HANDLER(BLKFRAGET, w_long), + IOCTL32_DEFAULT(BLKSECTSET), + IOCTL32_HANDLER(BLKSECTGET, w_long), + IOCTL32_DEFAULT(BLKSSZGET), + IOCTL32_HANDLER(BLKPG, blkpg_ioctl_trans), + IOCTL32_DEFAULT(BLKELVGET), + IOCTL32_DEFAULT(BLKELVSET), + + IOCTL32_DEFAULT(MTIOCTOP), /* mtio.h ioctls */ + IOCTL32_HANDLER(MTIOCGET32, mt_ioctl_trans), + IOCTL32_HANDLER(MTIOCPOS32, mt_ioctl_trans), + IOCTL32_HANDLER(MTIOCGETCONFIG32, mt_ioctl_trans), + IOCTL32_HANDLER(MTIOCSETCONFIG32, mt_ioctl_trans), + // MTIOCRDFTSEG + // MTIOCWRFTSEG + // MTIOCVOLINFO + // MTIOCGETSIZE + // MTIOCFTFORMAT + // MTIOCFTCMD + + IOCTL32_DEFAULT(AUTOFS_IOC_READY), /* auto_fs.h ioctls */ + IOCTL32_DEFAULT(AUTOFS_IOC_FAIL), + IOCTL32_DEFAULT(AUTOFS_IOC_CATATONIC), + IOCTL32_DEFAULT(AUTOFS_IOC_PROTOVER), + IOCTL32_HANDLER(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout), + IOCTL32_DEFAULT(AUTOFS_IOC_EXPIRE) }; #define NR_IOCTL32_HANDLERS (sizeof(ioctl32_handler_table) / \ diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- v2.4.0-test11/linux/arch/mips64/kernel/linux32.c Sun Nov 19 18:44:03 2000 +++ linux/arch/mips64/kernel/linux32.c Tue Nov 28 21:42:04 2000 @@ -5,7 +5,6 @@ * Written by Ulf Carlsson (ulfc@engr.sgi.com) * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com) */ - #include #include #include @@ -22,6 +21,13 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -176,6 +182,36 @@ return sys_ftruncate(fd, ((long) high << 32) | low); } +extern asmlinkage int sys_utime(char * filename, struct utimbuf * times); + +struct utimbuf32 { + __kernel_time_t32 actime, modtime; +}; + +asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times) +{ + struct utimbuf t; + mm_segment_t old_fs; + int ret; + char *filenam; + + if (!times) + return sys_utime(filename, NULL); + if (get_user (t.actime, ×->actime) || + __get_user (t.modtime, ×->modtime)) + return -EFAULT; + filenam = getname (filename); + ret = PTR_ERR(filenam); + if (!IS_ERR(filenam)) { + old_fs = get_fs(); + set_fs (KERNEL_DS); + ret = sys_utime(filenam, &t); + set_fs (old_fs); + putname (filenam); + } + return ret; +} + #if 0 /* * count32() counts the number of arguments/envelopes @@ -1005,6 +1041,72 @@ return ret; } +/* From the Single Unix Spec: pread & pwrite act like lseek to pos + op + + lseek back to original location. They fail just like lseek does on + non-seekable files. */ + +asmlinkage ssize_t sys32_pread(unsigned int fd, char * buf, + size_t count, u32 unused, loff_t pos) +{ + ssize_t ret; + struct file * file; + ssize_t (*read)(struct file *, char *, size_t, loff_t *); + + ret = -EBADF; + file = fget(fd); + if (!file) + goto bad_file; + if (!(file->f_mode & FMODE_READ)) + goto out; + ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode, + file, pos, count); + if (ret) + goto out; + ret = -EINVAL; + if (!file->f_op || !(read = file->f_op->read)) + goto out; + if (pos < 0) + goto out; + ret = read(file, buf, count, &pos); + if (ret > 0) + inode_dir_notify(file->f_dentry->d_parent->d_inode, DN_ACCESS); +out: + fput(file); +bad_file: + return ret; +} + +asmlinkage ssize_t sys32_pwrite(unsigned int fd, const char * buf, + size_t count, u32 unused, loff_t pos) +{ + ssize_t ret; + struct file * file; + ssize_t (*write)(struct file *, const char *, size_t, loff_t *); + + ret = -EBADF; + file = fget(fd); + if (!file) + goto bad_file; + if (!(file->f_mode & FMODE_WRITE)) + goto out; + ret = locks_verify_area(FLOCK_VERIFY_WRITE, file->f_dentry->d_inode, + file, pos, count); + if (ret) + goto out; + ret = -EINVAL; + if (!file->f_op || !(write = file->f_op->write)) + goto out; + if (pos < 0) + goto out; + + ret = write(file, buf, count, &pos); + if (ret > 0) + inode_dir_notify(file->f_dentry->d_parent->d_inode, DN_MODIFY); +out: + fput(file); +bad_file: + return ret; +} /* * Ooo, nasty. We need here to frob 32-bit unsigned longs to * 64-bit unsigned longs. @@ -1326,9 +1428,11 @@ return err; } -extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); +extern asmlinkage long +sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg); -asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) +asmlinkage long +sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg) { switch (cmd) { case F_GETLK: @@ -1339,12 +1443,12 @@ mm_segment_t old_fs; long ret; - if(get_flock(&f, (struct flock32 *)arg)) + if (get_flock(&f, (struct flock32 *)arg)) return -EFAULT; old_fs = get_fs(); set_fs (KERNEL_DS); ret = sys_fcntl(fd, cmd, (unsigned long)&f); set_fs (old_fs); - if(put_flock(&f, (struct flock32 *)arg)) + if (put_flock(&f, (struct flock32 *)arg)) return -EFAULT; return ret; } @@ -1353,6 +1457,21 @@ } } +asmlinkage long +sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case F_GETLK64: + return sys_fcntl(fd, F_GETLK, arg); + case F_SETLK64: + return sys_fcntl(fd, F_SETLK, arg); + case F_SETLKW64: + return sys_fcntl(fd, F_SETLKW, arg); + } + + return sys32_fcntl(fd, cmd, arg); +} + struct msgbuf32 { s32 mtype; char mtext[1]; }; struct ipc_perm32 @@ -1762,3 +1881,454 @@ return err; } +struct sysctl_args32 +{ + __kernel_caddr_t32 name; + int nlen; + __kernel_caddr_t32 oldval; + __kernel_caddr_t32 oldlenp; + __kernel_caddr_t32 newval; + __kernel_size_t32 newlen; + unsigned int __unused[4]; +}; + +asmlinkage long sys32_sysctl(struct sysctl_args32 *uargs32) +{ + struct __sysctl_args kargs; + struct sysctl_args32 kargs32; + mm_segment_t old_fs; + int name[CTL_MAXNAME]; + size_t oldlen[1]; + int err, ret; + + ret = -EFAULT; + + memset(&kargs, 0, sizeof (kargs)); + + err = get_user(kargs32.name, &uargs32->name); + err |= __get_user(kargs32.nlen, &uargs32->nlen); + err |= __get_user(kargs32.oldval, &uargs32->oldval); + err |= __get_user(kargs32.oldlenp, &uargs32->oldlenp); + err |= __get_user(kargs32.newval, &uargs32->newval); + err |= __get_user(kargs32.newlen, &uargs32->newlen); + if (err) + goto out; + + if (kargs32.nlen == 0 || kargs32.nlen >= CTL_MAXNAME) { + ret = -ENOTDIR; + goto out; + } + + kargs.name = name; + kargs.nlen = kargs32.nlen; + if (copy_from_user(kargs.name, (int *)A(kargs32.name), + kargs32.nlen * sizeof(name) / sizeof(name[0]))) + goto out; + + if (kargs32.oldval) { + if (!kargs32.oldlenp || get_user(oldlen[0], + (int *)A(kargs32.oldlenp))) + return -EFAULT; + kargs.oldlenp = oldlen; + kargs.oldval = kmalloc(oldlen[0], GFP_KERNEL); + if (!kargs.oldval) { + ret = -ENOMEM; + goto out; + } + } + + if (kargs32.newval && kargs32.newlen) { + kargs.newval = kmalloc(kargs32.newlen, GFP_KERNEL); + if (!kargs.newval) { + ret = -ENOMEM; + goto out; + } + if (copy_from_user(kargs.newval, (int *)A(kargs32.newval), + kargs32.newlen)) + goto out; + } + + old_fs = get_fs(); set_fs (KERNEL_DS); + ret = sys_sysctl(&kargs); + set_fs (old_fs); + + if (ret) + goto out; + + if (kargs.oldval) { + if (put_user(oldlen[0], (int *)A(kargs32.oldlenp)) || + copy_to_user((int *)A(kargs32.oldval), kargs.oldval, + oldlen[0])) + ret = -EFAULT; + } +out: + if (kargs.oldval) + kfree(kargs.oldval); + if (kargs.newval) + kfree(kargs.newval); + return ret; +} + +asmlinkage long sys32_newuname(struct new_utsname * name) +{ + int ret = 0; + + down_read(&uts_sem); + if (copy_to_user(name,&system_utsname,sizeof *name)) + ret = -EFAULT; + up_read(&uts_sem); + + if (current->personality == PER_LINUX32 && !ret) + if (copy_to_user(name->machine, "mips\0\0\0", 8)) + ret = -EFAULT; + + return ret; +} + +extern asmlinkage long sys_personality(unsigned long); + +asmlinkage int sys32_personality(unsigned long personality) +{ + int ret; + if (current->personality == PER_LINUX32 && personality == PER_LINUX) + personality = PER_LINUX32; + ret = sys_personality(personality); + if (ret == PER_LINUX32) + ret = PER_LINUX; + return ret; +} + +/* Handle adjtimex compatability. */ + +struct timex32 { + u32 modes; + s32 offset, freq, maxerror, esterror; + s32 status, constant, precision, tolerance; + struct timeval32 time; + s32 tick; + s32 ppsfreq, jitter, shift, stabil; + s32 jitcnt, calcnt, errcnt, stbcnt; + s32 :32; s32 :32; s32 :32; s32 :32; + s32 :32; s32 :32; s32 :32; s32 :32; + s32 :32; s32 :32; s32 :32; s32 :32; +}; + +extern int do_adjtimex(struct timex *); + +asmlinkage int sys32_adjtimex(struct timex32 *utp) +{ + struct timex txc; + int ret; + + memset(&txc, 0, sizeof(struct timex)); + + if(get_user(txc.modes, &utp->modes) || + __get_user(txc.offset, &utp->offset) || + __get_user(txc.freq, &utp->freq) || + __get_user(txc.maxerror, &utp->maxerror) || + __get_user(txc.esterror, &utp->esterror) || + __get_user(txc.status, &utp->status) || + __get_user(txc.constant, &utp->constant) || + __get_user(txc.precision, &utp->precision) || + __get_user(txc.tolerance, &utp->tolerance) || + __get_user(txc.time.tv_sec, &utp->time.tv_sec) || + __get_user(txc.time.tv_usec, &utp->time.tv_usec) || + __get_user(txc.tick, &utp->tick) || + __get_user(txc.ppsfreq, &utp->ppsfreq) || + __get_user(txc.jitter, &utp->jitter) || + __get_user(txc.shift, &utp->shift) || + __get_user(txc.stabil, &utp->stabil) || + __get_user(txc.jitcnt, &utp->jitcnt) || + __get_user(txc.calcnt, &utp->calcnt) || + __get_user(txc.errcnt, &utp->errcnt) || + __get_user(txc.stbcnt, &utp->stbcnt)) + return -EFAULT; + + ret = do_adjtimex(&txc); + + if(put_user(txc.modes, &utp->modes) || + __put_user(txc.offset, &utp->offset) || + __put_user(txc.freq, &utp->freq) || + __put_user(txc.maxerror, &utp->maxerror) || + __put_user(txc.esterror, &utp->esterror) || + __put_user(txc.status, &utp->status) || + __put_user(txc.constant, &utp->constant) || + __put_user(txc.precision, &utp->precision) || + __put_user(txc.tolerance, &utp->tolerance) || + __put_user(txc.time.tv_sec, &utp->time.tv_sec) || + __put_user(txc.time.tv_usec, &utp->time.tv_usec) || + __put_user(txc.tick, &utp->tick) || + __put_user(txc.ppsfreq, &utp->ppsfreq) || + __put_user(txc.jitter, &utp->jitter) || + __put_user(txc.shift, &utp->shift) || + __put_user(txc.stabil, &utp->stabil) || + __put_user(txc.jitcnt, &utp->jitcnt) || + __put_user(txc.calcnt, &utp->calcnt) || + __put_user(txc.errcnt, &utp->errcnt) || + __put_user(txc.stbcnt, &utp->stbcnt)) + ret = -EFAULT; + + return ret; +} + +/* + * Declare the 32-bit version of the msghdr + */ + +struct msghdr32 { + unsigned int msg_name; /* Socket name */ + int msg_namelen; /* Length of name */ + unsigned int msg_iov; /* Data blocks */ + unsigned int msg_iovlen; /* Number of blocks */ + unsigned int msg_control; /* Per protocol magic (eg BSD file descriptor passing) */ + unsigned int msg_controllen; /* Length of cmsg list */ + unsigned msg_flags; +}; + +static inline int +shape_msg(struct msghdr *mp, struct msghdr32 *mp32) +{ + int ret; + unsigned int i; + + if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) + return(-EFAULT); + ret = __get_user(i, &mp32->msg_name); + mp->msg_name = (void *)A(i); + ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); + ret |= __get_user(i, &mp32->msg_iov); + mp->msg_iov = (struct iovec *)A(i); + ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); + ret |= __get_user(i, &mp32->msg_control); + mp->msg_control = (void *)A(i); + ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); + ret |= __get_user(mp->msg_flags, &mp32->msg_flags); + return(ret ? -EFAULT : 0); +} + +/* + * Verify & re-shape IA32 iovec. The caller must ensure that the + * iovec is big enough to hold the re-shaped message iovec. + * + * Save time not doing verify_area. copy_*_user will make this work + * in any case. + * + * Don't need to check the total size for overflow (cf net/core/iovec.c), + * 32-bit sizes can't overflow a 64-bit count. + */ + +static inline int +verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode) +{ + int size, err, ct; + struct iovec32 *iov32; + + if(m->msg_namelen) + { + if(mode==VERIFY_READ) + { + err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); + if(err<0) + goto out; + } + + m->msg_name = address; + } else + m->msg_name = NULL; + + err = -EFAULT; + size = m->msg_iovlen * sizeof(struct iovec32); + if (copy_from_user(iov, m->msg_iov, size)) + goto out; + m->msg_iov=iov; + + err = 0; + iov32 = (struct iovec32 *)iov; + for (ct = m->msg_iovlen; ct-- > 0; ) { + iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; + iov[ct].iov_base = (void *) A(iov32[ct].iov_base); + err += iov[ct].iov_len; + } +out: + return err; +} + +extern __inline__ void +sockfd_put(struct socket *sock) +{ + fput(sock->file); +} + +/* XXX This really belongs in some header file... -DaveM */ +#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - + 16 for IP, 16 for IPX, + 24 for IPv6, + about 80 for AX.25 */ + +extern struct socket *sockfd_lookup(int fd, int *err); + +/* + * BSD sendmsg interface + */ + +int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) +{ + struct socket *sock; + char address[MAX_SOCK_ADDR]; + struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; + unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ + unsigned char *ctl_buf = ctl; + struct msghdr msg_sys; + int err, ctl_len, iov_size, total_len; + + err = -EFAULT; + if (shape_msg(&msg_sys, msg)) + goto out; + + sock = sockfd_lookup(fd, &err); + if (!sock) + goto out; + + /* do not move before msg_sys is valid */ + err = -EINVAL; + if (msg_sys.msg_iovlen > UIO_MAXIOV) + goto out_put; + + /* Check whether to allocate the iovec area*/ + err = -ENOMEM; + iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); + if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); + if (!iov) + goto out_put; + } + + /* This will also move the address data into kernel space */ + err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); + if (err < 0) + goto out_freeiov; + total_len = err; + + err = -ENOBUFS; + + if (msg_sys.msg_controllen > INT_MAX) + goto out_freeiov; + ctl_len = msg_sys.msg_controllen; + if (ctl_len) + { + if (ctl_len > sizeof(ctl)) + { + err = -ENOBUFS; + ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); + if (ctl_buf == NULL) + goto out_freeiov; + } + err = -EFAULT; + if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len)) + goto out_freectl; + msg_sys.msg_control = ctl_buf; + } + msg_sys.msg_flags = flags; + + if (sock->file->f_flags & O_NONBLOCK) + msg_sys.msg_flags |= MSG_DONTWAIT; + err = sock_sendmsg(sock, &msg_sys, total_len); + +out_freectl: + if (ctl_buf != ctl) + sock_kfree_s(sock->sk, ctl_buf, ctl_len); +out_freeiov: + if (iov != iovstack) + sock_kfree_s(sock->sk, iov, iov_size); +out_put: + sockfd_put(sock); +out: + return err; +} + +/* + * BSD recvmsg interface + */ + +int +sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) +{ + struct socket *sock; + struct iovec iovstack[UIO_FASTIOV]; + struct iovec *iov=iovstack; + struct msghdr msg_sys; + unsigned long cmsg_ptr; + int err, iov_size, total_len, len; + + /* kernel mode address */ + char addr[MAX_SOCK_ADDR]; + + /* user mode address pointers */ + struct sockaddr *uaddr; + int *uaddr_len; + + err=-EFAULT; + if (shape_msg(&msg_sys, msg)) + goto out; + + sock = sockfd_lookup(fd, &err); + if (!sock) + goto out; + + err = -EINVAL; + if (msg_sys.msg_iovlen > UIO_MAXIOV) + goto out_put; + + /* Check whether to allocate the iovec area*/ + err = -ENOMEM; + iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); + if (msg_sys.msg_iovlen > UIO_FASTIOV) { + iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); + if (!iov) + goto out_put; + } + + /* + * Save the user-mode address (verify_iovec will change the + * kernel msghdr to use the kernel address space) + */ + + uaddr = msg_sys.msg_name; + uaddr_len = &msg->msg_namelen; + err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); + if (err < 0) + goto out_freeiov; + total_len=err; + + cmsg_ptr = (unsigned long)msg_sys.msg_control; + msg_sys.msg_flags = 0; + + if (sock->file->f_flags & O_NONBLOCK) + flags |= MSG_DONTWAIT; + err = sock_recvmsg(sock, &msg_sys, total_len, flags); + if (err < 0) + goto out_freeiov; + len = err; + + if (uaddr != NULL) { + err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); + if (err < 0) + goto out_freeiov; + } + err = __put_user(msg_sys.msg_flags, &msg->msg_flags); + if (err) + goto out_freeiov; + err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, + &msg->msg_controllen); + if (err) + goto out_freeiov; + err = len; + +out_freeiov: + if (iov != iovstack) + sock_kfree_s(sock->sk, iov, iov_size); +out_put: + sockfd_put(sock); +out: + return err; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/proc.c linux/arch/mips64/kernel/proc.c --- v2.4.0-test11/linux/arch/mips64/kernel/proc.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/kernel/proc.c Tue Nov 28 21:42:04 2000 @@ -26,50 +26,67 @@ * Currently /proc/cpuinfo is being abused to print data about the * number of date/instruction cacheflushes. */ -int get_cpuinfo(char *buffer) +int get_cpuinfo(char *buffer, char **start, off_t offset, int count) { char fmt [64]; - size_t len; + struct cpuinfo_mips *c = cpu_data; + size_t len = 0; + int n; - len = sprintf(buffer, "cpu\t\t\t: MIPS\n"); -#if 0 - len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n", + for (n = 0; n < smp_num_cpus; n++, c++) { + len += sprintf(buffer + len, "processor\t\t: %d\n", n); + len += sprintf(buffer + len, "vendor_id\t\t: MIPS\n"); + len += sprintf(buffer + len, "model name\t\t: R10000\n"); +/* len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n", cpu_name[mips_cputype <= CPU_LAST ? mips_cputype : CPU_UNKNOWN], (version >> 4) & 0x0f, version & 0x0f); - len += sprintf(buffer + len, "system type\t\t: %s %s\n", + len += sprintf(buffer + len, "system type\t\t: %s %s\n", mach_group_names[mips_machgroup], mach_group_to_name[mips_machgroup][mips_machtype]); -#endif - len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", +*/ + len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n", (loops_per_sec + 2500) / 500000, ((loops_per_sec + 2500) / 5000) % 100); - len += sprintf(buffer + len, "Number of cpus\t\t: %d\n", smp_num_cpus); +/* len += sprintf(buffer + len, "Number of cpus\t\t: %d\n", smp_num_cpus);*/ #if defined (__MIPSEB__) - len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); + len += sprintf(buffer + len, "byteorder\t\t: big endian\n"); #endif #if defined (__MIPSEL__) - len += sprintf(buffer + len, "byteorder\t\t: little endian\n"); + len += sprintf(buffer + len, "byteorder\t\t: little endian\n"); #endif - len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", + len += sprintf(buffer + len, "unaligned accesses\t: %lu\n", unaligned_instructions); - len += sprintf(buffer + len, "wait instruction\t: %s\n", + len += sprintf(buffer + len, "wait instruction\t: %s\n", wait_available ? "yes" : "no"); - len += sprintf(buffer + len, "microsecond timers\t: %s\n", + len += sprintf(buffer + len, "microsecond timers\t: %s\n", cyclecounter_available ? "yes" : "no"); - len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", + len += sprintf(buffer + len, "extra interrupt vector\t: %s\n", dedicated_iv_available ? "yes" : "no"); - len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", + len += sprintf(buffer + len, "hardware watchpoint\t: %s\n", watch_available ? "yes" : "no"); - sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", + sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", vce_available ? "%d" : "not available"); - len += sprintf(buffer + len, fmt, 'D', vced_count); - len += sprintf(buffer + len, fmt, 'I', vcei_count); + len += sprintf(buffer + len, fmt, 'D', vced_count); + len += sprintf(buffer + len, fmt, 'I', vcei_count); + len += sprintf(buffer + len, "\n"); + + if (len < offset) + offset -= len, len = 0; + else if (len >= offset + count) + goto leave_loop; + } + +leave_loop: + *start = buffer + offset; + len -= offset; + if (len < 0) + len = 0; + return len > count ? count : len; - return len; } void init_irq_proc(void) diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c --- v2.4.0-test11/linux/arch/mips64/kernel/process.c Tue Sep 5 13:50:01 2000 +++ linux/arch/mips64/kernel/process.c Tue Nov 28 21:42:04 2000 @@ -186,28 +186,51 @@ #define first_sched ((unsigned long) scheduling_functions_start_here) #define last_sched ((unsigned long) scheduling_functions_end_here) +/* get_wchan - a maintenance nightmare ... */ unsigned long get_wchan(struct task_struct *p) { - unsigned long schedule_frame; - unsigned long pc; + unsigned long frame, pc; if (!p || p == current || p->state == TASK_RUNNING) return 0; pc = thread_saved_pc(&p->thread); - if (pc == (unsigned long) interruptible_sleep_on - || pc == (unsigned long) sleep_on) { - schedule_frame = ((unsigned long *)p->thread.reg30)[9]; - return ((unsigned long *)schedule_frame)[15]; - } - if (pc == (unsigned long) interruptible_sleep_on_timeout - || pc == (unsigned long) sleep_on_timeout) { - schedule_frame = ((unsigned long *)p->thread.reg30)[9]; - return ((unsigned long *)schedule_frame)[16]; - } + if (pc < first_sched || pc >= last_sched) + goto out; + + if (pc >= (unsigned long) sleep_on_timeout) + goto schedule_timeout_caller; + if (pc >= (unsigned long) sleep_on) + goto schedule_caller; + if (pc >= (unsigned long) interruptible_sleep_on_timeout) + goto schedule_timeout_caller; + if (pc >= (unsigned long)interruptible_sleep_on) + goto schedule_caller; + goto schedule_timeout_caller; + +schedule_caller: + frame = ((unsigned long *)p->thread.reg30)[10]; + pc = ((unsigned long *)frame)[7]; + goto out; + +schedule_timeout_caller: + /* Must be schedule_timeout ... */ + pc = ((unsigned long *)p->thread.reg30)[11]; + frame = ((unsigned long *)p->thread.reg30)[10]; + + /* The schedule_timeout frame ... */ + pc = ((unsigned long *)frame)[9]; + frame = ((unsigned long *)frame)[8]; + if (pc >= first_sched && pc < last_sched) { - printk(KERN_DEBUG "Bug in %s\n", __FUNCTION__); + /* schedule_timeout called by interruptible_sleep_on_timeout */ + pc = ((unsigned long *)frame)[7]; + frame = ((unsigned long *)frame)[6]; } + +out: + if (current->thread.mflags & MF_32BIT) /* Kludge for 32-bit ps */ + pc &= 0xffffffff; return pc; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/ptrace.c linux/arch/mips64/kernel/ptrace.c --- v2.4.0-test11/linux/arch/mips64/kernel/ptrace.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/kernel/ptrace.c Tue Nov 28 21:42:04 2000 @@ -5,7 +5,7 @@ * * Copyright (C) 1992 Ross Biro * Copyright (C) Linus Torvalds - * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle + * Copyright (C) 1994, 95, 96, 97, 98, 2000 Ralf Baechle * Copyright (C) 1996 David S. Miller * Copyright (C) 2000 Ulf Carlsson * @@ -268,7 +268,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); + child->ptrace = 0; child->exit_code = data; write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); @@ -280,6 +280,15 @@ break; } + case PTRACE_SETOPTIONS: { + if (data & PTRACE_O_TRACESYSGOOD) + child->ptrace |= PT_TRACESYSGOOD; + else + child->ptrace &= ~PT_TRACESYSGOOD; + ret = 0; + break; + } + default: ret = -EIO; break; @@ -534,7 +543,7 @@ ret = -EIO; if ((unsigned long) data > _NSIG) break; - child->ptrace &= ~(PT_PTRACED|PT_TRACESYS); + child->ptrace = 0; child->exit_code = data; write_lock_irq(&tasklist_lock); REMOVE_LINKS(child); @@ -546,6 +555,15 @@ break; } + case PTRACE_SETOPTIONS: { + if (data & PTRACE_O_TRACESYSGOOD) + child->ptrace |= PT_TRACESYSGOOD; + else + child->ptrace &= ~PT_TRACESYSGOOD; + ret = 0; + break; + } + default: ret = -EIO; break; @@ -564,7 +582,10 @@ != (PT_PTRACED|PT_TRACESYS)) return; - current->exit_code = SIGTRAP; + /* The 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) + ? 0x80 : 0); current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/scall_64.S linux/arch/mips64/kernel/scall_64.S --- v2.4.0-test11/linux/arch/mips64/kernel/scall_64.S Fri Aug 11 14:29:05 2000 +++ linux/arch/mips64/kernel/scall_64.S Tue Nov 28 21:42:04 2000 @@ -190,7 +190,7 @@ PTR sys_ni_syscall PTR sys_setpgid PTR sys_ni_syscall - PTR sys_olduname + PTR sys_ni_syscall PTR sys_umask /* 4060 */ PTR sys_chroot PTR sys_ustat @@ -220,7 +220,7 @@ PTR sys_uselib PTR sys_swapon PTR sys_reboot - PTR old_readdir + PTR sys_ni_syscall /* old_readdir */ PTR sys_mmap /* 4090 */ PTR sys_munmap PTR sys_truncate @@ -240,7 +240,7 @@ PTR sys_newstat PTR sys_newlstat PTR sys_newfstat - PTR sys_uname + PTR sys_ni_syscall PTR sys_ni_syscall /* sys_ioperm *//* 4110 */ PTR sys_vhangup PTR sys_ni_syscall /* was sys_idle */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/scall_o32.S linux/arch/mips64/kernel/scall_o32.S --- v2.4.0-test11/linux/arch/mips64/kernel/scall_o32.S Fri Aug 11 14:29:05 2000 +++ linux/arch/mips64/kernel/scall_o32.S Tue Nov 28 21:42:04 2000 @@ -231,7 +231,7 @@ sys sys32_alarm 1 sys sys_fstat 2 sys sys_pause 0 - sys sys_utime 2 /* 4030 */ + sys sys32_utime 2 /* 4030 */ sys sys_ni_syscall 0 sys sys_ni_syscall 0 sys sys_access 2 @@ -260,7 +260,7 @@ sys sys_ni_syscall 2 sys sys_setpgid 2 sys sys_ni_syscall, 0 - sys sys_olduname 1 + sys sys_ni_syscall 0 /* was sys_olduname */ sys sys_umask 1 /* 4060 */ sys sys_chroot 1 sys sys_ustat 2 @@ -310,7 +310,7 @@ sys sys32_newstat 2 sys sys32_newlstat 2 sys sys32_newfstat 2 - sys sys_uname 1 + sys sys_ni_syscall 0 /* was sys_uname */ sys sys_ni_syscall 0 /* sys_ioperm *//* 4110 */ sys sys_vhangup 0 sys sys_ni_syscall 0 /* was sys_idle */ @@ -323,9 +323,9 @@ sys sys32_sigreturn 0 sys sys_clone 0 /* 4120 */ sys sys_setdomainname 2 - sys sys_newuname 1 + sys sys32_newuname 1 sys sys_ni_syscall 0 /* sys_modify_ldt */ - sys sys_adjtimex 1 + sys sys32_adjtimex 1 sys sys_mprotect 3 /* 4125 */ sys sys32_sigprocmask 3 sys sys_create_module 2 @@ -337,7 +337,7 @@ sys sys_fchdir 1 sys sys_bdflush 2 sys sys_sysfs 3 /* 4135 */ - sys sys_personality 1 + sys sys32_personality 1 sys sys_ni_syscall 0 /* for afs_syscall */ sys sys_setfsuid 1 sys sys_setfsgid 1 @@ -354,7 +354,7 @@ sys sys_ni_syscall 0 /* 4150 */ sys sys_getsid 1 sys sys_fdatasync 0 - sys sys_sysctl 1 + sys sys32_sysctl 1 sys sys_mlock 2 sys sys_munlock 2 /* 4155 */ sys sys_mlockall 1 @@ -378,9 +378,9 @@ sys sys_listen 2 sys sys_recv 4 /* 4175 */ sys sys_recvfrom 6 - sys sys_recvmsg 3 + sys sys32_recvmsg 3 sys sys_send 4 - sys sys_sendmsg 3 + sys sys32_sendmsg 3 sys sys_sendto 6 /* 4180 */ sys sys32_setsockopt 5 sys sys_shutdown 2 @@ -401,8 +401,8 @@ sys sys32_rt_sigtimedwait 4 sys sys32_rt_sigqueueinfo 3 sys sys32_rt_sigsuspend 0 - sys sys_pread 4 /* 4200 */ - sys sys_pwrite 4 + sys sys32_pread 6 /* 4200 */ + sys sys32_pwrite 6 sys sys_chown 3 sys sys_getcwd 2 sys sys_capget 2 @@ -414,13 +414,14 @@ sys sys_mmap2 6 /* 4210 */ sys sys_truncate64 2 sys sys_ftruncate64 2 - sys sys_newstat 3 - sys sys_newlstat 3 - sys sys_newfstat 3 /* 4210 */ + sys sys_newstat 2 + sys sys_newlstat 2 + sys sys_newfstat 2 /* 4215 */ sys sys_pivot_root 2 sys sys_mincore 3 sys sys_madvise 3 sys sys_getdents64 3 + sys sys32_fcntl64 3 /* 4220 */ .endm .macro sys function, nargs diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/setup.c linux/arch/mips64/kernel/setup.c --- v2.4.0-test11/linux/arch/mips64/kernel/setup.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/kernel/setup.c Tue Nov 28 21:42:04 2000 @@ -1,5 +1,4 @@ -/* $Id: setup.c,v 1.9 2000/03/14 01:39:27 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -36,11 +35,6 @@ #include #include #include - -#ifdef CONFIG_SGI_IP27 -/* XXX Origin garbage has no business in this file */ -#include -#endif #ifndef CONFIG_SMP struct cpuinfo_mips cpu_data[1]; diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c --- v2.4.0-test11/linux/arch/mips64/kernel/signal32.c Sun Sep 3 11:53:42 2000 +++ linux/arch/mips64/kernel/signal32.c Tue Nov 28 21:42:04 2000 @@ -60,7 +60,7 @@ /* IRIX compatible stack_t */ typedef struct sigaltstack32 { - void *ss_sp; + s32 ss_sp; __kernel_size_t32 ss_size; int ss_flags; } stack32_t; @@ -272,11 +272,13 @@ stack_t kss, koss; int ret, err = 0; mm_segment_t old_fs = get_fs(); + s32 sp; if (uss) { if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) return -EFAULT; - err |= __get_user(kss.ss_sp, &uss->ss_sp); + err |= __get_user(sp, &uss->ss_sp); + kss.ss_size = (long) sp; err |= __get_user(kss.ss_size, &uss->ss_size); err |= __get_user(kss.ss_flags, &uss->ss_flags); if (err) @@ -290,7 +292,8 @@ if (!ret && uoss) { if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) return -EFAULT; - err |= __put_user(koss.ss_sp, &uoss->ss_sp); + sp = (int) (long) koss.ss_sp; + err |= __put_user(sp, &uoss->ss_sp); err |= __put_user(koss.ss_size, &uoss->ss_size); err |= __put_user(koss.ss_flags, &uoss->ss_flags); if (err) @@ -879,12 +882,12 @@ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) return -EFAULT; - err |= __put_user((u32)(u64)new_sa.sa.sa_handler, + err |= __put_user((u32)(u64)old_sa.sa.sa_handler, &oact->sa_handler); - err |= __put_user(new_sa.sa.sa_flags, &oact->sa_flags); - err |= __put_user((u32)(u64)new_sa.sa.sa_restorer, + err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags); + err |= __put_user((u32)(u64)old_sa.sa.sa_restorer, &oact->sa_restorer); - err |= put_sigset(&new_sa.sa.sa_mask, &oact->sa_mask); + err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask); if (err) return -EFAULT; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c --- v2.4.0-test11/linux/arch/mips64/kernel/smp.c Tue Oct 31 12:42:26 2000 +++ linux/arch/mips64/kernel/smp.c Tue Nov 28 21:42:04 2000 @@ -168,7 +168,7 @@ return 0; } -void smp_call_function_interrupt(void) +extern void smp_call_function_interrupt(int irq, void *d, struct pt_regs *r) { void (*func) (void *info) = call_data->func; void *info = call_data->info; @@ -205,9 +205,29 @@ _flush_tlb_mm((struct mm_struct *)mm); } +/* + * The following tlb flush calls are invoked when old translations are + * being torn down, or pte attributes are changing. For single threaded + * address spaces, a new context is obtained on the current cpu, and tlb + * context on other cpus are invalidated to force a new context allocation + * at switch_mm time, should the mm ever be used on other cpus. For + * multithreaded address spaces, intercpu interrupts have to be sent. + * Another case where intercpu interrupts are required is when the target + * mm might be active on another cpu (eg debuggers doing the flushes on + * behalf of debugees, kswapd stealing pages from another process etc). + * Kanoj 07/00. + */ + void flush_tlb_mm(struct mm_struct *mm) { - smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1); + if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { + smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1); + } else { + int i; + for (i = 0; i < smp_num_cpus; i++) + if (smp_processor_id() != i) + CPU_CONTEXT(i, mm) = 0; + } _flush_tlb_mm(mm); } @@ -227,12 +247,19 @@ void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end) { - struct flush_tlb_data fd; + if ((atomic_read(&mm->mm_users) != 1) || (current->mm != mm)) { + struct flush_tlb_data fd; - fd.mm = mm; - fd.addr1 = start; - fd.addr2 = end; - smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1); + fd.mm = mm; + fd.addr1 = start; + fd.addr2 = end; + smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1); + } else { + int i; + for (i = 0; i < smp_num_cpus; i++) + if (smp_processor_id() != i) + CPU_CONTEXT(i, mm) = 0; + } _flush_tlb_range(mm, start, end); } @@ -245,11 +272,18 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) { - struct flush_tlb_data fd; + if ((atomic_read(&vma->vm_mm->mm_users) != 1) || (current->mm != vma->vm_mm)) { + struct flush_tlb_data fd; - fd.vma = vma; - fd.addr1 = page; - smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1); + fd.vma = vma; + fd.addr1 = page; + smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1); + } else { + int i; + for (i = 0; i < smp_num_cpus; i++) + if (smp_processor_id() != i) + CPU_CONTEXT(i, vma->vm_mm) = 0; + } _flush_tlb_page(vma, page); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/syscall.c linux/arch/mips64/kernel/syscall.c --- v2.4.0-test11/linux/arch/mips64/kernel/syscall.c Tue Sep 5 13:50:01 2000 +++ linux/arch/mips64/kernel/syscall.c Tue Nov 28 21:42:04 2000 @@ -31,6 +31,8 @@ #include #include +extern asmlinkage void syscall_trace(void); + asmlinkage int sys_pipe(abi64_no_regargs, struct pt_regs regs) { int fd[2]; @@ -117,43 +119,6 @@ } /* - * Compacrapability ... - */ -asmlinkage int sys_uname(struct old_utsname * name) -{ - if (name && !copy_to_user(name, &system_utsname, sizeof (*name))) - return 0; - return -EFAULT; -} - -/* - * Compacrapability ... - */ -asmlinkage int sys_olduname(struct oldold_utsname * name) -{ - int error; - - if (!name) - return -EFAULT; - if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) - return -EFAULT; - - error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN); - error -= __put_user(0,name->sysname+__OLD_UTS_LEN); - error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN); - error -= __put_user(0,name->nodename+__OLD_UTS_LEN); - error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN); - error -= __put_user(0,name->release+__OLD_UTS_LEN); - error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN); - error -= __put_user(0,name->version+__OLD_UTS_LEN); - error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN); - error = __put_user(0,name->machine+__OLD_UTS_LEN); - error = error ? -EFAULT : 0; - - return error; -} - -/* * Do the indirect syscall syscall. * * XXX This is borken. @@ -168,7 +133,7 @@ { int *p; char *name; - int flags, tmp, len, errno; + int tmp, len, errno; switch(cmd) { case SETNAME: { @@ -191,8 +156,6 @@ } case MIPS_ATOMIC_SET: { - /* This is broken in case of page faults and SMP ... - Risc/OS faults after maximum 20 tries with EAGAIN. */ unsigned int tmp; p = (int *) arg1; @@ -200,15 +163,41 @@ if (errno) return errno; errno = 0; - save_and_cli(flags); - errno |= __get_user(tmp, p); - errno |= __put_user(arg2, p); - restore_flags(flags); + + __asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t" + ".set\tnoreorder\n\t" + ".set\tnoat\n\t" + "1:\tll\t%0, %4\n\t" + "2:\tmove\t$1, %3\n\t" + "3:\tsc\t$1, %1\n\t" + "beqzl\t$1, 2b\n\t" + "4:\t ll\t%0, %4\n\t" + ".set\tpop\n\t" + ".section\t.fixup,\"ax\"\n" + "5:\tli\t%2, 1\t\t\t# error\n\t" + ".previous\n\t" + ".section\t__ex_table,\"a\"\n\t" + ".dword\t1b, 5b\n\t" + ".dword\t3b, 5b\n\t" + ".dword\t4b, 5b\n\t" + ".previous\n\t" + : "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno) + : "r" (arg2), "o" (* (u32 *) p), "2" (errno) + : "$1"); if (errno) - return tmp; + return -EFAULT; - return tmp; /* This is broken ... */ + /* We're skipping error handling etc. */ + if (current->ptrace & PT_TRACESYS) + syscall_trace(); + + __asm__ __volatile__( + "move\t$29, %0\n\t" + "j\tret_from_sys_call" + : /* No outputs */ + : "r" (&cmd)); + /* Unreached */ } case MIPS_FIXADE: @@ -217,7 +206,7 @@ return 0; case FLUSH_CACHE: - flush_cache_l1(); + _flush_cache_l2(); return 0; case MIPS_RDNVRAM: diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/traps.c linux/arch/mips64/kernel/traps.c --- v2.4.0-test11/linux/arch/mips64/kernel/traps.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/kernel/traps.c Sun Dec 3 17:48:19 2000 @@ -27,19 +27,6 @@ #include #include -extern int console_loglevel; - -static inline void console_silent(void) -{ - console_loglevel = 0; -} - -static inline void console_verbose(void) -{ - if (console_loglevel) - console_loglevel = 15; -} - extern asmlinkage void __xtlb_mod(void); extern asmlinkage void __xtlb_tlbl(void); extern asmlinkage void __xtlb_tlbs(void); diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/kernel/unaligned.c linux/arch/mips64/kernel/unaligned.c --- v2.4.0-test11/linux/arch/mips64/kernel/unaligned.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/kernel/unaligned.c Tue Nov 28 21:42:04 2000 @@ -1,5 +1,4 @@ -/* $Id: unaligned.c,v 1.2 1999/11/23 17:12:50 ralf Exp $ - * +/* * Handle unaligned accesses by emulation. * * This file is subject to the terms and conditions of the GNU General Public @@ -91,8 +90,8 @@ * User code may only access USEG; kernel code may access the * entire address space. */ -#define check_axs(p,a,s) \ - if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ +#define check_axs(pc,a,s) \ + if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \ goto sigbus; static inline void diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/ld.script.elf32 linux/arch/mips64/ld.script.elf32 --- v2.4.0-test11/linux/arch/mips64/ld.script.elf32 Wed Jul 12 15:14:41 2000 +++ linux/arch/mips64/ld.script.elf32 Wed Dec 31 16:00:00 1969 @@ -1,112 +0,0 @@ -OUTPUT_ARCH(mips) -ENTRY(kernel_entry) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - .init : { *(.init) } =0 - .text : - { - *(.text) - *(.rodata) - *(.rodata1) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - } =0 - _etext = .; - - . = ALIGN(16384); - /* This for CONFIG_MAPPED_KERNEL . = . + 16777216; */ - .data.init_task : { *(.data.init_task) } - - /* Startup code */ - . = ALIGN(4096); - __init_begin = .; - .text.init : { *(.text.init) } - .data.init : { *(.data.init) } - . = ALIGN(16); - __setup_start = .; - .setup.init : { *(.setup.init) } - __setup_end = .; - __initcall_start = .; - .initcall.init : { *(.initcall.init) } - __initcall_end = .; - . = ALIGN(4096); /* Align double page for init_task_union */ - __init_end = .; - - . = ALIGN(4096); - .data.page_aligned : { *(.data.idt) } - - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - - .fini : { *(.fini) } =0 - .reginfo : { *(.reginfo) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. It would - be more correct to do this: - . = .; - The current expression does not correctly handle the case of a - text segment ending precisely at the end of a page; it causes the - data segment to skip a page. The above expression does not have - this problem, but it will currently (2/95) cause BFD to allocate - a single segment, combining both text and data, for this case. - This will prevent the text segment from being shared among - multiple executions of the program; I think that is more - important than losing a page of the virtual address space (note - that no actual memory is lost; the page which is skipped can not - be referenced). */ - . = .; - .data : - { - _fdata = . ; - *(.data) - CONSTRUCTORS - } - .data1 : { *(.data1) } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - .ctors : { *(.ctors) } - .dtors : { *(.dtors) } - .got : { *(.got.plt) *(.got) } - .dynamic : { *(.dynamic) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : { *(.sdata) } - _edata = .; - - .sbss : { *(.sbss) *(.scommon) } - .bss : - { - *(.dynbss) - *(.bss) - *(COMMON) - _end = . ; - } - - /* Sections to be discarded */ - /DISCARD/ : - { - *(.text.exit) - *(.data.exit) - *(.exitcall.exit) - } - - /* These are needed for ELF backends which have not yet been - converted to the new style linker. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - /* DWARF debug sections. - Symbols in the .debug DWARF section are relative to the beginning of the - section so we begin .debug at 0. It's not clear yet what needs to happen - for the others. */ - .debug 0 : { *(.debug) } - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - .debug_sfnames 0 : { *(.debug_sfnames) } - .line 0 : { *(.line) } - /* These must appear regardless of . */ - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } -} diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/ld.script.elf32.S linux/arch/mips64/ld.script.elf32.S --- v2.4.0-test11/linux/arch/mips64/ld.script.elf32.S Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/ld.script.elf32.S Tue Nov 28 21:42:04 2000 @@ -0,0 +1,123 @@ +OUTPUT_ARCH(mips) +ENTRY(kernel_entry) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + .init : { *(.init) } =0 + .text : + { + *(.text) + *(.rodata) + *(.rodata1) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + } =0 + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___dbe_table = .; /* Exception table for data bus errors */ + __dbe_table : { *(__dbe_table) } + __stop___dbe_table = .; + + _etext = .; + + . = ALIGN(16384); + . = . + MAPPED_OFFSET; /* for CONFIG_MAPPED_KERNEL */ + .data.init_task : { *(.data.init_task) } + + /* Startup code */ + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + . = ALIGN(4096); /* Align double page for init_task_union */ + __init_end = .; + + . = ALIGN(4096); + .data.page_aligned : { *(.data.idt) } + + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + .fini : { *(.fini) } =0 + .reginfo : { *(.reginfo) } + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. It would + be more correct to do this: + . = .; + The current expression does not correctly handle the case of a + text segment ending precisely at the end of a page; it causes the + data segment to skip a page. The above expression does not have + this problem, but it will currently (2/95) cause BFD to allocate + a single segment, combining both text and data, for this case. + This will prevent the text segment from being shared among + multiple executions of the program; I think that is more + important than losing a page of the virtual address space (note + that no actual memory is lost; the page which is skipped can not + be referenced). */ + . = .; + .data : + { + _fdata = . ; + *(.data) + CONSTRUCTORS + } + .data1 : { *(.data1) } + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .got : { *(.got.plt) *(.got) } + .dynamic : { *(.dynamic) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : { *(.sdata) } + _edata = .; + + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + _end = . ; + } + + /* Sections to be discarded */ + /DISCARD/ : + { + *(.text.exit) + *(.data.exit) + *(.exitcall.exit) + } + + /* These are needed for ELF backends which have not yet been + converted to the new style linker. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + /* DWARF debug sections. + Symbols in the .debug DWARF section are relative to the beginning of the + section so we begin .debug at 0. It's not clear yet what needs to happen + for the others. */ + .debug 0 : { *(.debug) } + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + .debug_sfnames 0 : { *(.debug_sfnames) } + .line 0 : { *(.line) } + /* These must appear regardless of . */ + .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } + .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/ld.script.elf64 linux/arch/mips64/ld.script.elf64 --- v2.4.0-test11/linux/arch/mips64/ld.script.elf64 Wed Jul 12 15:14:41 2000 +++ linux/arch/mips64/ld.script.elf64 Tue Nov 28 21:42:04 2000 @@ -22,6 +22,17 @@ /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } = 0 + .kstrtab : { *(.kstrtab) } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___dbe_table = .; /* Exception table for data bus errors */ + __dbe_table : { *(__dbe_table) } + __stop___dbe_table = .; + _etext = .; . = ALIGN(16384); diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/lib/Makefile linux/arch/mips64/lib/Makefile --- v2.4.0-test11/linux/arch/mips64/lib/Makefile Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/Makefile Tue Dec 5 23:15:12 2000 @@ -1,4 +1,3 @@ -# $Id: Makefile,v 1.2 1999/11/19 20:35:22 ralf Exp $ # # Makefile for MIPS-specific library files.. # diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/lib/memcpy.S linux/arch/mips64/lib/memcpy.S --- v2.4.0-test11/linux/arch/mips64/lib/memcpy.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/memcpy.S Tue Dec 5 23:15:12 2000 @@ -1,13 +1,12 @@ -/* $Id: memcpy.S,v 1.2 1999/10/19 20:51:51 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Unified implementation of memcpy, memmove and the __copy_user backend. * - * Copyright (C) 1998, 1999 Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1998, 1999, 2000 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. * * For __rmemcpy and memmove an exception is always a kernel bug, therefore * they're not protected. In order to keep the exception fixup routine @@ -28,12 +27,20 @@ #define uswU swr #define ulwL lwl #define ulwU lwr +#define usdL sdl +#define usdU sdr +#define uldL ldl +#define uldU ldr #endif #ifdef __MIPSEL__ #define uswL swr #define uswU swl #define ulwL lwr #define ulwU lwl +#define usdL sdr +#define usdU sdl +#define uldL ldr +#define uldU ldl #endif #define EX(insn,reg,addr,handler) \ @@ -50,6 +57,33 @@ PTR 10b, handler; \ .previous +#define UEXD(insn,reg,addr,handler) \ +9: insn ## L reg, addr; \ +10: insn ## U reg, 7 + addr; \ + .section __ex_table,"a"; \ + PTR 9b, handler; \ + PTR 10b, handler; \ + .previous + +/* ascending order, destination aligned */ +#define MOVE_BIGGERCHUNK(src, dst, offset, t0, t1, t2, t3) \ + EX(ld, t0, (offset + 0x00)(src), l_fixup); \ + EX(ld, t1, (offset + 0x08)(src), l_fixup); \ + EX(ld, t2, (offset + 0x10)(src), l_fixup); \ + EX(ld, t3, (offset + 0x18)(src), l_fixup); \ + EX(sd, t0, (offset + 0x00)(dst), s_fixup); \ + EX(sd, t1, (offset + 0x08)(dst), s_fixup); \ + EX(sd, t2, (offset + 0x10)(dst), s_fixup); \ + EX(sd, t3, (offset + 0x18)(dst), s_fixup); \ + EX(ld, t0, (offset + 0x20)(src), l_fixup); \ + EX(ld, t1, (offset + 0x28)(src), l_fixup); \ + EX(ld, t2, (offset + 0x30)(src), l_fixup); \ + EX(ld, t3, (offset + 0x38)(src), l_fixup); \ + EX(sd, t0, (offset + 0x20)(dst), s_fixup); \ + EX(sd, t1, (offset + 0x28)(dst), s_fixup); \ + EX(sd, t2, (offset + 0x30)(dst), s_fixup); \ + EX(sd, t3, (offset + 0x38)(dst), s_fixup) + /* ascending order, destination aligned */ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ EX(lw, t0, (offset + 0x00)(src), l_fixup); \ @@ -70,6 +104,25 @@ EX(sw, t3, (offset + 0x1c)(dst), s_fixup) /* ascending order, destination unaligned */ +#define UMOVE_BIGGERCHUNK(src, dst, offset, t0, t1, t2, t3) \ + EX(ld, t0, (offset + 0x00)(src), l_fixup); \ + EX(ld, t1, (offset + 0x08)(src), l_fixup); \ + EX(ld, t2, (offset + 0x10)(src), l_fixup); \ + EX(ld, t3, (offset + 0x18)(src), l_fixup); \ + UEXD(usd, t0, (offset + 0x00)(dst), s_fixup); \ + UEXD(usd, t1, (offset + 0x08)(dst), s_fixup); \ + UEXD(usd, t2, (offset + 0x10)(dst), s_fixup); \ + UEXD(usd, t3, (offset + 0x18)(dst), s_fixup); \ + EX(ld, t0, (offset + 0x20)(src), l_fixup); \ + EX(ld, t1, (offset + 0x28)(src), l_fixup); \ + EX(ld, t2, (offset + 0x30)(src), l_fixup); \ + EX(ld, t3, (offset + 0x38)(src), l_fixup); \ + UEXD(usd, t0, (offset + 0x20)(dst), s_fixup); \ + UEXD(usd, t1, (offset + 0x28)(dst), s_fixup); \ + UEXD(usd, t2, (offset + 0x30)(dst), s_fixup); \ + UEXD(usd, t3, (offset + 0x38)(dst), s_fixup) + +/* ascending order, destination unaligned */ #define UMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ EX(lw, t0, (offset + 0x00)(src), l_fixup); \ EX(lw, t1, (offset + 0x04)(src), l_fixup); \ @@ -93,12 +146,12 @@ .set noat .align 5 -LEAF(xxmemcpy) /* a0=dst a1=src a2=len */ +LEAF(memcpy) /* a0=dst a1=src a2=len */ move v0, a0 /* return value */ __memcpy: FEXPORT(__copy_user) xor ta0, a0, a1 - andi ta0, ta0, 0x3 + andi ta0, ta0, 0x7 move t3, a0 beqz ta0, can_align sltiu t8, a2, 0x8 @@ -127,7 +180,7 @@ word_align: beqz t8, dword_align sltiu t8, a2, 56 - + EX(lh, ta0, (a1), l_fixup) dsubu a2, a2, 0x2 EX(sh, ta0, (a0), s_fixup) @@ -185,10 +238,10 @@ andi ta2, a2, 0x40 move_128bytes: - MOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - MOVE_BIGCHUNK(a1, a0, 0x20, ta0, ta1, ta3, t0) - MOVE_BIGCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) - MOVE_BIGCHUNK(a1, a0, 0x60, ta0, ta1, ta3, t0) + pref 0, 2*128(a0) + pref 1, 2*128(a1) + MOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) + MOVE_BIGGERCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) dsubu t8, t8, 0x01 daddu a1, a1, 0x80 bnez t8, move_128bytes @@ -199,8 +252,7 @@ andi ta2, a2, 0x20 move_64bytes: - MOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - MOVE_BIGCHUNK(a1, a0, 0x20, ta0, ta1, ta3, t0) + MOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) daddu a1, a1, 0x40 daddu a0, a0, 0x40 @@ -257,10 +309,8 @@ xori ta0, 7 dsubu ta0, a1 - UEX(ulw, ta1, 0(a1), l_fixup) # dword alignment - UEX(ulw, ta2, 4(a1), l_fixup) - UEX(usw, ta1, 0(a0), s_fixup) - UEX(usw, ta2, 4(a0), s_fixup) + UEXD(uld, ta1, 0(a1), l_fixup) # dword alignment + UEXD(usd, ta1, 0(a0), s_fixup) daddu a1, ta0 # src daddu a0, ta0 # dst @@ -276,11 +326,9 @@ beqz t8, u_oword_align andi t8, a1, 0x10 - EX(lw, ta0, 0x00(a1), l_fixup) - EX(lw, ta1, 0x04(a1), l_fixup) + EX(ld, ta0, 0x00(a1), l_fixup) dsubu a2, a2, 0x8 - UEX(usw, ta0, 0x00(a0), s_fixup) - UEX(usw, ta1, 0x04(a0), s_fixup) + UEXD(usd, ta0, 0x00(a0), s_fixup) daddu a1, a1, 0x8 andi t8, a1, 0x10 daddu a0, a0, 0x8 @@ -307,10 +355,8 @@ andi ta2, a2, 0x40 u_move_128bytes: - UMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - UMOVE_BIGCHUNK(a1, a0, 0x20, ta0, ta1, ta3, t0) - UMOVE_BIGCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) - UMOVE_BIGCHUNK(a1, a0, 0x60, ta0, ta1, ta3, t0) + UMOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) + UMOVE_BIGGERCHUNK(a1, a0, 0x40, ta0, ta1, ta3, t0) dsubu t8, t8, 0x01 daddu a1, a1, 0x80 bnez t8, u_move_128bytes @@ -321,8 +367,7 @@ andi ta2, a2, 0x20 u_move_64bytes: - UMOVE_BIGCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) - UMOVE_BIGCHUNK(a1, a0, 0x20, ta0, ta1, ta3, t0) + UMOVE_BIGGERCHUNK(a1, a0, 0x00, ta0, ta1, ta3, t0) daddu a1, a1, 0x40 daddu a0, a0, 0x40 @@ -365,7 +410,7 @@ jr ra move a2, zero - END(xxmemcpy) + END(memcpy) /* descending order, destination aligned */ #define RMOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3) \ @@ -406,14 +451,15 @@ usw t3, (offset + 0x0c)(dst) .align 5 -LEAF(xxmemmove) +LEAF(memmove) sltu ta0, a0, a1 # dst < src -> memcpy - bnez ta0, xxmemcpy + bnez ta0, memcpy daddu v0, a0, a2 sltu ta0, v0, a1 # dst + len < src -> non- bnez ta0, __memcpy # overlapping, can use memcpy move v0, a0 /* return value */ - END(xxmemmove) + beqz a2, r_out + END(memmove) LEAF(__rmemcpy) /* a0=dst a1=src a2=len */ daddu a0, a2 # dst = dst + len diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/lib/memset.S linux/arch/mips64/lib/memset.S --- v2.4.0-test11/linux/arch/mips64/lib/memset.S Sat May 13 08:30:17 2000 +++ linux/arch/mips64/lib/memset.S Tue Dec 5 23:15:12 2000 @@ -1,15 +1,16 @@ -/* $Id: memset.S,v 1.3 2000/01/15 23:48:55 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 1998, 1999 by Ralf Baechle - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1998, 1999, 2000 by Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include #include +#include +#include #define EX(insn,reg,addr,handler) \ 9: insn reg, addr; \ @@ -34,8 +35,6 @@ * a1: char to fill with * a2: size of area to clear */ -#include -#include .set noreorder .align 5 LEAF(memset) diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/mm/andes.c linux/arch/mips64/mm/andes.c --- v2.4.0-test11/linux/arch/mips64/mm/andes.c Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/mm/andes.c Tue Nov 28 21:42:04 2000 @@ -20,11 +20,6 @@ static int scache_lsz64; -/* CP0 hazard avoidance. I think we can drop this for the R10000. */ -#define BARRIER __asm__ __volatile__(".set noreorder\n\t" \ - "nop; nop; nop; nop; nop; nop;\n\t" \ - ".set reorder\n\t") - /* * This version has been tuned on an Origin. For other machines the arguments * of the pref instructin may have to be tuned differently. @@ -143,8 +138,6 @@ #define NTLB_ENTRIES 64 #define NTLB_ENTRIES_HALF 32 -/* TLB operations. - XXX These should work fine on R10k without the BARRIERs. */ static inline void andes_flush_tlb_all(void) { @@ -162,19 +155,15 @@ set_entryhi(CKSEG0); set_entrylo0(0); set_entrylo1(0); - BARRIER; entry = get_wired(); /* Blast 'em all away. */ while(entry < NTLB_ENTRIES) { set_index(entry); - BARRIER; tlb_write_indexed(); - BARRIER; entry++; } - BARRIER; set_entryhi(old_ctx); __restore_flags(flags); } @@ -222,18 +211,14 @@ set_entryhi(start | newpid); start += (PAGE_SIZE << 1); - BARRIER; tlb_probe(); - BARRIER; idx = get_index(); set_entrylo0(0); set_entrylo1(0); set_entryhi(KSEG0); - BARRIER; if(idx < 0) continue; tlb_write_indexed(); - BARRIER; } set_entryhi(oldpid); } else { @@ -261,20 +246,16 @@ __save_and_cli(flags); oldpid = (get_entryhi() & 0xff); set_entryhi(page | newpid); - BARRIER; tlb_probe(); - BARRIER; idx = get_index(); set_entrylo0(0); set_entrylo1(0); set_entryhi(KSEG0); if(idx < 0) goto finish; - BARRIER; tlb_write_indexed(); finish: - BARRIER; set_entryhi(oldpid); __restore_flags(flags); } @@ -311,34 +292,22 @@ address &= (PAGE_MASK << 1); set_entryhi(address | (pid)); pgdp = pgd_offset(vma->vm_mm, address); - BARRIER; tlb_probe(); - BARRIER; pmdp = pmd_offset(pgdp, address); idx = get_index(); ptep = pte_offset(pmdp, address); - BARRIER; set_entrylo0(pte_val(*ptep++) >> 6); set_entrylo1(pte_val(*ptep) >> 6); set_entryhi(address | (pid)); - BARRIER; if(idx < 0) { tlb_write_random(); } else { tlb_write_indexed(); } - BARRIER; set_entryhi(pid); - BARRIER; __restore_flags(flags); } -static int -andes_user_mode(struct pt_regs *regs) -{ - return (regs->cp0_status & ST0_KSU) == KSU_USER; -} - static void andes_show_regs(struct pt_regs *regs) { printk("Cpu %d\n", smp_processor_id()); @@ -407,7 +376,6 @@ update_mmu_cache = andes_update_mmu_cache; _show_regs = andes_show_regs; - _user_mode = andes_user_mode; flush_cache_l1(); diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/mm/fault.c linux/arch/mips64/mm/fault.c --- v2.4.0-test11/linux/arch/mips64/mm/fault.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/mm/fault.c Tue Nov 28 21:42:04 2000 @@ -57,6 +57,19 @@ printk("Got exception 0x%lx at 0x%lx\n", retaddr, regs.cp0_epc); } +extern spinlock_t console_lock, timerlist_lock; + +/* + * Unlock any spinlocks which will prevent us from getting the + * message out (timerlist_lock is aquired through the + * console unblank code) + */ +void bust_spinlocks(void) +{ + spin_lock_init(&console_lock); + spin_lock_init(&timerlist_lock); +} + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate @@ -181,6 +194,9 @@ * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ + + bust_spinlocks(); + printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at " "address %08lx, epc == %08x, ra == %08x\n", smp_processor_id(), address, (unsigned int) regs->cp0_epc, diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/mm/loadmmu.c linux/arch/mips64/mm/loadmmu.c --- v2.4.0-test11/linux/arch/mips64/mm/loadmmu.c Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/mm/loadmmu.c Tue Nov 28 21:42:04 2000 @@ -55,8 +55,6 @@ void (*_show_regs)(struct pt_regs *); -int (*_user_mode)(struct pt_regs *); - extern void ld_mmu_r4xx0(void); extern void ld_mmu_andes(void); diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c --- v2.4.0-test11/linux/arch/mips64/mm/r4xx0.c Sun Aug 6 11:43:17 2000 +++ linux/arch/mips64/mm/r4xx0.c Tue Nov 28 21:42:04 2000 @@ -1,5 +1,4 @@ -/* $Id: r4xx0.c,v 1.8 2000/02/24 00:12:41 ralf Exp $ - * +/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. @@ -7,8 +6,8 @@ * r4xx0.c: R4000 processor variant specific MMU/Cache routines. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) - * Copyright (C) 1997, 1998, 1999 Ralf Baechle (ralf@gnu.org) - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include #include @@ -811,7 +810,7 @@ blast_scache16_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -840,7 +839,7 @@ pmd_t *pmd; pte_t *pte; - save_and_cli(flags); + __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -850,7 +849,7 @@ blast_scache32_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -879,7 +878,7 @@ pmd_t *pmd; pte_t *pte; - save_and_cli(flags); + __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -889,7 +888,7 @@ blast_scache64_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -918,7 +917,7 @@ pmd_t *pmd; pte_t *pte; - save_and_cli(flags); + __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -928,7 +927,7 @@ blast_scache128_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -957,7 +956,7 @@ pmd_t *pmd; pte_t *pte; - save_and_cli(flags); + __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -967,7 +966,7 @@ blast_scache32_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -996,7 +995,7 @@ pmd_t *pmd; pte_t *pte; - save_and_cli(flags); + __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1006,7 +1005,7 @@ blast_scache64_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -1035,7 +1034,7 @@ pmd_t *pmd; pte_t *pte; - save_and_cli(flags); + __save_and_cli(flags); while(start < end) { pgd = pgd_offset(mm, start); pmd = pmd_offset(pgd, start); @@ -1045,7 +1044,7 @@ blast_scache128_page(start); start += PAGE_SIZE; } - restore_flags(flags); + __restore_flags(flags); } } } @@ -1060,9 +1059,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - save_and_cli(flags); + __save_and_cli(flags); blast_dcache16(); blast_icache16(); - restore_flags(flags); + __restore_flags(flags); } } @@ -1076,9 +1075,9 @@ #ifdef DEBUG_CACHE printk("crange[%d,%08lx,%08lx]", (int)mm->context, start, end); #endif - save_and_cli(flags); + __save_and_cli(flags); blast_dcache32(); blast_icache32(); - restore_flags(flags); + __restore_flags(flags); } } @@ -1185,7 +1184,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1197,7 +1195,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1210,7 +1208,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation * for every cache flush operation. So we do indexed flushes @@ -1223,13 +1220,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache16_page_indexed(page); - if(text) - blast_icache16_page_indexed(page); blast_scache16_page_indexed(page); } else blast_scache16_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1240,7 +1235,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1252,7 +1246,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1264,7 +1258,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation * for every cache flush operation. So we do indexed flushes @@ -1277,13 +1270,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache16_page_indexed(page); - if(text) - blast_icache16_page_indexed(page); blast_scache32_page_indexed(page); } else blast_scache32_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1294,7 +1285,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1306,7 +1296,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1318,7 +1308,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1332,13 +1321,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache16_page_indexed(page); - if(text) - blast_icache16_page_indexed(page); blast_scache64_page_indexed(page); } else blast_scache64_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1349,7 +1336,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1361,7 +1347,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1374,7 +1360,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation * for every cache flush operation. So we do indexed flushes @@ -1388,13 +1373,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache16_page_indexed(page); - if(text) - blast_icache16_page_indexed(page); blast_scache128_page_indexed(page); } else blast_scache128_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1405,7 +1388,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1417,7 +1399,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1430,7 +1412,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1445,13 +1426,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache32_page_indexed(page); - if(text) - blast_icache32_page_indexed(page); blast_scache32_page_indexed(page); } else blast_scache32_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1462,7 +1441,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1474,7 +1452,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1487,7 +1465,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1502,13 +1479,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache32_page_indexed(page); - if(text) - blast_icache32_page_indexed(page); blast_scache64_page_indexed(page); } else blast_scache64_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1519,7 +1494,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1531,7 +1505,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1543,7 +1517,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1557,13 +1530,11 @@ */ page = (KSEG0 + (page & (scache_size - 1))); blast_dcache32_page_indexed(page); - if(text) - blast_icache32_page_indexed(page); blast_scache128_page_indexed(page); } else blast_scache128_page(page); out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1574,7 +1545,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1586,7 +1556,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1598,7 +1568,6 @@ if(!(pte_val(*ptep) & _PAGE_VALID)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1607,19 +1576,15 @@ */ if(mm == current->mm) { blast_dcache16_page(page); - if(text) - blast_icache16_page(page); } else { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. */ page = (KSEG0 + (page & (dcache_size - 1))); blast_dcache16_page_indexed(page); - if(text) - blast_icache16_page_indexed(page); } out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1630,7 +1595,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1642,7 +1606,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1655,7 +1619,6 @@ if(!(pte_val(*ptep) & _PAGE_PRESENT)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1664,8 +1627,6 @@ */ if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { blast_dcache32_page(page); - if(text) - blast_icache32_page(page); } else { /* * Do indexed flush, too much work to get the (possible) @@ -1673,11 +1634,9 @@ */ page = (KSEG0 + (page & (dcache_size - 1))); blast_dcache32_page_indexed(page); - if(text) - blast_icache32_page_indexed(page); } out: - restore_flags(flags); + __restore_flags(flags); } static void @@ -1689,7 +1648,6 @@ pgd_t *pgdp; pmd_t *pmdp; pte_t *ptep; - int text; /* * If ownes no valid ASID yet, cannot possibly have gotten @@ -1701,7 +1659,7 @@ #ifdef DEBUG_CACHE printk("cpage[%d,%08lx]", (int)mm->context, page); #endif - save_and_cli(flags); + __save_and_cli(flags); page &= PAGE_MASK; pgdp = pgd_offset(mm, page); pmdp = pmd_offset(pgdp, page); @@ -1714,7 +1672,6 @@ if(!(pte_val(*ptep) & _PAGE_PRESENT)) goto out; - text = (vma->vm_flags & VM_EXEC); /* * Doing flushes for another ASID than the current one is * too difficult since stupid R4k caches do a TLB translation @@ -1723,8 +1680,6 @@ */ if((mm == current->mm) && (pte_val(*ptep) & _PAGE_VALID)) { blast_dcache32_page(page); - if(text) - blast_icache32_page(page); } else { /* Do indexed flush, too much work to get the (possible) * tlb refills to work correctly. @@ -1732,136 +1687,47 @@ page = (KSEG0 + (page & (dcache_size - 1))); blast_dcache32_page_indexed(page); blast_dcache32_page_indexed(page ^ dcache_waybit); - if(text) { - blast_icache32_page_indexed(page); - blast_icache32_page_indexed(page ^ icache_waybit); - } } out: - restore_flags(flags); -} - -/* If the addresses passed to these routines are valid, they are either: - * - * 1) In KSEG0, so we can do a direct flush of the page. - * 2) In KSEG2, and since every process can translate those addresses all - * the time in kernel mode we can do a direct flush. - * 3) In KSEG1, no flush necessary. - */ -static void r4k_flush_page_to_ram_s16d16i16(struct page * page) -{ - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache16_page(addr); - } -} - -static void r4k_flush_page_to_ram_s32d16i16(struct page * page) -{ - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache32_page(addr); - } -} - -static void r4k_flush_page_to_ram_s64d16i16(struct page * page) -{ - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache64_page(addr); - } + __restore_flags(flags); } -static void r4k_flush_page_to_ram_s128d16i16(struct page * page) +static void r4k_flush_page_to_ram_s16(struct page *page) { - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache128_page(addr); - } + blast_scache16_page((unsigned long)page_address(page)); } -static void r4k_flush_page_to_ram_s32d32i32(struct page * page) +static void r4k_flush_page_to_ram_s32(struct page *page) { - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache32_page(addr); - } + blast_scache32_page((unsigned long)page_address(page)); } -static void r4k_flush_page_to_ram_s64d32i32(struct page * page) +static void r4k_flush_page_to_ram_s64(struct page *page) { - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache64_page(addr); - } + blast_scache64_page((unsigned long)page_address(page)); } -static void r4k_flush_page_to_ram_s128d32i32(struct page * page) +static void r4k_flush_page_to_ram_s128(struct page *page) { - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - blast_scache128_page(addr); - } + blast_scache128_page((unsigned long)page_address(page)); } -static void r4k_flush_page_to_ram_d16i16(struct page * page) +static void r4k_flush_page_to_ram_d16(struct page *page) { - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { - unsigned long flags; + unsigned long flags; -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - __save_and_cli(flags); - blast_dcache16_page(addr); - __restore_flags(flags); - } + __save_and_cli(flags); + blast_dcache16_page((unsigned long)page_address(page)); + __restore_flags(flags); } -static void r4k_flush_page_to_ram_d32i32(struct page * page) +static void r4k_flush_page_to_ram_d32(struct page *page) { - unsigned long addr = (unsigned long) page_address(page) & PAGE_MASK; - - if ((addr >= KSEG0 && addr < KSEG1) || (addr >= KSEG2)) { - unsigned long flags; + unsigned long flags; -#ifdef DEBUG_CACHE - printk("cram[%08lx]", addr); -#endif - __save_and_cli(flags); - blast_dcache32_page(addr); - __restore_flags(flags); - } + __save_and_cli(flags); + blast_dcache32_page((unsigned long)page_address(page)); + __restore_flags(flags); } /* @@ -2008,7 +1874,6 @@ } #undef DEBUG_TLB -#undef DEBUG_TLBUPDATE #define NTLB_ENTRIES 48 /* Fixed on all R4XX0 variants... */ @@ -2151,12 +2016,6 @@ { } -#ifdef DEBUG_TLBUPDATE -static unsigned long ehi_debug[NTLB_ENTRIES]; -static unsigned long el0_debug[NTLB_ENTRIES]; -static unsigned long el1_debug[NTLB_ENTRIES]; -#endif - /* We will need multiple versions of update_mmu_cache(), one that just * updates the TLB with the new pte(s), and another which also checks * for the R4k "end of page" hardware bug and does the needy. @@ -2386,7 +2245,6 @@ _flush_cache_mm = r4k_flush_cache_mm_d16i16; _flush_cache_range = r4k_flush_cache_range_d16i16; _flush_cache_page = r4k_flush_cache_page_d16i16; - _flush_page_to_ram = r4k_flush_page_to_ram_d16i16; break; case 32: prid = read_32bit_cp0_register(CP0_PRID) & 0xfff0; @@ -2404,9 +2262,18 @@ _flush_cache_mm = r4k_flush_cache_mm_d32i32; _flush_cache_range = r4k_flush_cache_range_d32i32; _flush_cache_page = r4k_flush_cache_page_d32i32; - _flush_page_to_ram = r4k_flush_page_to_ram_d32i32; break; } + + switch(ic_lsize) { + case 16: + _flush_page_to_ram = r4k_flush_page_to_ram_d16; + break; + case 32: + _flush_page_to_ram = r4k_flush_page_to_ram_d32; + break; + } + _dma_cache_wback_inv = r4k_dma_cache_wback_inv_pc; _dma_cache_wback = r4k_dma_cache_wback; _dma_cache_inv = r4k_dma_cache_inv_pc; @@ -2422,11 +2289,11 @@ _flush_cache_mm = r4k_flush_cache_mm_s16d16i16; _flush_cache_range = r4k_flush_cache_range_s16d16i16; _flush_cache_page = r4k_flush_cache_page_s16d16i16; - _flush_page_to_ram = r4k_flush_page_to_ram_s16d16i16; break; case 32: panic("Invalid cache configuration detected"); }; + _flush_page_to_ram = r4k_flush_page_to_ram_s16; _clear_page = r4k_clear_page_s16; _copy_page = r4k_copy_page_s16; break; @@ -2437,16 +2304,15 @@ _flush_cache_mm = r4k_flush_cache_mm_s32d16i16; _flush_cache_range = r4k_flush_cache_range_s32d16i16; _flush_cache_page = r4k_flush_cache_page_s32d16i16; - _flush_page_to_ram = r4k_flush_page_to_ram_s32d16i16; break; case 32: _flush_cache_l1 = r4k_flush_cache_all_s32d32i32; _flush_cache_mm = r4k_flush_cache_mm_s32d32i32; _flush_cache_range = r4k_flush_cache_range_s32d32i32; _flush_cache_page = r4k_flush_cache_page_s32d32i32; - _flush_page_to_ram = r4k_flush_page_to_ram_s32d32i32; break; }; + _flush_page_to_ram = r4k_flush_page_to_ram_s32; _clear_page = r4k_clear_page_s32; _copy_page = r4k_copy_page_s32; break; @@ -2457,16 +2323,15 @@ _flush_cache_mm = r4k_flush_cache_mm_s64d16i16; _flush_cache_range = r4k_flush_cache_range_s64d16i16; _flush_cache_page = r4k_flush_cache_page_s64d16i16; - _flush_page_to_ram = r4k_flush_page_to_ram_s64d16i16; break; case 32: _flush_cache_l1 = r4k_flush_cache_all_s64d32i32; _flush_cache_mm = r4k_flush_cache_mm_s64d32i32; _flush_cache_range = r4k_flush_cache_range_s64d32i32; _flush_cache_page = r4k_flush_cache_page_s64d32i32; - _flush_page_to_ram = r4k_flush_page_to_ram_s64d32i32; break; }; + _flush_page_to_ram = r4k_flush_page_to_ram_s64; _clear_page = r4k_clear_page_s64; _copy_page = r4k_copy_page_s64; break; @@ -2477,16 +2342,15 @@ _flush_cache_mm = r4k_flush_cache_mm_s128d16i16; _flush_cache_range = r4k_flush_cache_range_s128d16i16; _flush_cache_page = r4k_flush_cache_page_s128d16i16; - _flush_page_to_ram = r4k_flush_page_to_ram_s128d16i16; break; case 32: _flush_cache_l1 = r4k_flush_cache_all_s128d32i32; _flush_cache_mm = r4k_flush_cache_mm_s128d32i32; _flush_cache_range = r4k_flush_cache_range_s128d32i32; _flush_cache_page = r4k_flush_cache_page_s128d32i32; - _flush_page_to_ram = r4k_flush_page_to_ram_s128d32i32; break; }; + _flush_page_to_ram = r4k_flush_page_to_ram_s128; _clear_page = r4k_clear_page_s128; _copy_page = r4k_copy_page_s128; break; @@ -2515,11 +2379,6 @@ setup_noscache_funcs(); } -static int r4k_user_mode(struct pt_regs *regs) -{ - return (regs->cp0_status & ST0_KSU) == KSU_USER; -} - void __init ld_mmu_r4xx0(void) { unsigned long config = read_32bit_cp0_register(CP0_CONFIG); @@ -2554,7 +2413,6 @@ update_mmu_cache = r4k_update_mmu_cache; _show_regs = r4k_show_regs; - _user_mode = r4k_user_mode; flush_cache_l1(); diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-hpc.c linux/arch/mips64/sgi-ip22/ip22-hpc.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-hpc.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip22/ip22-hpc.c Tue Nov 28 21:42:04 2000 @@ -12,6 +12,7 @@ #include #include #include +#include #undef DEBUG_SGIHPC @@ -50,10 +51,12 @@ prom_printf("GUINESS "); #endif sgi_guiness = 1; + mips_machtype = MACH_SGI_INDY; } else { #ifdef DEBUG_SGIHPC prom_printf("FULLHOUSE "); #endif + mips_machtype = MACH_SGI_INDIGO2; sgi_guiness = 0; } sgi_boardid = brev; diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-int.c Fri Aug 4 16:15:37 2000 +++ linux/arch/mips64/sgi-ip22/ip22-int.c Tue Nov 28 21:42:04 2000 @@ -1,5 +1,4 @@ -/* $Id: ip22-int.c,v 1.5 2000/03/02 02:36:50 ralf Exp $ - * +/* * indy_int.c: Routines for generic manipulation of the INT[23] ASIC * found on INDY workstations.. * @@ -65,7 +64,6 @@ static char lc3msk_to_irqnr[256]; extern asmlinkage void indyIRQ(void); -int (*irq_cannonicalize)(int irq); #ifdef CONFIG_REMOTE_DEBUG extern void rs_kgdb_hook(int); @@ -607,13 +605,7 @@ #endif } -static int indy_irq_cannonicalize(int irq) -{ - return irq; /* Sane hardware, sane code ... */ -} - void __init init_IRQ(void) { - irq_cannonicalize = indy_irq_cannonicalize; sgint_init(); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-setup.c linux/arch/mips64/sgi-ip22/ip22-setup.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-setup.c Wed Aug 9 13:46:02 2000 +++ linux/arch/mips64/sgi-ip22/ip22-setup.c Tue Nov 28 21:42:04 2000 @@ -153,7 +153,7 @@ console_setup ("ttyS0"); } #endif -#ifdef CONFIG_SGI_PROM_CONSOLE +#ifdef CONFIG_ARC_CONSOLE console_setup("ttyS0"); #endif diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-timer.c linux/arch/mips64/sgi-ip22/ip22-timer.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip22/ip22-timer.c Tue Oct 31 12:42:26 2000 +++ linux/arch/mips64/sgi-ip22/ip22-timer.c Tue Nov 28 21:42:04 2000 @@ -257,8 +257,9 @@ { write_lock_irq(&xtime_lock); xtime = *tv; - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + time_adjust = 0; /* stop active adjtime() */ + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; write_unlock_irq(&xtime_lock); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/Makefile linux/arch/mips64/sgi-ip27/Makefile --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/Makefile Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/sgi-ip27/Makefile Tue Nov 28 21:42:04 2000 @@ -1,4 +1,3 @@ -# $Id: Makefile,v 1.3 2000/02/04 08:41:40 kanoj Exp $ # # Makefile for the IP27 specific kernel interface routines under Linux. # @@ -8,9 +7,9 @@ .S.o: $(CC) $(CFLAGS) -c $< -o $*.o -L_TARGET = ip27.a -L_OBJS = ip27-berr.o ip27-irq.o ip27-irq-glue.o ip27-klconfig.o \ - ip27-memory.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \ - ip27-timer.o ip27-init.o ip27-nmi.o ip27-klnuma.o +O_TARGET = ip27.a +O_OBJS = ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \ + ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \ + ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-console.c linux/arch/mips64/sgi-ip27/ip27-console.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-console.c Wed Dec 31 16:00:00 1969 +++ linux/arch/mips64/sgi-ip27/ip27-console.c Tue Nov 28 21:42:04 2000 @@ -0,0 +1,57 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void prom_putchar(char c) +{ + struct ioc3 *ioc3; + struct ioc3_uartregs *uart; + + ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base; + uart = &ioc3->sregs.uarta; + + while ((uart->iu_lsr & 0x20) == 0); + uart->iu_thr = c; +} + +char __init prom_getchar(void) +{ + return 0; +} + +static void +ip27prom_console_write(struct console *con, const char *s, unsigned n) +{ + prom_printf("%s", s); +} + +static kdev_t +ip27prom_console_dev(struct console *c) +{ + return MKDEV(TTY_MAJOR, 64 + c->index); +} + +static struct console ip27_prom_console = { + name: "prom", + write: ip27prom_console_write, + device: ip27prom_console_dev, + flags: CON_PRINTBUFFER, + index: -1, +}; + +__init void ip27_setup_console(void) +{ + register_console(&ip27_prom_console); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-init.c Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/sgi-ip27/ip27-init.c Tue Nov 28 21:42:04 2000 @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -271,6 +271,9 @@ { extern void pcibr_setup(cnodeid_t); cnodemask_t done; + nasid_t nasid; + + nasid = COMPACT_TO_NASID_NODEID(cnode); spin_lock(&hub_mask_lock); /* Test our bit. */ @@ -281,6 +284,11 @@ * Do the actual initialization if it hasn't been done yet. * We don't need to hold a lock for this work. */ + /* + * Set CRB timeout at 5ms, (< PI timeout of 10ms) + */ + REMOTE_HUB_S(nasid, IIO_ICTP, 0x800); + REMOTE_HUB_S(nasid, IIO_ICTO, 0xff); hub_rtc_init(cnode); pcibr_setup(cnode); #ifdef CONFIG_REPLICATE_EXHANDLERS diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-irq.c Fri Aug 4 16:15:37 2000 +++ linux/arch/mips64/sgi-ip27/ip27-irq.c Tue Nov 28 21:42:04 2000 @@ -61,7 +61,6 @@ extern asmlinkage void ip27_irq(void); extern int irq_to_bus[], irq_to_slot[], bus_to_cpu[]; -int (*irq_cannonicalize)(int irq); int intr_connect_level(int cpu, int bit); int intr_disconnect_level(int cpu, int bit); @@ -392,18 +391,10 @@ return 0; } -static int indy_irq_cannonicalize(int irq) -{ - return irq; /* Sane hardware, sane code ... */ -} - void __init init_IRQ(void) { - irq_cannonicalize = indy_irq_cannonicalize; - set_except_vector(0, ip27_irq); } - #ifdef CONFIG_SMP diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-klnuma.c linux/arch/mips64/sgi-ip27/ip27-klnuma.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-klnuma.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/sgi-ip27/ip27-klnuma.c Tue Nov 28 21:42:04 2000 @@ -136,9 +136,7 @@ loadbase = CKSSEG + 16777216; #endif offset = PAGE_ALIGN((unsigned long)(&_end)) - loadbase; - if (cnode == 0) - return (offset >> PAGE_SHIFT); - else if (CPUMASK_TSTB(ktext_repmask, cnode)) + if ((cnode == 0) || (CPUMASK_TSTB(ktext_repmask, cnode))) return (TO_NODE(nasid, offset) >> PAGE_SHIFT); else return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-memory.c Tue Oct 31 12:42:26 2000 +++ linux/arch/mips64/sgi-ip27/ip27-memory.c Tue Nov 28 21:42:04 2000 @@ -258,8 +258,8 @@ extern unsigned long totalram_pages; extern unsigned long setup_zero_pages(void); cnodeid_t nid; - unsigned long tmp, ram; - unsigned long codesize, reservedpages, datasize, initsize; + unsigned long tmp; + unsigned long codesize, datasize, initsize; int slot, numslots; struct page *pg, *pslot; pfn_t pgnr; @@ -295,7 +295,6 @@ * free up the pages that hold the memmap entries. */ while (pg < pslot) { - pg->flags |= (1<> 10, - reservedpages << (PAGE_SHIFT-10), + (num_physpages - tmp) << (PAGE_SHIFT-10), datasize >> 10, initsize >> 10); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-nmi.c linux/arch/mips64/sgi-ip27/ip27-nmi.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-nmi.c Sun Jul 9 22:18:16 2000 +++ linux/arch/mips64/sgi-ip27/ip27-nmi.c Tue Nov 28 21:42:04 2000 @@ -57,10 +57,10 @@ { int i, numberof_nmi_cpu_regs; machreg_t *prom_format; - + /* Get the total number of registers being saved by the prom */ numberof_nmi_cpu_regs = sizeof(struct reg_struct) / sizeof(machreg_t); - + /* Get the pointer to the current cpu's register set. */ prom_format = (machreg_t *)(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) + @@ -166,4 +166,3 @@ nmi_eframes_save(); LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET); } - diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c linux/arch/mips64/sgi-ip27/ip27-pci-dma.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Sat May 13 08:30:17 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci-dma.c Tue Nov 28 21:42:04 2000 @@ -42,7 +42,7 @@ if (ret != NULL) { memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); + *dma_handle = (bus_to_baddr[hwdev->bus->number] | __pa(ret)); } return ret; diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-pci.c linux/arch/mips64/sgi-ip27/ip27-pci.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-pci.c Mon Aug 7 14:31:40 2000 +++ linux/arch/mips64/sgi-ip27/ip27-pci.c Tue Nov 28 21:42:04 2000 @@ -199,10 +199,11 @@ if (irqstore[dev->bus->number][slot]) return(irqstore[dev->bus->number][slot]); else { - lastirq++; /* IOC3_ETH_INT hack */ irq_to_bus[lastirq] = dev->bus->number; irq_to_slot[lastirq] = slot; - return(irqstore[dev->bus->number][slot] = lastirq); + irqstore[dev->bus->number][slot] = lastirq; + lastirq++; + return (lastirq - 1); } } @@ -314,11 +315,25 @@ d->resource[i].end = 0UL; d->resource[i].flags = 0UL; } - d->subsystem_vendor = 0; - d->subsystem_device = 0; - d->irq = 1; pci_disable_swapping(d); + + /* + * The serial driver will try to probe for serial ports + * later on. MENET boards dbe out unrecoverably on sio space + * access to the 4th ioc3. (The first 3 iocs work okay, they + * have kbd/ms ports; all have ethernet ports). Catch this + * case now and disable the serial driver from looking at + * these ioc3s. Identify MENET cards by seeing if an ioc3 is + * at slot 3. + */ + d->subsystem_vendor = 0xFF00; + if (PCI_SLOT(d->devfn) == 3) { + struct list_head *p; + list_for_each(p, &d->bus->devices) { + list_entry(p, struct pci_dev, bus_list)->subsystem_vendor = 0; + } + } } static void __init diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-rtc.c linux/arch/mips64/sgi-ip27/ip27-rtc.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-rtc.c Tue Oct 31 12:42:26 2000 +++ linux/arch/mips64/sgi-ip27/ip27-rtc.c Tue Nov 28 21:42:04 2000 @@ -37,7 +37,7 @@ #include #include -#include +#include #include #include #include diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-setup.c linux/arch/mips64/sgi-ip27/ip27-setup.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-setup.c Thu Jul 13 09:39:49 2000 +++ linux/arch/mips64/sgi-ip27/ip27-setup.c Tue Nov 28 21:42:04 2000 @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -104,10 +104,12 @@ #define BASE_XBOW_PORT 8 /* Lowest external port */ unsigned int bus_to_cpu[256]; +unsigned long bus_to_baddr[256]; void __init pcibr_setup(cnodeid_t nid) { - int i, start, num, masterwid; + int i, start, num; + unsigned long masterwid; bridge_t *bridge; volatile u64 hubreg; nasid_t nasid, masternasid; @@ -116,6 +118,17 @@ static spinlock_t pcibr_setup_lock = SPIN_LOCK_UNLOCKED; /* + * If the master is doing this for headless node, nothing to do. + * This is because currently we require at least one of the hubs + * (master hub) connected to the xbow to have at least one enabled + * cpu to receive intrs. Else we need an array bus_to_intrnasid[] + * that bridge_startup() needs to use to target intrs. All dma is + * routed thru the widget of the master hub. The master hub wid + * is selectable by WIDGET_A below. + */ + if (nid != get_compact_nodeid()) + return; + /* * find what's on our local node */ spin_lock(&pcibr_setup_lock); @@ -137,6 +150,8 @@ num_bridges = 1; bus_to_wid[0] = 0x8; bus_to_nid[0] = 0; + masterwid = 0xa; + bus_to_baddr[0] = 0xa100000000000000UL; } else if (partnum == XBOW_WIDGET_PART_NUM) { lboard_t *brd; klxbow_t *xbow_p; @@ -157,21 +172,22 @@ else { /* * Okay, here's a xbow. Lets arbitrate and find - * out if we should initialize it. Set hub connected - * at highest or lowest widget as master. - * This algo needs to change a little for headless - * nodes. + * out if we should initialize it. Set enabled + * hub connected at highest or lowest widget as + * master. */ #ifdef WIDGET_A i = HUB_WIDGET_ID_MAX + 1; do { i--; - } while (!XBOW_PORT_TYPE_HUB(xbow_p, i)); + } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || + (!XBOW_PORT_IS_ENABLED(xbow_p, i))); #else i = HUB_WIDGET_ID_MIN - 1; do { i++; - } while (!XBOW_PORT_TYPE_HUB(xbow_p, i)); + } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) || + (!XBOW_PORT_IS_ENABLED(xbow_p, i))); #endif masterwid = i; masternasid = XBOW_PORT_NASID(xbow_p, i); @@ -187,6 +203,7 @@ printk("widget 0x%x is a bridge\n", i); bus_to_wid[num_bridges] = i; bus_to_nid[num_bridges] = nasid; + bus_to_baddr[num_bridges] = ((masterwid << 60) | (1UL << 56)); /* Barrier set */ num_bridges++; } } @@ -205,6 +222,10 @@ bus_to_nid[1] = 0; bus_to_nid[2] = 0; + bus_to_baddr[0] = 0xa100000000000000UL; + bus_to_baddr[1] = 0xa100000000000000UL; + bus_to_baddr[2] = 0xa100000000000000UL; + masterwid = 0xa; num_bridges = 3; } } @@ -240,24 +261,25 @@ /* * Hmm... IRIX sets additional bits in the address which * are documented as reserved in the bridge docs. - * We waste time programming b_wid_int_upper/b_wid_int_lower, - * since bridge_startup will set up the widget->nasid intr - * path anyway. */ bridge->b_int_mode = 0x0; /* Don't clear ints */ - bridge->b_wid_int_upper = 0x000a8000; /* Ints to widget A */ - bridge->b_wid_int_lower = 0x01800090; - bridge->b_dir_map = 0xa00000; /* DMA */ + bridge->b_wid_int_upper = 0x8000 | (masterwid << 16); + bridge->b_wid_int_lower = 0x01800090; /* PI_INT_PEND_MOD off*/ + bridge->b_dir_map = (masterwid << 20); /* DMA */ bridge->b_int_enable = 0; bridge->b_wid_tflush; /* wait until Bridge PIO complete */ } } +extern void ip27_setup_console(void); + void __init ip27_setup(void) { nasid_t nid; hubreg_t p, e; + + ip27_setup_console(); num_bridges = 0; /* diff -u --recursive --new-file v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c --- v2.4.0-test11/linux/arch/mips64/sgi-ip27/ip27-timer.c Tue Oct 31 12:42:26 2000 +++ linux/arch/mips64/sgi-ip27/ip27-timer.c Tue Nov 28 21:42:04 2000 @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -23,7 +23,8 @@ #include #include -/* This is a hack; we really need to figure these values out dynamically +/* + * This is a hack; we really need to figure these values out dynamically * * Since 800 ns works very well with various HUB frequencies, such as * 360, 380, 390 and 400 MHZ, we use 800 ns rtc cycle time. @@ -43,49 +44,47 @@ static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; +{ + int retval = 0; + int real_seconds, real_minutes, cmos_minutes; struct m48t35_rtc *rtc; nasid_t nid; nid = get_nasid(); - rtc = (struct m48t35_rtc *) - KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0; - + rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + + IOC3_BYTEBUS_DEV0); + rtc->control |= M48T35_RTC_READ; cmos_minutes = rtc->min; BCD_TO_BIN(cmos_minutes); rtc->control &= ~M48T35_RTC_READ; - - /* - * Since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { + + /* + * Since we're only adjusting minutes and seconds, don't interfere with + * hour overflow. This avoids messing with unknown time zones but + * requires your RTC not to be off by more than 15 minutes + */ + real_seconds = nowtime % 60; + real_minutes = nowtime / 60; + if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) + real_minutes += 30; /* correct for half hour time zone */ + real_minutes %= 60; + + if (abs(real_minutes - cmos_minutes) < 30) { BIN_TO_BCD(real_seconds); BIN_TO_BCD(real_minutes); rtc->control |= M48T35_RTC_SET; - rtc->sec = real_seconds; - rtc->min = real_minutes; + rtc->sec = real_seconds; + rtc->min = real_minutes; rtc->control &= ~M48T35_RTC_SET; - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } + } else { + printk(KERN_WARNING + "set_rtc_mmss: can't update from %d to %d\n", + cmos_minutes, real_minutes); + retval = -1; + } - - return retval; + return retval; } void rt_timer_interrupt(struct pt_regs *regs) @@ -110,41 +109,28 @@ do_timer(regs); #ifdef CONFIG_SMP - if (current->pid) { - unsigned int *inc, *inc2; + { int user = user_mode(regs); - update_one_process(current, 1, user, !user, cpu); - if (--current->counter <= 0) { - current->counter = 0; - current->need_resched = 1; - } - - if (user) { - if (current->nice > 0) { - inc = &kstat.cpu_nice; - inc2 = &kstat.per_cpu_nice[cpu]; - } else { - inc = &kstat.cpu_user; - inc2 = &kstat.per_cpu_user[cpu]; - } - } else { - inc = &kstat.cpu_system; - inc2 = &kstat.per_cpu_system[cpu]; - } - atomic_inc((atomic_t *)inc); - atomic_inc((atomic_t *)inc2); + /* + * update_process_times() expects us to have done irq_enter(). + * Besides, if we don't timer interrupts ignore the global + * interrupt lock, which is the WrongThing (tm) to do. + * Picked from i386 code. + */ + irq_enter(cpu, 0); + update_process_times(user); + irq_exit(cpu, 0); } #endif /* CONFIG_SMP */ - /* - * If we have an externally synchronized Linux clock, then update - * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be - * called as close as possible to when a second starts. - */ - - if ((time_status & STA_UNSYNC) == 0 && - xtime.tv_sec > last_rtc_update + 660) { + /* + * If we have an externally synchronized Linux clock, then update + * RTC clock accordingly every ~11 minutes. Set_rtc_mmss() has to be + * called as close as possible to when a second starts. + */ + if ((time_status & STA_UNSYNC) == 0 && + xtime.tv_sec > last_rtc_update + 660) { if (xtime.tv_usec >= 1000000 - ((unsigned) tick) / 2) { if (set_rtc_mmss(xtime.tv_sec + 1) == 0) last_rtc_update = xtime.tv_sec; @@ -206,9 +192,9 @@ xtime = *tv; time_adjust = 0; /* stop active adjtime() */ - time_state = TIME_BAD; - time_maxerror = MAXPHASE; - time_esterror = MAXPHASE; + time_status |= STA_UNSYNC; + time_maxerror = NTP_PHASE_LIMIT; + time_esterror = NTP_PHASE_LIMIT; write_unlock_irq(&xtime_lock); } @@ -219,10 +205,8 @@ #include #include -#define DEBUG_RTC - -static unsigned long __init get_m48t35_time(void) -{ +static __init unsigned long get_m48t35_time(void) +{ unsigned int year, month, date, hour, min, sec; struct m48t35_rtc *rtc; nasid_t nid; @@ -231,7 +215,7 @@ rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0); - rtc->control |= M48T35_RTC_READ; + rtc->control |= M48T35_RTC_READ; sec = rtc->sec; min = rtc->min; hour = rtc->hour; @@ -252,8 +236,6 @@ return mktime(year, month, date, hour, min, sec); } -extern void ioc3_eth_init(void); - void __init time_init(void) { xtime.tv_sec = get_m48t35_time(); @@ -265,7 +247,7 @@ lboard_t *board; klcpu_t *cpu; int cpuid; - + /* Don't use ARCS. ARCS is fragile. Klconfig is simple and sane. */ board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27); if (!board) diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/Makefile linux/arch/parisc/Makefile --- v2.4.0-test11/linux/arch/parisc/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/Makefile Tue Dec 5 12:29:39 2000 @@ -0,0 +1,91 @@ +# +# parisc/Makefile +# +# This file is included by the global makefile so that you can add your own +# architecture-specific flags and dependencies. Remember to do have actions +# for "archclean" and "archdep" for cleaning up and making dependencies for +# this architecture +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 1994 by Linus Torvalds +# Portions Copyright (C) 1999 The Puffin Group +# +# Modified for PA-RISC Linux by Paul Lahaie, Alex deVries, +# Mike Shaver, Helge Deller and Martin K. Petersen +# + +FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align + +CPP=$(CC) -E +OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S +LDFLAGS = +LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS) + +CFLAGS_PIPE := -pipe +CFLAGS_NSR := -fno-strength-reduce +CFLAGS := $(CFLAGS) -D__linux__ $(CFLAGS_PIPE) $(CFLAGS_NSR) + +# These should be on for older toolchains or SOM toolchains that don't +# enable them by default. +CFLAGS += -mno-space-regs -mfast-indirect-calls + +# If we become able to compile for specific platforms, this should be +# conditional on that. +CFLAGS += -mschedule=7200 + +# No fixed-point multiply +CFLAGS += -mdisable-fpregs + +HEAD = arch/parisc/kernel/head.o + +SUBDIRS := $(SUBDIRS) $(addprefix arch/parisc/, tools kernel mm lib hpux) +CORE_FILES := $(addprefix arch/parisc/, kernel/pdc_cons.o kernel/process.o \ + lib/lib.a mm/mm.o kernel/kernel.o hpux/hpux.o) \ + $(CORE_FILES) arch/parisc/kernel/init_task.o +LIBS := `$(CC) -print-libgcc-file-name` $(TOPDIR)/arch/parisc/lib/lib.a $(LIBS) + +ifdef CONFIG_MATH_EMULATION +SUBDIRS := $(SUBDIRS) arch/parisc/math-emu +DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.a +endif + +ifdef CONFIG_KWDB +SUBDIRS := $(SUBDIRS) arch/parisc/kdb +DRIVERS := $(DRIVERS) arch/parisc/kdb/kdb.o + +arch/parisc/kdb: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/kdb +endif + +arch/parisc/kernel: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/kernel + +arch/parisc/mm: dummy + $(MAKE) linuxsubdirs SUBDIRS=arch/parisc/mm + +palo: vmlinux + export TOPDIR=`pwd`; export CONFIG_STI_CONSOLE=$(CONFIG_STI_CONSOLE); \ + unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage + +Image: palo + +Image-clean: + +ramdisk.o: + +zImage: palo + +bzImage: palo + +compressed: zImage + +install: + +archclean: + +archmrproper: + +archdep: diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/config.in linux/arch/parisc/config.in --- v2.4.0-test11/linux/arch/parisc/config.in Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/config.in Tue Dec 5 12:29:39 2000 @@ -0,0 +1,208 @@ +# +# For a description of the syntax of this configuration file, +# see the Configure script. +# + +mainmenu_name "Linux Kernel Configuration" + +define_bool CONFIG_PARISC y +define_bool CONFIG_UID16 n + +mainmenu_option next_comment +comment 'Code maturity level options' +bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL +endmenu + +mainmenu_option next_comment +comment 'General options' + +# bool 'Symmetric multi-processing support' CONFIG_SMP +define_bool CONFIG_SMP n + +bool 'Kernel Debugger support' CONFIG_KWDB +# define_bool CONFIG_KWDB n + +# bool 'GSC/Gecko bus support' CONFIG_GSC y +define_bool CONFIG_GSC y + +bool 'U2/Uturn I/O MMU' CONFIG_IOMMU_CCIO y +bool 'LASI I/O support' CONFIG_GSC_LASI y + +bool 'PCI bus support' CONFIG_PCI y + +if [ "$CONFIG_PCI" = "y" ]; then + bool 'GSCtoPCI/DINO PCI support' CONFIG_GSC_DINO y + bool 'LBA/Elroy PCI support' CONFIG_PCI_LBA n +fi + +if [ "$CONFIG_PCI_LBA" = "y" ]; then + define_bool CONFIG_IOSAPIC y + define_bool CONFIG_IOMMU_SBA y +fi + +# +# if [ "$CONFIG_PCI_EPIC" = "y" ]; then... +# + +endmenu + +mainmenu_option next_comment +comment 'Loadable module support' +bool 'Enable loadable module support' CONFIG_MODULES +if [ "$CONFIG_MODULES" = "y" ]; then + bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS + bool 'Kernel module loader' CONFIG_KMOD +fi +endmenu + +mainmenu_option next_comment +comment 'General setup' + +bool 'Networking support' CONFIG_NET + +bool 'System V IPC' CONFIG_SYSVIPC +bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'Sysctl support' CONFIG_SYSCTL +tristate 'Kernel support for SOM binaries' CONFIG_BINFMT_SOM +tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF +tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC +if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA +fi + +endmenu + +##source drivers/parport/Config.in +mainmenu_option next_comment +comment 'Parallel port support' + +tristate 'Parallel port support' CONFIG_PARPORT +if [ "$CONFIG_PARPORT" != "n" ]; then + if [ "$CONFIG_PCI" = "y" ]; then + dep_tristate ' PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT + if [ "$CONFIG_PARPORT_PC" != "n" ]; then + bool ' Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + bool ' SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO + fi + fi + fi + if [ "$CONFIG_GSC_LASI" = "y" ]; then + dep_tristate ' LASI/ASP builtin parallel-port' CONFIG_PARPORT_GSC $CONFIG_PARPORT + else + define_tristate CONFIG_PARPORT_GSC n + fi + + # If exactly one hardware type is selected then parport will optimise away + # support for loading any others. Defeat this if the user is keen. + bool ' Support foreign hardware' CONFIG_PARPORT_OTHER + + bool ' IEEE 1284 transfer modes' CONFIG_PARPORT_1284 +fi +endmenu + + +source drivers/block/Config.in + +if [ "$CONFIG_NET" = "y" ]; then + source net/Config.in +fi + +mainmenu_option next_comment +comment 'SCSI support' + +tristate 'SCSI support' CONFIG_SCSI + +if [ "$CONFIG_SCSI" != "n" ]; then + comment 'SCSI support type (disk, tape, CDrom)' + + dep_tristate 'SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI + if [ "$CONFIG_BLK_DEV_SD" != "n" ]; then + int 'Maximum number of SCSI disks that can be loaded as modules' CONFIG_SD_EXTRA_DEVS 40 + fi + + dep_tristate 'SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI + dep_tristate 'SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI + if [ "$CONFIG_BLK_DEV_SR" != "n" ]; then + bool ' Enable vendor-specific extensions (for SCSI CDROM)' CONFIG_BLK_DEV_SR_VENDOR + int 'Maximum number of CDROM devices that can be loaded as modules' CONFIG_SR_EXTRA_DEVS 2 + fi + dep_tristate 'SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI + + comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs' + bool 'Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN + bool 'Verbose SCSI error reporting (kernel size +=12K)' CONFIG_SCSI_CONSTANTS + + mainmenu_option next_comment + comment 'SCSI low-level drivers' + if [ "$CONFIG_GSC_LASI" = "y" ]; then + dep_tristate 'Lasi SCSI support' CONFIG_SCSI_LASI $CONFIG_SCSI + dep_tristate 'Zalon SCSI support' CONFIG_SCSI_ZALON $CONFIG_SCSI + fi + if [ "$CONFIG_PCI" = "y" ]; then + dep_tristate 'SYM53C8XX SCSI support' CONFIG_SCSI_SYM53C8XX $CONFIG_SCSI + fi + if [ "$CONFIG_SCSI_ZALON" != "n" -o "$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 20 + bool ' enable profiling' CONFIG_SCSI_NCR53C8XX_PROFILE + bool ' use normal IO' CONFIG_SCSI_NCR53C8XX_IOMAPPED + fi + endmenu +fi +endmenu + +if [ "$CONFIG_NET" = "y" ]; then + mainmenu_option next_comment + comment 'Network device support' + + bool 'Network device support' CONFIG_NETDEVICES + + if [ "$CONFIG_NETDEVICES" = "y" ]; then + if [ "$CONFIG_GSC_LASI" = "y" ]; then + tristate 'Lasi ethernet' CONFIG_LASI_82596 + fi + source drivers/net/Config.in + fi + endmenu +fi + +source drivers/char/Config.in + +source fs/Config.in + +mainmenu_option next_comment +comment 'Sound Drivers' +tristate 'Sound card support' CONFIG_SOUND +if [ "$CONFIG_SOUND" != "n" ]; then + source drivers/sound/Config.in +fi +endmenu + +if [ "$CONFIG_VT" = "y" ]; then + mainmenu_option next_comment + comment 'Console drivers' + source drivers/video/Config.in + +# bool 'IODC console' CONFIG_IODC_CONSOLE + bool 'STI console' CONFIG_STI_CONSOLE + if [ "$CONFIG_IODC_CONSOLE" = "n" ]; then + if [ "$CONFIG_GSC_PS2" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + fi + if [ "$CONFIG_STI_CONSOLE" = "y" ]; then + define_bool CONFIG_DUMMY_CONSOLE y + fi + endmenu +fi +# endmenu + +mainmenu_option next_comment +comment 'Kernel hacking' + +#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC +bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ +endmenu + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/defconfig linux/arch/parisc/defconfig --- v2.4.0-test11/linux/arch/parisc/defconfig Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/defconfig Tue Dec 5 12:29:39 2000 @@ -0,0 +1,363 @@ +# +# Automatically generated by make menuconfig: don't edit +# +CONFIG_PARISC=y +# CONFIG_UID16 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# General options +# +# CONFIG_SMP is not set +# CONFIG_KWDB is not set +CONFIG_GSC=y +CONFIG_IOMMU_CCIO=y +CONFIG_GSC_LASI=y +CONFIG_PCI=y +CONFIG_GSC_DINO=y +CONFIG_PCI_LBA=y +CONFIG_IOSAPIC=y +CONFIG_IOMMU_SBA=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_BINFMT_SOM=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +# CONFIG_BINFMT_JAVA is not set + +# +# Parallel port support +# +CONFIG_PARPORT=y +# CONFIG_PARPORT_PC is not set +CONFIG_PARPORT_GSC=y +# CONFIG_PARPORT_OTHER is not set +# CONFIG_PARPORT_1284 is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# Networking options +# +# CONFIG_PACKET is not set +# CONFIG_NETLINK is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_BOOTP=y +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_IPV6 is not set +# CONFIG_KHTTPD is not set +# CONFIG_ATM is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_LLC is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# SCSI support +# +CONFIG_SCSI=y +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +CONFIG_CHR_DEV_ST=y +CONFIG_BLK_DEV_SR=y +# CONFIG_BLK_DEV_SR_VENDOR is not set +CONFIG_SR_EXTRA_DEVS=2 +CONFIG_CHR_DEV_SG=y +# CONFIG_SCSI_MULTI_LUN is not set +# CONFIG_SCSI_CONSTANTS is not set + +# +# SCSI low-level drivers +# +CONFIG_SCSI_LASI=y +CONFIG_SCSI_ZALON=y +CONFIG_SCSI_SYM53C8XX=y +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y +CONFIG_LASI_82596=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_DE4X5 is not set +CONFIG_TULIP=y +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +# CONFIG_EEPRO100 is not set +# CONFIG_LNE390 is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_RTL8129 is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_TLAN is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_RCPCI is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_GSC_PS2=y +CONFIG_HIL=y +CONFIG_SERIAL=y +CONFIG_SERIAL_CONSOLE=y +CONFIG_SERIAL_GSC=y +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_PRINTER=y +# CONFIG_LP_CONSOLE is not set +# CONFIG_PPDEV is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set + +# +# Joysticks +# +# CONFIG_JOYSTICK is not set +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +CONFIG_GENRTC=y +# CONFIG_INTEL_RNG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +# CONFIG_AGP is not set +# CONFIG_DRM is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_RAMFS is not set +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_MINIX_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_DEVPTS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_SYSV_FS_WRITE is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +CONFIG_ROOT_NFS=y +# CONFIG_NFSD is not set +# CONFIG_NFSD_V3 is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_MOUNT_SUBDIR is not set +# CONFIG_NCPFS_NDS_DOMAINS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_NLS is not set + +# +# Sound Drivers +# +# CONFIG_SOUND is not set + +# +# Console drivers +# + +# +# Frame-buffer support +# +# CONFIG_FB is not set +# CONFIG_STI_CONSOLE is not set + +# +# Kernel hacking +# +CONFIG_MAGIC_SYSRQ=y diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/Makefile linux/arch/parisc/hpux/Makefile --- v2.4.0-test11/linux/arch/parisc/hpux/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/Makefile Tue Dec 5 12:29:39 2000 @@ -0,0 +1,16 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +all: hpux.o +O_TARGET = hpux.o +O_OBJS = entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o + +.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/entry_hpux.S linux/arch/parisc/hpux/entry_hpux.S --- v2.4.0-test11/linux/arch/parisc/hpux/entry_hpux.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/entry_hpux.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,537 @@ +/* ----------------------------------------------------------------------------- + * + * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) + * + * modified by Matthew Wilcox 1999-07-26 + */ + + +#define ASSEMBLY + +#include +#include +#include + + + .text + +#define ENTRY_NAME(_name_) .word _name_ + + .align 4 + .export hpux_call_table +hpux_call_table: + ENTRY_NAME(sys_ni_syscall) /* 0 */ + ENTRY_NAME(sys_exit) + ENTRY_NAME(hpux_fork_wrapper) + ENTRY_NAME(sys_read) + ENTRY_NAME(sys_write) + ENTRY_NAME(sys_open) /* 5 */ + ENTRY_NAME(sys_close) + ENTRY_NAME(hpux_wait) + ENTRY_NAME(sys_creat) + ENTRY_NAME(sys_link) + ENTRY_NAME(sys_unlink) /* 10 */ + ENTRY_NAME(hpux_execv_wrapper) + ENTRY_NAME(sys_chdir) + ENTRY_NAME(sys_time) + ENTRY_NAME(sys_mknod) + ENTRY_NAME(sys_chmod) /* 15 */ + ENTRY_NAME(sys_chown) + ENTRY_NAME(hpux_brk) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_lseek) + ENTRY_NAME(sys_getpid) /* 20 */ + ENTRY_NAME(hpux_mount) + ENTRY_NAME(sys_oldumount) + ENTRY_NAME(sys_setuid) + ENTRY_NAME(sys_getuid) + ENTRY_NAME(sys_stime) /* 25 */ + ENTRY_NAME(hpux_ptrace) + ENTRY_NAME(sys_alarm) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_pause) + ENTRY_NAME(sys_utime) /* 30 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_access) + ENTRY_NAME(hpux_nice) + ENTRY_NAME(sys_ni_syscall) /* 35 */ + ENTRY_NAME(sys_sync) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_newstat) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_newlstat) /* 40 */ + ENTRY_NAME(sys_dup) + ENTRY_NAME(hpux_pipe_wrapper) + ENTRY_NAME(sys_times) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 45 */ + ENTRY_NAME(sys_setgid) + ENTRY_NAME(sys_getgid) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 50 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_ioctl) + ENTRY_NAME(sys_ni_syscall) /* 55 */ + ENTRY_NAME(sys_symlink) + ENTRY_NAME(hpux_utssys) + ENTRY_NAME(sys_readlink) + ENTRY_NAME(hpux_execve_wrapper) + ENTRY_NAME(sys_umask) /* 60 */ + ENTRY_NAME(sys_chroot) + ENTRY_NAME(sys_fcntl) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 65 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_sbrk) + ENTRY_NAME(sys_ni_syscall) /* 70 */ + ENTRY_NAME(sys_mmap) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 75 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 80 */ + ENTRY_NAME(sys_getpgid) + ENTRY_NAME(sys_setpgid) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 85 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_dup2) /* 90 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_newfstat) + ENTRY_NAME(sys_select) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 95 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 100 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 105 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 110 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 115 */ + ENTRY_NAME(sys_gettimeofday) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 120 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_fchown) + ENTRY_NAME(sys_fchmod) + ENTRY_NAME(sys_ni_syscall) /* 125 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_rename) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 130 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_sysconf) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 135 */ + ENTRY_NAME(sys_mkdir) + ENTRY_NAME(sys_rmdir) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 140 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 145 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 150 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 155 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 160 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 165 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 170 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 175 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 180 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 185 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 190 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_getdomainname) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 195 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_waitpid) /* 200 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 205 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 210 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 215 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 220 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 225 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 230 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 235 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 240 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 245 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 250 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 255 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 260 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 265 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 270 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_fchdir) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_accept) /* 275 */ + ENTRY_NAME(sys_bind) + ENTRY_NAME(sys_connect) + ENTRY_NAME(sys_getpeername) + ENTRY_NAME(sys_getsockname) + ENTRY_NAME(sys_getsockopt) /* 280 */ + ENTRY_NAME(sys_listen) + ENTRY_NAME(sys_recv) + ENTRY_NAME(sys_recvfrom) + ENTRY_NAME(sys_recvmsg) + ENTRY_NAME(sys_send) /* 285 */ + ENTRY_NAME(sys_sendmsg) + ENTRY_NAME(sys_sendto) + ENTRY_NAME(sys_setsockopt) + ENTRY_NAME(sys_shutdown) + ENTRY_NAME(sys_socket) /* 290 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 295 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 300 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 305 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 310 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 315 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 320 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 325 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 330 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_lchown) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 335 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 340 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 345 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 350 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_nanosleep) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 355 */ + ENTRY_NAME(hpux_getdents) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 360 */ + ENTRY_NAME(hpux_fstat64) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 365 */ + ENTRY_NAME(hpux_lstat64) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(hpux_stat64) + ENTRY_NAME(sys_ni_syscall) /* 370 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 375 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 380 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 385 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 390 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 395 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 400 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 405 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 410 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 415 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 420 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 425 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 430 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 435 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 440 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 445 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 450 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 455 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 460 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 465 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 470 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 475 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 480 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 485 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 490 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 495 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 500 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 505 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) /* 510 */ + ENTRY_NAME(sys_ni_syscall) + ENTRY_NAME(sys_ni_syscall) +.end + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/fs.c linux/arch/parisc/hpux/fs.c --- v2.4.0-test11/linux/arch/parisc/hpux/fs.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/fs.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,250 @@ +/* + * linux/arch/parisc/kernel/sys_hpux.c + * + * implements HPUX syscalls. + */ + +#include +#include +#include +#include +#include +#include +#include + +int hpux_execve(struct pt_regs *regs) +{ + int error; + char *filename; + + filename = getname((char *) regs->gr[26]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + + error = do_execve(filename, (char **) regs->gr[25], + (char **)regs->gr[24], regs); + + if (error == 0) + current->ptrace &= ~PT_DTRACE; + putname(filename); + +out: + return error; +} + +struct hpux_dirent { + long d_off_pad; /* we only have a 32-bit off_t */ + long d_off; + ino_t d_ino; + short d_reclen; + short d_namlen; + char d_name[1]; +}; + +struct getdents_callback { + struct hpux_dirent *current_dir; + struct hpux_dirent *previous; + int count; + int error; +}; + +#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de))) +#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) + +static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino) +{ + struct hpux_dirent * dirent; + struct getdents_callback * buf = (struct getdents_callback *) __buf; + int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); + + buf->error = -EINVAL; /* only used if we fail.. */ + if (reclen > buf->count) + return -EINVAL; + dirent = buf->previous; + if (dirent) + put_user(offset, &dirent->d_off); + dirent = buf->current_dir; + buf->previous = dirent; + put_user(ino, &dirent->d_ino); + put_user(reclen, &dirent->d_reclen); + put_user(namlen, &dirent->d_namlen); + copy_to_user(dirent->d_name, name, namlen); + put_user(0, dirent->d_name + namlen); + ((char *) dirent) += reclen; + buf->current_dir = dirent; + buf->count -= reclen; + return 0; +} + +#undef NAME_OFFSET +#undef ROUND_UP + +int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count) +{ + struct file * file; + struct dentry * dentry; + struct inode * inode; + struct hpux_dirent * lastdirent; + struct getdents_callback buf; + int error; + + lock_kernel(); + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + + dentry = file->f_dentry; + if (!dentry) + goto out_putf; + + inode = dentry->d_inode; + if (!inode) + goto out_putf; + + buf.current_dir = dirent; + buf.previous = NULL; + buf.count = count; + buf.error = 0; + + error = -ENOTDIR; + if (!file->f_op || !file->f_op->readdir) + goto out_putf; + + /* + * Get the inode's semaphore to prevent changes + * to the directory while we read it. + */ + down(&inode->i_sem); + error = file->f_op->readdir(file, &buf, filldir); + up(&inode->i_sem); + if (error < 0) + goto out_putf; + error = buf.error; + lastdirent = buf.previous; + if (lastdirent) { + put_user(file->f_pos, &lastdirent->d_off); + error = count - buf.count; + } + +out_putf: + fput(file); +out: + unlock_kernel(); + return error; +} + +int hpux_mount(const char *fs, const char *path, int mflag, + const char *fstype, const char *dataptr, int datalen) +{ + return -ENOSYS; +} + +static int cp_hpux_stat(struct inode * inode, struct hpux_stat64 * statbuf) +{ + struct hpux_stat64 tmp; + unsigned int blocks, indirect; + + memset(&tmp, 0, sizeof(tmp)); + tmp.st_dev = kdev_t_to_nr(inode->i_dev); + tmp.st_ino = inode->i_ino; + tmp.st_mode = inode->i_mode; + tmp.st_nlink = inode->i_nlink; + tmp.st_uid = inode->i_uid; + tmp.st_gid = inode->i_gid; + tmp.st_rdev = kdev_t_to_nr(inode->i_rdev); + tmp.st_size = inode->i_size; + tmp.st_atime = inode->i_atime; + tmp.st_mtime = inode->i_mtime; + tmp.st_ctime = inode->i_ctime; + +#define D_B 7 +#define I_B (BLOCK_SIZE / sizeof(unsigned short)) + + if (!inode->i_blksize) { + blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE; + if (blocks > D_B) { + indirect = (blocks - D_B + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) { + indirect = (indirect - 1 + I_B - 1) / I_B; + blocks += indirect; + if (indirect > 1) + blocks++; + } + } + tmp.st_blocks = (BLOCK_SIZE / 512) * blocks; + tmp.st_blksize = BLOCK_SIZE; + } else { + tmp.st_blocks = inode->i_blocks; + tmp.st_blksize = inode->i_blksize; + } + return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0; +} + +/* + * Revalidate the inode. This is required for proper NFS attribute caching. + * Blatently copied wholesale from fs/stat.c + */ +static __inline__ int +do_revalidate(struct dentry *dentry) +{ + struct inode * inode = dentry->d_inode; + if (inode->i_op && inode->i_op->revalidate) + return inode->i_op->revalidate(dentry); + return 0; +} + +long hpux_stat64(const char *path, struct hpux_stat64 *buf) +{ + struct nameidata nd; + int error; + + lock_kernel(); + error = user_path_walk(path, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_hpux_stat(nd.dentry->d_inode, buf); + path_release(&nd); + } + unlock_kernel(); + return error; +} + +long hpux_fstat64(unsigned int fd, struct hpux_stat64 *statbuf) +{ + struct file * f; + int err = -EBADF; + + lock_kernel(); + f = fget(fd); + if (f) { + struct dentry * dentry = f->f_dentry; + + err = do_revalidate(dentry); + if (!err) + err = cp_hpux_stat(dentry->d_inode, statbuf); + fput(f); + } + unlock_kernel(); + return err; +} + +long hpux_lstat64(char *filename, struct hpux_stat64 *statbuf) +{ + struct nameidata nd; + int error; + + lock_kernel(); + error = user_path_walk_link(filename, &nd); + if (!error) { + error = do_revalidate(nd.dentry); + if (!error) + error = cp_hpux_stat(nd.dentry->d_inode, statbuf); + path_release(&nd); + } + unlock_kernel(); + return error; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/gate.S linux/arch/parisc/hpux/gate.S --- v2.4.0-test11/linux/arch/parisc/hpux/gate.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/gate.S Wed Dec 6 11:46:39 2000 @@ -0,0 +1,72 @@ +/* ------------------------------------------------------------------------------ + * + * Linux/PARISC Project (http://www.thepuffingroup.com/parisc) + * + * System call entry code Copyright (c) Matthew Wilcox 1999 + * Licensed under the GNU GPL. + * thanks to Philipp Rumpf, Mike Shaver and various others + * sorry about the wall, puffin.. + */ + +#define __ASSEMBLY__ +#include +#include +#include +#include + + .text + + .import hpux_call_table + .import hpux_syscall_exit,code + .export hpux_gateway_page + + .align 4096 +hpux_gateway_page: + nop + mfsp %sr7,%r1 ;! we must set sr3 to the space + mtsp %r1,%sr3 ;! of the user before the gate +#ifdef __LP64__ +#warning NEEDS WORK for 64-bit +#endif + ldw -64(%r30), %r28 ;! 8th argument + ldw -60(%r30), %r19 ;! 7th argument + ldw -56(%r30), %r20 ;! 6th argument + ldw -52(%r30), %r21 ;! 5th argument + gate .+8, %r0 ;! become privileged + mtsp %r0,%sr4 ;! get kernel space into sr4 + mtsp %r0,%sr5 ;! get kernel space into sr5 + mtsp %r0,%sr6 ;! get kernel space into sr6 + mtsp %r0,%sr7 ;! get kernel space into sr7 + mfctl %cr30,%r1 ;! get the kernel task ptr + mtctl %r0,%cr30 ;! zero it (flag) + STREG %r30,TASK_PT_GR30(%r1) ;! preserve userspace sp + STREG %r2,TASK_PT_GR2(%r1) ;! preserve rp + STREG %r27,TASK_PT_GR27(%r1) ;! user dp + STREG %r31,TASK_PT_GR31(%r1) ;! preserve syscall return ptr + + loadgp ;! setup kernel dp + + ldo TASK_SZ_ALGN+64(%r1),%r30 ;! set up kernel stack + + stw %r21, -52(%r30) ;! 5th argument + stw %r20, -56(%r30) ;! 6th argument + stw %r19, -60(%r30) ;! 7th argument + stw %r28, -64(%r30) ;! 8th argument + + ldil L%hpux_call_table, %r21 + ldo R%hpux_call_table(%r21), %r21 + comiclr,>>= __NR_HPUX_syscalls, %r22, %r0 + b,n syscall_nosys + ldwx,s %r22(%r21), %r21 + ldil L%hpux_syscall_exit,%r2 + be 0(%sr7,%r21) + ldo R%hpux_syscall_exit(%r2),%r2 + +syscall_nosys: + ldil L%hpux_syscall_exit,%r1 + be R%hpux_syscall_exit(%sr7,%r1) + ldo -ENOSYS(%r0),%r28 + + .align 4096 + .export end_hpux_gateway_page +end_hpux_gateway_page: diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/ioctl.c linux/arch/parisc/hpux/ioctl.c --- v2.4.0-test11/linux/arch/parisc/hpux/ioctl.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/ioctl.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,63 @@ +/* + * linux/arch/parisc/hpux/ioctl.c + * + * implements some necessary HPUX ioctls. + */ + +/* + * Supported ioctls: + * TCGETA + * TCSETA + * TCSETAW + * TCSETAF + * TCSBRK + * TCXONC + * TCFLSH + * TIOCGWINSZ + * TIOCSWINSZ + * TIOCGPGRP + * TIOCSPGRP + */ + +#include +#include +#include +#include +#include + +int sys_ioctl(unsigned int, unsigned int, unsigned long); + +static int hpux_ioctl_t(int fd, unsigned long cmd, unsigned long arg) +{ + int result = -EOPNOTSUPP; + int nr = _IOC_NR(cmd); + switch (nr) { + case 106: + result = sys_ioctl(fd, TIOCSWINSZ, arg); + break; + case 107: + result = sys_ioctl(fd, TIOCGWINSZ, arg); + break; + } + return result; +} + +int hpux_ioctl(int fd, unsigned long cmd, unsigned long arg) +{ + int result = -EOPNOTSUPP; + int type = _IOC_TYPE(cmd); + switch (type) { + case 'T': + /* Our structures are now compatible with HPUX's */ + result = sys_ioctl(fd, cmd, arg); + break; + case 't': + result = hpux_ioctl_t(fd, cmd, arg); + break; + default: + /* If my mother ever sees this, I hope she disowns me. + * Take this out after NYLWE. */ + result = sys_ioctl(fd, cmd, arg); + } + return result; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/sys_hpux.c linux/arch/parisc/hpux/sys_hpux.c --- v2.4.0-test11/linux/arch/parisc/hpux/sys_hpux.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/sys_hpux.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,334 @@ +/* + * linux/arch/parisc/kernel/sys_hpux.c + * + * implements HPUX syscalls. + */ + +#include +#include +#include +#include +#include + +unsigned long sys_brk(unsigned long addr); + +unsigned long hpux_brk(unsigned long addr) +{ + /* Sigh. Looks like HP/UX libc relies on kernel bugs. */ + return sys_brk(addr + PAGE_SIZE); +} + +int hpux_sbrk(void) +{ + return -ENOSYS; +} + +/* Random other syscalls */ + +int hpux_nice(int priority_change) +{ + return -ENOSYS; +} + +int hpux_ptrace(void) +{ + return -ENOSYS; +} + +int hpux_wait(int *stat_loc) +{ + extern int sys_waitpid(int, int *, int); + return sys_waitpid(-1, stat_loc, 0); +} + +#define _SC_CPU_VERSION 10001 +#define _SC_OPEN_MAX 4 +#define CPU_PA_RISC1_1 0x210 + +int hpux_sysconf(int which) +{ + switch (which) { + case _SC_CPU_VERSION: + return CPU_PA_RISC1_1; + case _SC_OPEN_MAX: + return INT_MAX; + default: + return -EINVAL; + } +} + +/*****************************************************************************/ + +#define HPUX_UTSLEN 9 +#define HPUX_SNLEN 15 + +struct hpux_utsname { + char sysname[HPUX_UTSLEN]; + char nodename[HPUX_UTSLEN]; + char release[HPUX_UTSLEN]; + char version[HPUX_UTSLEN]; + char machine[HPUX_UTSLEN]; + char idnumber[HPUX_SNLEN]; +} ; + +struct hpux_ustat { + int32_t f_tfree; /* total free (daddr_t) */ + u_int32_t f_tinode; /* total inodes free (ino_t) */ + char f_fname[6]; /* filsys name */ + char f_fpack[6]; /* filsys pack name */ + u_int32_t f_blksize; /* filsys block size (int) */ +}; + +/* + * HPUX's utssys() call. It's a collection of miscellaneous functions, + * alas, so there's no nice way of splitting them up. + */ + +/* This function is called from hpux_utssys(); HP-UX implements + * ustat() as an option to utssys(). + * + * Now, struct ustat on HP-UX is exactly the same as on Linux, except + * that it contains one addition field on the end, int32_t f_blksize. + * So, we could have written this function to just call the Linux + * sys_ustat(), (defined in linux/fs/super.c), and then just + * added this additional field to the user's structure. But I figure + * if we're gonna be digging through filesystem structures to get + * this, we might as well just do the whole enchilada all in one go. + * + * So, most of this function is almost identical to sys_ustat(). + * I have placed comments at the few lines changed or added, to + * aid in porting forward if and when sys_ustat() is changed from + * its form in kernel 2.2.5. + */ +static int hpux_ustat(dev_t dev, struct hpux_ustat *ubuf) +{ + struct super_block *s; + struct hpux_ustat tmp; /* Changed to hpux_ustat */ + struct statfs sbuf; + int err = -EINVAL; + + lock_kernel(); + s = get_super(to_kdev_t(dev)); + if (s == NULL) + goto out; + err = vfs_statfs(s, &sbuf); + if (err) + goto out; + + memset(&tmp,0,sizeof(struct hpux_ustat)); /* Changed to hpux_ustat */ + + tmp.f_tfree = (int32_t)sbuf.f_bfree; + tmp.f_tinode = (u_int32_t)sbuf.f_ffree; + tmp.f_blksize = (u_int32_t)sbuf.f_bsize; /* Added this line */ + + /* Changed to hpux_ustat: */ + err = copy_to_user(ubuf,&tmp,sizeof(struct hpux_ustat)) ? -EFAULT : 0; +out: + unlock_kernel(); + return err; +} + + +/* This function is called from hpux_utssys(); HP-UX implements + * uname() as an option to utssys(). + * + * The form of this function is pretty much copied from sys_olduname(), + * defined in linux/arch/i386/kernel/sys_i386.c. + */ +/* TODO: Are these put_user calls OK? Should they pass an int? + * (I copied it from sys_i386.c like this.) + */ +static int hpux_uname(struct hpux_utsname *name) +{ + int error; + + if (!name) + return -EFAULT; + if (!access_ok(VERIFY_WRITE,name,sizeof(struct hpux_utsname))) + return -EFAULT; + + down_read(&uts_sem); + + error = __copy_to_user(&name->sysname,&system_utsname.sysname,HPUX_UTSLEN-1); + error |= __put_user(0,name->sysname+HPUX_UTSLEN-1); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename,HPUX_UTSLEN-1); + error |= __put_user(0,name->nodename+HPUX_UTSLEN-1); + error |= __copy_to_user(&name->release,&system_utsname.release,HPUX_UTSLEN-1); + error |= __put_user(0,name->release+HPUX_UTSLEN-1); + error |= __copy_to_user(&name->version,&system_utsname.version,HPUX_UTSLEN-1); + error |= __put_user(0,name->version+HPUX_UTSLEN-1); + error |= __copy_to_user(&name->machine,&system_utsname.machine,HPUX_UTSLEN-1); + error |= __put_user(0,name->machine+HPUX_UTSLEN-1); + + up_read(&uts_sem); + + /* HP-UX utsname has no domainname field. */ + + /* TODO: Implement idnumber!!! */ +#if 0 + error |= __put_user(0,name->idnumber); + error |= __put_user(0,name->idnumber+HPUX_SNLEN-1); +#endif + + error = error ? -EFAULT : 0; + + return error; +} + +int sys_sethostname(char *, int); +int sys_gethostname(char *, int); + +/* Note: HP-UX just uses the old suser() function to check perms + * in this system call. We'll use capable(CAP_SYS_ADMIN). + */ +int hpux_utssys(char *ubuf, int n, int type) +{ + int len; + int error; + switch( type ) { + case 0: + /* uname(): */ + return( hpux_uname( (struct hpux_utsname *)ubuf ) ); + break ; + case 1: + /* Obsolete (used to be umask().) */ + return -EFAULT ; + break ; + case 2: + /* ustat(): */ + return( hpux_ustat((dev_t)n, (struct hpux_ustat *)ubuf) ); + break ; + case 3: + /* setuname(): + * + * On linux (unlike HP-UX), utsname.nodename + * is the same as the hostname. + * + * sys_sethostname() is defined in linux/kernel/sys.c. + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + /* Unlike Linux, HP-UX returns an error if n==0: */ + if ( n <= 0 ) + return -EINVAL ; + /* Unlike Linux, HP-UX truncates it if n is too big: */ + len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; + return( sys_sethostname(ubuf, len) ); + break ; + case 4: + /* sethostname(): + * + * sys_sethostname() is defined in linux/kernel/sys.c. + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + /* Unlike Linux, HP-UX returns an error if n==0: */ + if ( n <= 0 ) + return -EINVAL ; + /* Unlike Linux, HP-UX truncates it if n is too big: */ + len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; + return( sys_sethostname(ubuf, len) ); + break ; + case 5: + /* gethostname(): + * + * sys_gethostname() is defined in linux/kernel/sys.c. + */ + /* Unlike Linux, HP-UX returns an error if n==0: */ + if ( n <= 0 ) + return -EINVAL ; + return( sys_gethostname(ubuf, n) ); + break ; + case 6: + /* Supposedly called from setuname() in libc. + * TODO: When and why is this called? + * Is it ever even called? + * + * This code should look a lot like sys_sethostname(), + * defined in linux/kernel/sys.c. If that gets updated, + * update this code similarly. + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + /* Unlike Linux, HP-UX returns an error if n==0: */ + if ( n <= 0 ) + return -EINVAL ; + /* Unlike Linux, HP-UX truncates it if n is too big: */ + len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; + /**/ + /* TODO: print a warning about using this? */ + down_write(&uts_sem); + error = -EFAULT; + if (!copy_from_user(system_utsname.sysname, ubuf, len)) { + system_utsname.sysname[len] = 0; + error = 0; + } + up_write(&uts_sem); + return error; + break ; + case 7: + /* Sets utsname.release, if you're allowed. + * Undocumented. Used by swinstall to change the + * OS version, during OS updates. Yuck!!! + * + * This code should look a lot like sys_sethostname() + * in linux/kernel/sys.c. If that gets updated, update + * this code similarly. + */ + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + /* Unlike Linux, HP-UX returns an error if n==0: */ + if ( n <= 0 ) + return -EINVAL ; + /* Unlike Linux, HP-UX truncates it if n is too big: */ + len = (n <= __NEW_UTS_LEN) ? n : __NEW_UTS_LEN ; + /**/ + /* TODO: print a warning about this? */ + down_write(&uts_sem); + error = -EFAULT; + if (!copy_from_user(system_utsname.release, ubuf, len)) { + system_utsname.release[len] = 0; + error = 0; + } + up_write(&uts_sem); + return error; + break ; + default: + /* This system call returns -EFAULT if given an unknown type. + * Why not -EINVAL? I don't know, it's just not what they did. + */ + return -EFAULT ; + } +} + +int hpux_getdomainname(char *name, int len) +{ + int nlen; + int err = -EFAULT; + + down_read(&uts_sem); + + nlen = strlen(system_utsname.domainname) + 1; + + if (nlen < len) + len = nlen; + if(len > __NEW_UTS_LEN) + goto done; + if(copy_to_user(name, system_utsname.domainname, len)) + goto done; + err = 0; +done: + up_read(&uts_sem); + return err; + +} + +int hpux_pipe(int *kstack_fildes) +{ + int error; + + lock_kernel(); + error = do_pipe(kstack_fildes); + unlock_kernel(); + return error; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/hpux/wrappers.S linux/arch/parisc/hpux/wrappers.S --- v2.4.0-test11/linux/arch/parisc/hpux/wrappers.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/hpux/wrappers.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,244 @@ +/*------------------------------------------------------------------------------ + * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) + * + * HP-UX System Call Wrapper routines and System Call Return Path + * + * Copyright (C) 2000 Hewlett-Packard (John Marvin) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef __LP64__ +#warning Must be changed for PA64 +#endif + +#include + + .level 1.1 + .text + +#define __ASSEMBLY__ +#include +#include + + /* These should probably go in a header file somewhere. + * They are duplicated in kernel/wrappers.S + * Possibly we should consider consolidating these + * register save/restore macros. + */ + .macro reg_save regs +#ifdef __LP64__ +#warning NEEDS WORK for 64-bit +#endif + stw %r3, PT_GR3(\regs) + stw %r4, PT_GR4(\regs) + stw %r5, PT_GR5(\regs) + stw %r6, PT_GR6(\regs) + stw %r7, PT_GR7(\regs) + stw %r8, PT_GR8(\regs) + stw %r9, PT_GR9(\regs) + stw %r10,PT_GR10(\regs) + stw %r11,PT_GR11(\regs) + stw %r12,PT_GR12(\regs) + stw %r13,PT_GR13(\regs) + stw %r14,PT_GR14(\regs) + stw %r15,PT_GR15(\regs) + stw %r16,PT_GR16(\regs) + stw %r17,PT_GR17(\regs) + stw %r18,PT_GR18(\regs) + .endm + + .macro reg_restore regs + ldw PT_GR3(\regs), %r3 + ldw PT_GR4(\regs), %r4 + ldw PT_GR5(\regs), %r5 + ldw PT_GR6(\regs), %r6 + ldw PT_GR7(\regs), %r7 + ldw PT_GR8(\regs), %r8 + ldw PT_GR9(\regs), %r9 + ldw PT_GR10(\regs),%r10 + ldw PT_GR11(\regs),%r11 + ldw PT_GR12(\regs),%r12 + ldw PT_GR13(\regs),%r13 + ldw PT_GR14(\regs),%r14 + ldw PT_GR15(\regs),%r15 + ldw PT_GR16(\regs),%r16 + ldw PT_GR17(\regs),%r17 + ldw PT_GR18(\regs),%r18 + .endm + + + .export hpux_fork_wrapper + .import sys_fork + +hpux_fork_wrapper: + ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs + ;! pointer in task + reg_save %r1 + + stw %r2,-20(%r30) + ldo 64(%r30),%r30 + stw %r2,PT_GR19(%r1) ;! save for child + stw %r30,PT_GR20(%r1) ;! save for child + ldil L%child_return,%r3 + ldo R%child_return(%r3),%r3 + stw %r3,PT_GR21(%r1) ;! save for child + + ldw TASK_PT_GR30(%r1),%r25 + copy %r1,%r24 + bl sys_clone,%r2 + ldi SIGCHLD,%r26 + + ldw -84(%r30),%r2 +fork_return: + ldo -64(%r30),%r30 + ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs + + reg_restore %r1 + + /* + * HP-UX wants pid (child gets parent pid, parent gets child pid) + * in r28 and a flag in r29 (r29 == 1 for child, 0 for parent). + * Linux fork returns 0 for child, pid for parent. Since HP-UX + * libc stub throws away parent pid and returns 0 for child, + * we'll just return 0 for parent pid now. Only applications + * that jump directly to the gateway page (not supported) will + * know the difference. We can fix this later if necessary. + */ + + ldo -1024(%r0),%r1 + comb,>>=,n %r28,%r1,fork_exit /* just let the syscall exit handle it */ + or,= %r28,%r0,%r0 + or,tr %r0,%r0,%r29 /* r28 <> 0, we are parent, set r29 to 0 */ + ldo 1(%r0),%r29 /* r28 == 0, we are child, set r29 to 1 */ + +fork_exit: + bv %r0(%r2) + nop + + /* Set the return value for the child */ + +child_return: + ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 + b fork_return + copy %r0,%r28 + + .export hpux_execve_wrapper + .export hpux_execv_wrapper + .import hpux_execve + +hpux_execv_wrapper: + copy %r0,%r24 /* NULL environment */ + +hpux_execve_wrapper: + + ldo TASK_REGS-TASK_SZ_ALGN-64(%r30),%r1 ;! get pt regs + + /* + * Do we need to save/restore r3-r18 here? + * I don't think so. why would new thread need old + * threads registers? + */ + + /* Store arg0, arg1 and arg2 so that hpux_execve will find them */ + + stw %r26,PT_GR26(%r1) + stw %r25,PT_GR25(%r1) + stw %r24,PT_GR24(%r1) + + stw %r2,-20(%r30) + ldo 64(%r30),%r30 + bl hpux_execve,%r2 + copy %r1,%arg0 + + ldo -64(%r30),%r30 + ldw -20(%r30),%r2 + + /* If exec succeeded we need to load the args */ + + ldo -1024(%r0),%r1 + comb,>>= %r28,%r1,exec_error + copy %r2,%r19 + ldo -TASK_SZ_ALGN-64(%r30),%r1 ;! get task ptr + ldw TASK_PT_GR26(%r1),%r26 + ldw TASK_PT_GR25(%r1),%r25 + ldw TASK_PT_GR24(%r1),%r24 + ldw TASK_PT_GR23(%r1),%r23 + copy %r0,%r2 /* Flag to syscall_exit not to clear args */ + +exec_error: + bv %r0(%r19) + nop + + .export hpux_pipe_wrapper + .import hpux_pipe + + /* HP-UX expects pipefd's returned in r28 & r29 */ + +hpux_pipe_wrapper: + stw %r2,-20(%r30) + ldo 64(%r30),%r30 + bl hpux_pipe,%r2 + ldo -56(%r30),%r26 /* pass local array to hpux_pipe */ + + + ldo -1024(%r0),%r1 + comb,>>= %r28,%r1,pipe_exit /* let syscall exit handle it */ + ldw -84(%r30),%r2 + + /* if success, load fd's from stack array */ + + ldw -56(%r30),%r28 + ldw -52(%r30),%r29 + +pipe_exit: + bv %r0(%r2) + ldo -64(%r30),%r30 + + .export hpux_syscall_exit + .import syscall_exit + +hpux_syscall_exit: + + /* + * + * HP-UX call return conventions: + * + * if error: + * r22 = 1 + * r28 = errno value + * r29 = secondary return value + * else + * r22 = 0 + * r28 = return value + * r29 = secondary return value + * + * For now, we'll just check to see if r28 is < (unsigned long)-1024 + * (to handle addresses > 2 Gb) and if so set r22 to zero. If not, + * we'll complement r28 and set r22 to 1. Wrappers will be + * needed for syscalls that care about the secondary return value. + * The wrapper may also need a way of avoiding the following code, + * but we'll deal with that when it becomes necessary. + */ + + ldo -1024(%r0),%r1 + comb,<< %r28,%r1,no_error + copy %r0,%r22 + subi 0,%r28,%r28 + ldo 1(%r0),%r22 + +no_error: + b syscall_exit + nop diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/Makefile linux/arch/parisc/kernel/Makefile --- v2.4.0-test11/linux/arch/parisc/kernel/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/Makefile Tue Dec 5 12:29:39 2000 @@ -0,0 +1,52 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +all: kernel.o init_task.o pdc_cons.o process.o head.o +O_TARGET = kernel.o +O_OBJS = + +# Object file lists. + +obj-y := +obj-m := +obj-n := +obj- := + +obj-y += cache.o setup.o traps.o time.o irq.o \ + syscall.o entry.o sys_parisc.o pdc.o ptrace.o hardware.o \ + inventory.o drivers.o semaphore.o pa7300lc.o pci-dma.o \ + signal.o hpmc.o \ + real1.o real2.o led.o parisc_ksyms.o + +export-objs := parisc_ksyms.o + + +obj-$(CONFIG_PCI) += pci.o +obj-$(CONFIG_VT) += keyboard.o +obj-$(CONFIG_PCI_LBA) += lba_pci.o +# I/O SAPIC is also on IA64 platforms. +# The two could be merged into a common source some day. +obj-$(CONFIG_IOSAPIC) += iosapic.o +obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o +# Only use one of them: ccio-rm-dma is for PCX-W systems *only* +# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o +obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o + +.o.S: $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o + +# Translate to Rules.make lists. + +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) +MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m))) +MIX_OBJS := $(sort $(filter $(export-objs), $(int-m))) + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/cache.c linux/arch/parisc/kernel/cache.c --- v2.4.0-test11/linux/arch/parisc/kernel/cache.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/cache.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,253 @@ +/* $Id: cache.c,v 1.4 2000/01/25 00:11:38 prumpf Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 Helge Deller (07-13-1999) + * Copyright (C) 1999 SuSE GmbH Nuernberg + * Copyright (C) 2000 Philipp Rumpf (prumpf@tux.org) + * + * Cache and TLB management + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +struct pdc_cache_info cache_info; +#ifndef __LP64__ +static struct pdc_btlb_info btlb_info; +#endif + + +void __flush_page_to_ram(unsigned long address) +{ + __flush_dcache_range(address, PAGE_SIZE); + __flush_icache_range(address, PAGE_SIZE); +} + + + +void flush_data_cache(void) +{ + register unsigned long base = cache_info.dc_base; + register unsigned long count = cache_info.dc_count; + register unsigned long loop = cache_info.dc_loop; + register unsigned long stride = cache_info.dc_stride; + register unsigned long addr; + register long i, j; + + for(i=0,addr=base; i>8, + btlb_info.fixed_range_info.num_i, + btlb_info.fixed_range_info.num_d, + btlb_info.fixed_range_info.num_comb, + btlb_info.variable_range_info.num_i, + btlb_info.variable_range_info.num_d, + btlb_info.variable_range_info.num_comb + ); + } +#endif + + return p - buffer; +} + + +void __init +cache_init(void) +{ + if(pdc_cache_info(&cache_info)<0) + panic("cache_init: pdc_cache_info failed"); + +#if 0 + printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n", + cache_info.ic_size, + cache_info.dc_size, + cache_info.it_size, + sizeof (struct pdc_cache_info) / sizeof (long), + sizeof (struct pdc_cache_cf) + ); +#endif +#ifndef __LP64__ + if(pdc_btlb_info(&btlb_info)<0) { + memset(&btlb_info, 0, sizeof btlb_info); + } +#endif +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/ccio-dma.c linux/arch/parisc/kernel/ccio-dma.c --- v2.4.0-test11/linux/arch/parisc/kernel/ccio-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/ccio-dma.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,1209 @@ +/* +** ccio-dma.c: +** DMA management routines for first generation cache-coherent machines. +** Program U2/Uturn in "Virtual Mode" and use the I/O MMU. +** +** (c) Copyright 2000 Grant Grundler +** (c) Copyright 2000 Ryan Bradetich +** (c) Copyright 2000 Hewlett-Packard Company +** +** 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. +** +** +** "Real Mode" operation refers to U2/Uturn chip operation. +** U2/Uturn were designed to perform coherency checks w/o using +** the I/O MMU - basically what x86 does. +** +** Philipp Rumpf has a "Real Mode" driver for PCX-W machines at: +** CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc +** cvs -z3 co linux/arch/parisc/kernel/dma-rm.c +** +** I've rewritten his code to work under TPG's tree. See ccio-rm-dma.c. +** +** Drawbacks of using Real Mode are: +** o outbound DMA is slower - U2 won't prefetch data (GSC+ XQL signal). +** o Inbound DMA less efficient - U2 can't use DMA_FAST attribute. +** o Ability to do scatter/gather in HW is lost. +** o Doesn't work under PCX-U/U+ machines since they didn't follow +** the coherency design originally worked out. Only PCX-W does. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* for L1_CACHE_BYTES */ +#include +#include +#include + +#include +#include /* for gsc_writeN()... */ + +/* +** Choose "ccio" since that's what HP-UX calls it. +** Make it easier for folks to migrate from one to the other :^) +*/ +#define MODULE_NAME "ccio" + +/* +#define DEBUG_CCIO_RES +#define DEBUG_CCIO_RUN +#define DEBUG_CCIO_INIT +#define DUMP_RESMAP +*/ + +#include +#include /* for proc_runway_root */ + +#ifdef DEBUG_CCIO_INIT +#define DBG_INIT(x...) printk(x) +#else +#define DBG_INIT(x...) +#endif + +#ifdef DEBUG_CCIO_RUN +#define DBG_RUN(x...) printk(x) +#else +#define DBG_RUN(x...) +#endif + +#ifdef DEBUG_CCIO_RES +#define DBG_RES(x...) printk(x) +#else +#define DBG_RES(x...) +#endif + +#define CCIO_INLINE /* inline */ +#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr)) + +#define U2_IOA_RUNWAY 0x580 +#define U2_BC_GSC 0x501 +#define UTURN_IOA_RUNWAY 0x581 +#define UTURN_BC_GSC 0x502 +/* We *can't* support JAVA (T600). Venture there at your own risk. */ + +static void dump_resmap(void); + +static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *); + +static struct pa_iodc_driver ccio_drivers_for[] = { + + {HPHW_IOA, U2_IOA_RUNWAY, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback}, + + {HPHW_IOA, UTURN_IOA_RUNWAY, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback}, + +/* +** FIXME: The following claims the GSC bus port, not the IOA. +** And there are two busses below a single I/O TLB. +** +** These should go away once we have a real PA bus walk. +** Firmware wants to tell the PA bus walk code about the GSC ports +** since they are not "architected" PA I/O devices. Ie a PA bus walk +** wouldn't discover them. But the PA bus walk code could check +** the "fixed module table" to add such devices to an I/O Tree +** and proceed with the recursive, depth first bus walk. +*/ + {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xc, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "U2 GSC+ BC", (void *) ccio_driver_callback}, + + {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xc, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "Uturn GSC+ BC", (void *) ccio_driver_callback}, + + {0,0,0,0,0,0, + 0, + (char *) NULL, (char *) NULL, (void *) NULL } +}; + + +#define IS_U2(id) ( \ + (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \ + (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \ +) + +#define IS_UTURN(id) ( \ + (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \ + (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \ +) + + +#define IOA_NORMAL_MODE 0x00020080 /* IO_CONTROL to turn on CCIO */ +#define CMD_TLB_DIRECT_WRITE 35 /* IO_COMMAND for I/O TLB Writes */ +#define CMD_TLB_PURGE 33 /* IO_COMMAND to Purge I/O TLB entry */ + +struct ioa_registers { + /* Runway Supervisory Set */ + volatile int32_t unused1[12]; + volatile uint32_t io_command; /* Offset 12 */ + volatile uint32_t io_status; /* Offset 13 */ + volatile uint32_t io_control; /* Offset 14 */ + volatile int32_t unused2[1]; + + /* Runway Auxiliary Register Set */ + volatile uint32_t io_err_resp; /* Offset 0 */ + volatile uint32_t io_err_info; /* Offset 1 */ + volatile uint32_t io_err_req; /* Offset 2 */ + volatile uint32_t io_err_resp_hi; /* Offset 3 */ + volatile uint32_t io_tlb_entry_m; /* Offset 4 */ + volatile uint32_t io_tlb_entry_l; /* Offset 5 */ + volatile uint32_t unused3[1]; + volatile uint32_t io_pdir_base; /* Offset 7 */ + volatile uint32_t io_io_low_hv; /* Offset 8 */ + volatile uint32_t io_io_high_hv; /* Offset 9 */ + volatile uint32_t unused4[1]; + volatile uint32_t io_chain_id_mask; /* Offset 11 */ + volatile uint32_t unused5[2]; + volatile uint32_t io_io_low; /* Offset 14 */ + volatile uint32_t io_io_high; /* Offset 15 */ +}; + + +struct ccio_device { + struct ccio_device *next; /* list of LBA's in system */ + struct hp_device *iodc; /* data about dev from firmware */ + spinlock_t ccio_lock; + + struct ioa_registers *ccio_hpa; /* base address */ + u64 *pdir_base; /* physical base address */ + char *res_map; /* resource map, bit == pdir entry */ + + int res_hint; /* next available IOVP - circular search */ + int res_size; /* size of resource map in bytes */ + int chainid_shift; /* specify bit location of chain_id */ + int flags; /* state/functionality enabled */ +#ifdef DELAYED_RESOURCE_CNT + dma_addr_t res_delay[DELAYED_RESOURCE_CNT]; +#endif + + /* STUFF We don't need in performance path */ + int pdir_size; /* in bytes, determined by IOV Space size */ + int hw_rev; /* HW revision of chip */ +}; + + +/* Ratio of Host MEM to IOV Space size */ +static unsigned long ccio_mem_ratio = 4; +static struct ccio_device *ccio_list = NULL; + +static int ccio_proc_info(char *buffer, char **start, off_t offset, int length); +static unsigned long ccio_used_bytes = 0; +static unsigned long ccio_used_pages = 0; +static int ccio_cujo_bug = 0; + +static unsigned long ccio_alloc_size = 0; +static unsigned long ccio_free_size = 0; + +/************************************************************** +* +* I/O Pdir Resource Management +* +* Bits set in the resource map are in use. +* Each bit can represent a number of pages. +* LSbs represent lower addresses (IOVA's). +* +* This was was copied from sba_iommu.c. Don't try to unify +* the two resource managers unless a way to have different +* allocation policies is also adjusted. We'd like to avoid +* I/O TLB thrashing by having resource allocation policy +* match the I/O TLB replacement policy. +* +***************************************************************/ +#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ +#define IOVP_SIZE PAGE_SIZE +#define IOVP_SHIFT PAGE_SHIFT +#define IOVP_MASK PAGE_MASK + +/* Convert from IOVP to IOVA and vice versa. */ +#define CCIO_IOVA(iovp,offset) ((iovp) | (offset)) +#define CCIO_IOVP(iova) ((iova) & ~(IOVP_SIZE-1) ) + +#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) +#define MKIOVP(pdir_idx) ((long)(pdir_idx) << IOVP_SHIFT) +#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset) + +/* CUJO20 KLUDGE start */ +#define CUJO_20_BITMASK 0x0ffff000 /* upper nibble is a don't care */ +#define CUJO_20_STEP 0x10000000 /* inc upper nibble */ +#define CUJO_20_BADPAGE1 0x01003000 /* pages that hpmc on raven U+ */ +#define CUJO_20_BADPAGE2 0x01607000 /* pages that hpmc on firehawk U+ */ +#define CUJO_20_BADHVERS 0x6821 /* low nibble 1 is cujo rev 2.0 */ +#define CUJO_RAVEN_LOC 0xf1000000UL /* cujo location on raven U+ */ +#define CUJO_FIREHAWK_LOC 0xf1604000UL /* cujo location on firehawk U+ */ +/* CUJO20 KLUDGE end */ + +/* +** Don't worry about the 150% average search length on a miss. +** If the search wraps around, and passes the res_hint, it will +** cause the kernel to panic anyhow. +*/ + +/* ioa->res_hint = idx + (size >> 3); \ */ + +#define CCIO_SEARCH_LOOP(ioa, idx, mask, size) \ + for(; res_ptr < res_end; ++res_ptr) \ + { \ + if(0 == ((*res_ptr) & mask)) { \ + *res_ptr |= mask; \ + idx = (int)((unsigned long)res_ptr - (unsigned long)ioa->res_map); \ + ioa->res_hint = 0;\ + goto resource_found; \ + } \ + } + +#define CCIO_FIND_FREE_MAPPING(ioa, idx, mask, size) { \ + u##size *res_ptr = (u##size *)&((ioa)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \ + u##size *res_end = (u##size *)&(ioa)->res_map[ioa->res_size]; \ + CCIO_SEARCH_LOOP(ioa, idx, mask, size); \ + res_ptr = (u##size *)&(ioa)->res_map[0]; \ + CCIO_SEARCH_LOOP(ioa, idx, mask, size); \ +} + +/* +** Find available bit in this ioa's resource map. +** Use a "circular" search: +** o Most IOVA's are "temporary" - avg search time should be small. +** o keep a history of what happened for debugging +** o KISS. +** +** Perf optimizations: +** o search for log2(size) bits at a time. +** o search for available resource bits using byte/word/whatever. +** o use different search for "large" (eg > 4 pages) or "very large" +** (eg > 16 pages) mappings. +*/ +static int +ccio_alloc_range(struct ccio_device *ioa, size_t size) +{ + int res_idx; + unsigned long mask, flags; + unsigned int pages_needed = size >> PAGE_SHIFT; + + ASSERT(pages_needed); + ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE); + ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT)); + + mask = (unsigned long) -1L; + mask >>= BITS_PER_LONG - pages_needed; + + DBG_RES(__FUNCTION__ " size: %d pages_needed %d pages_mask 0x%08lx\n", + size, pages_needed, mask); + + spin_lock_irqsave(&ioa->ccio_lock, flags); + + /* + ** "seek and ye shall find"...praying never hurts either... + ** ggg sacrafices another 710 to the computer gods. + */ + + if(pages_needed <= 8) { + CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 8); + } else if(pages_needed <= 16) { + CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 16); + } else if(pages_needed <= 32) { + CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 32); +#ifdef __LP64__ + } else if(pages_needed <= 64) { + CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 64) +#endif + } else { + panic(__FILE__ ":" __FUNCTION__ "() Too many pages to map.\n"); + } + +#ifdef DUMP_RESMAP + dump_resmap(); +#endif + panic(__FILE__ ":" __FUNCTION__ "() I/O MMU is out of mapping resources\n"); + +resource_found: + + DBG_RES(__FUNCTION__ " res_idx %d mask 0x%08lx res_hint: %d\n", + res_idx, mask, ioa->res_hint); + + ccio_used_pages += pages_needed; + ccio_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1); + + spin_unlock_irqrestore(&ioa->ccio_lock, flags); + +#ifdef DUMP_RESMAP + dump_resmap(); +#endif + + /* + ** return the bit address (convert from byte to bit). + */ + return (res_idx << 3); +} + + +#define CCIO_FREE_MAPPINGS(ioa, idx, mask, size) \ + u##size *res_ptr = (u##size *)&((ioa)->res_map[idx + (((size >> 3) - 1) & ~((size >> 3) - 1))]); \ + ASSERT((*res_ptr & mask) == mask); \ + *res_ptr &= ~mask; + +/* +** clear bits in the ioa's resource map +*/ +static void +ccio_free_range(struct ccio_device *ioa, dma_addr_t iova, size_t size) +{ + unsigned long mask, flags; + unsigned long iovp = CCIO_IOVP(iova); + unsigned int res_idx = PDIR_INDEX(iovp)>>3; + unsigned int pages_mapped = (size >> IOVP_SHIFT) + !!(size & ~IOVP_MASK); + + ASSERT(pages_needed); + ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE); + ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT)); + + mask = (unsigned long) -1L; + mask >>= BITS_PER_LONG - pages_mapped; + + DBG_RES(__FUNCTION__ " res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n", + res_idx, size, pages_mapped, mask); + + spin_lock_irqsave(&ioa->ccio_lock, flags); + + if(pages_mapped <= 8) { + CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 8); + } else if(pages_mapped <= 16) { + CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 16); + } else if(pages_mapped <= 32) { + CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 32); +#ifdef __LP64__ + } else if(pages_mapped <= 64) { + CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 64); +#endif + } else { + panic(__FILE__ ":" __FUNCTION__ "() Too many pages to unmap.\n"); + } + + ccio_used_pages -= (pages_mapped ? pages_mapped : 1); + ccio_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1); + + spin_unlock_irqrestore(&ioa->ccio_lock, flags); + +#ifdef DUMP_RESMAP + dump_resmap(); +#endif +} + + +/**************************************************************** +** +** CCIO dma_ops support routines +** +*****************************************************************/ + +typedef unsigned long space_t; +#define KERNEL_SPACE 0 + + +/* +** DMA "Page Type" and Hints +** o if SAFE_DMA isn't set, mapping is for FAST_DMA. SAFE_DMA should be +** set for subcacheline DMA transfers since we don't want to damage the +** other part of a cacheline. +** o SAFE_DMA must be set for "memory" allocated via pci_alloc_consistent(). +** This bit tells U2 to do R/M/W for partial cachelines. "Streaming" +** data can avoid this if the mapping covers full cache lines. +** o STOP_MOST is needed for atomicity across cachelines. +** Apperently only "some EISA devices" need this. +** Using CONFIG_ISA is hack. Only the IOA with EISA under it needs +** to use this hint iff the EISA devices needs this feature. +** According to the U2 ERS, STOP_MOST enabled pages hurt performance. +** o PREFETCH should *not* be set for cases like Multiple PCI devices +** behind GSCtoPCI (dino) bus converter. Only one cacheline per GSC +** device can be fetched and multiply DMA streams will thrash the +** prefetch buffer and burn memory bandwidth. See 6.7.3 "Prefetch Rules +** and Invalidation of Prefetch Entries". +** +** FIXME: the default hints need to be per GSC device - not global. +** +** HP-UX dorks: linux device driver programming model is totally different +** than HP-UX's. HP-UX always sets HINT_PREFETCH since it's drivers +** do special things to work on non-coherent platforms...linux has to +** be much more careful with this. +*/ +#define IOPDIR_VALID 0x01UL +#define HINT_SAFE_DMA 0x02UL /* used for pci_alloc_consistent() pages */ +#ifdef CONFIG_ISA /* EISA support really */ +#define HINT_STOP_MOST 0x04UL /* LSL support */ +#else +#define HINT_STOP_MOST 0x00UL /* only needed for "some EISA devices" */ +#endif +#define HINT_UDPATE_ENB 0x08UL /* not used/supported by U2 */ +#define HINT_PREFETCH 0x10UL /* for outbound pages which are not SAFE */ + + +/* +** Use direction (ie PCI_DMA_TODEVICE) to pick hint. +** ccio_alloc_consistent() depends on this to get SAFE_DMA +** when it passes in BIDIRECTIONAL flag. +*/ +static u32 hint_lookup[] = { + [PCI_DMA_BIDIRECTIONAL] HINT_STOP_MOST | HINT_SAFE_DMA | IOPDIR_VALID, + [PCI_DMA_TODEVICE] HINT_STOP_MOST | HINT_PREFETCH | IOPDIR_VALID, + [PCI_DMA_FROMDEVICE] HINT_STOP_MOST | IOPDIR_VALID, + [PCI_DMA_NONE] 0, /* not valid */ +}; + +/* +** Initialize an I/O Pdir entry +** +** Given a virtual address (vba, arg2) and space id, (sid, arg1), +** load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir +** entry consists of 8 bytes as shown below (MSB == bit 0): +** +** +** WORD 0: +** +------+----------------+-----------------------------------------------+ +** | Phys | Virtual Index | Phys | +** | 0:3 | 0:11 | 4:19 | +** |4 bits| 12 bits | 16 bits | +** +------+----------------+-----------------------------------------------+ +** WORD 1: +** +-----------------------+-----------------------------------------------+ +** | Phys | Rsvd | Prefetch |Update |Rsvd |Lock |Safe |Valid | +** | 20:39 | | Enable |Enable | |Enable|DMA | | +** | 20 bits | 5 bits | 1 bit |1 bit |2 bits|1 bit |1 bit |1 bit | +** +-----------------------+-----------------------------------------------+ +** +** The virtual index field is filled with the results of the LCI +** (Load Coherence Index) instruction. The 8 bits used for the virtual +** index are bits 12:19 of the value returned by LCI. +*/ + +void CCIO_INLINE +ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, void * vba, unsigned long hints) +{ + register unsigned long pa = (volatile unsigned long) vba; + register unsigned long ci; /* coherent index */ + + /* We currently only support kernel addresses */ + ASSERT(sid == 0); + ASSERT(((unsigned long) vba & 0xf0000000UL) == 0xc0000000UL); + + mtsp(sid,1); + + /* + ** WORD 1 - low order word + ** "hints" parm includes the VALID bit! + ** "dep" clobbers the physical address offset bits as well. + */ + pa = virt_to_phys(vba); + asm volatile("depw %1,31,12,%0" : "+r" (pa) : "r" (hints)); + ((u32 *)pdir_ptr)[1] = (u32) pa; + + /* + ** WORD 0 - high order word + */ + +#ifdef __LP64__ + /* + ** get bits 12:15 of physical address + ** shift bits 16:31 of physical address + ** and deposit them + */ + asm volatile ("extrd,u %1,15,4,%0" : "=r" (ci) : "r" (pa)); + asm volatile ("extrd,u %1,31,16,%0" : "+r" (ci) : "r" (ci)); + asm volatile ("depd %1,35,4,%0" : "+r" (pa) : "r" (ci)); +#else + pa = 0; +#endif + /* + ** get CPU coherency index bits + ** Grab virtual index [0:11] + ** Deposit virt_idx bits into I/O PDIR word + */ + asm volatile ("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba)); + asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci)); + asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci)); + + ((u32 *)pdir_ptr)[0] = (u32) pa; + + + /* FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360) + ** PCX-U/U+ do. (eg C200/C240) + ** PCX-T'? Don't know. (eg C110 or similar K-class) + ** + ** See PDC_MODEL/option 0/SW_CAP word for "Non-coherent IO-PDIR bit". + ** Hopefully we can patch (NOP) these out at boot time somehow. + ** + ** "Since PCX-U employs an offset hash that is incompatible with + ** the real mode coherence index generation of U2, the PDIR entry + ** must be flushed to memory to retain coherence." + */ + asm volatile("fdc 0(%0)" : : "r" (pdir_ptr)); + asm volatile("sync"); +} + + +/* +** Remove stale entries from the I/O TLB. +** Need to do this whenever an entry in the PDIR is marked invalid. +*/ +static CCIO_INLINE void +ccio_clear_io_tlb( struct ccio_device *d, dma_addr_t iovp, size_t byte_cnt) +{ + u32 chain_size = 1 << d->chainid_shift; + + iovp &= ~(IOVP_SIZE-1); /* clear offset bits, just want pagenum */ + byte_cnt += chain_size; + + while (byte_cnt > chain_size) { + WRITE_U32(CMD_TLB_PURGE | iovp, &d->ccio_hpa->io_command); + iovp += chain_size; + byte_cnt -= chain_size; + } +} + + +/*********************************************************** + * + * Mark the I/O Pdir entries invalid and blow away the + * corresponding I/O TLB entries. + * + * FIXME: at some threshhold it might be "cheaper" to just blow + * away the entire I/O TLB instead of individual entries. + * + * FIXME: Uturn has 256 TLB entries. We don't need to purge every + * PDIR entry - just once for each possible TLB entry. + * (We do need to maker I/O PDIR entries invalid regardless). + ***********************************************************/ +static CCIO_INLINE void +ccio_mark_invalid(struct ccio_device *d, dma_addr_t iova, size_t byte_cnt) +{ + u32 iovp = (u32) CCIO_IOVP(iova); + size_t saved_byte_cnt; + + /* round up to nearest page size */ + saved_byte_cnt = byte_cnt = (byte_cnt + IOVP_SIZE - 1) & IOVP_MASK; + + while (byte_cnt > 0) { + /* invalidate one page at a time */ + unsigned int idx = PDIR_INDEX(iovp); + char *pdir_ptr = (char *) &(d->pdir_base[idx]); + + ASSERT( idx < (d->pdir_size/sizeof(u64))); + + pdir_ptr[7] = 0; /* clear only VALID bit */ + + /* + ** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360) + ** PCX-U/U+ do. (eg C200/C240) + ** See PDC_MODEL/option 0/SW_CAP for "Non-coherent IO-PDIR bit". + ** + ** Hopefully someone figures out how to patch (NOP) the + ** FDC/SYNC out at boot time. + */ + asm volatile("fdc 0(%0)" : : "r" (pdir_ptr[7])); + + iovp += IOVP_SIZE; + byte_cnt -= IOVP_SIZE; + } + + asm volatile("sync"); + ccio_clear_io_tlb(d, CCIO_IOVP(iova), saved_byte_cnt); +} + + +/**************************************************************** +** +** CCIO dma_ops +** +*****************************************************************/ + +void __init ccio_init(void) +{ + register_driver(ccio_drivers_for); +} + + +static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask) +{ + if (dev == NULL) { + printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); + BUG(); + return(0); + } + + dev->dma_mask = mask; /* save it */ + + /* only support 32-bit devices (ie PCI/GSC) */ + return((int) (mask >= 0xffffffffUL)); +} + +/* +** Dump a hex representation of the resource map. +*/ + +#ifdef DUMP_RESMAP +static +void dump_resmap() +{ + struct ccio_device *ioa = ccio_list; + unsigned long *res_ptr = (unsigned long *)ioa->res_map; + unsigned long i = 0; + + printk("res_map: "); + for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr) + printk("%08lx ", *res_ptr); + + printk("\n"); +} +#endif + +/* +** map_single returns a fully formed IOVA +*/ +static dma_addr_t ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) +{ + struct ccio_device *ioa = ccio_list; /* FIXME : see Multi-IOC below */ + dma_addr_t iovp; + dma_addr_t offset; + u64 *pdir_start; + unsigned long hint = hint_lookup[direction]; + int idx; + + ASSERT(size > 0); + + /* save offset bits */ + offset = ((dma_addr_t) addr) & ~IOVP_MASK; + + /* round up to nearest IOVP_SIZE */ + size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK; + + idx = ccio_alloc_range(ioa, size); + iovp = (dma_addr_t) MKIOVP(idx); + + DBG_RUN(__FUNCTION__ " 0x%p -> 0x%lx", addr, (long) iovp | offset); + + pdir_start = &(ioa->pdir_base[idx]); + + /* If not cacheline aligned, force SAFE_DMA on the whole mess */ + if ((size % L1_CACHE_BYTES) || ((unsigned long) addr % L1_CACHE_BYTES)) + hint |= HINT_SAFE_DMA; + + /* round up to nearest IOVP_SIZE */ + size = (size + IOVP_SIZE - 1) & IOVP_MASK; + + while (size > 0) { + + ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint); + + DBG_RUN(" pdir %p %08x%08x\n", + pdir_start, + (u32) (((u32 *) pdir_start)[0]), + (u32) (((u32 *) pdir_start)[1]) + ); + addr += IOVP_SIZE; + size -= IOVP_SIZE; + pdir_start++; + } + /* form complete address */ + return CCIO_IOVA(iovp, offset); +} + + +static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction) +{ +#ifdef FIXME +/* Multi-IOC (ie N-class) : need to lookup IOC from dev +** o If we can't know about lba PCI data structs, that eliminates ->sysdata. +** o walking up pcidev->parent dead ends at elroy too +** o leaves hashing dev->bus->number into some lookup. +** (may only work for N-class) +*/ + struct ccio_device *ioa = dev->sysdata +#else + struct ccio_device *ioa = ccio_list; +#endif + dma_addr_t offset; + + offset = iova & ~IOVP_MASK; + + /* round up to nearest IOVP_SIZE */ + size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK; + + /* Mask off offset */ + iova &= IOVP_MASK; + + DBG_RUN(__FUNCTION__ " iovp 0x%lx\n", (long) iova); + +#ifdef DELAYED_RESOURCE_CNT + if (ioa->saved_cnt < DELAYED_RESOURCE_CNT) { + ioa->saved_iova[ioa->saved_cnt] = iova; + ioa->saved_size[ioa->saved_cnt] = size; + ccio_saved_cnt++; + } else { + do { +#endif + ccio_mark_invalid(ioa, iova, size); + ccio_free_range(ioa, iova, size); + +#ifdef DELAYED_RESOURCE_CNT + d->saved_cnt--; + iova = ioa->saved_iova[ioa->saved_cnt]; + size = ioa->saved_size[ioa->saved_cnt]; + } while (ioa->saved_cnt) + } +#endif +} + + +static void * ccio_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +{ + void *ret; + unsigned long flags; + struct ccio_device *ioa = ccio_list; + + DBG_RUN(__FUNCTION__ " size 0x%x\n", size); + +#if 0 +/* GRANT Need to establish hierarchy for non-PCI devs as well +** and then provide matching gsc_map_xxx() functions for them as well. +*/ + if (!hwdev) { + /* only support PCI */ + *dma_handle = 0; + return 0; + } +#endif + spin_lock_irqsave(&ioa->ccio_lock, flags); + ccio_alloc_size += get_order(size); + spin_unlock_irqrestore(&ioa->ccio_lock, flags); + + ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size)); + + if (ret) { + memset(ret, 0, size); + *dma_handle = ccio_map_single(hwdev, ret, size, PCI_DMA_BIDIRECTIONAL); + } + DBG_RUN(__FUNCTION__ " ret %p\n", ret); + + return ret; +} + + +static void ccio_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +{ + unsigned long flags; + struct ccio_device *ioa = ccio_list; + + spin_lock_irqsave(&ioa->ccio_lock, flags); + ccio_free_size += get_order(size); + spin_unlock_irqrestore(&ioa->ccio_lock, flags); + + ccio_unmap_single(hwdev, dma_handle, size, 0); + free_pages((unsigned long) vaddr, get_order(size)); +} + + +static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + int tmp = nents; + + DBG_RUN(KERN_WARNING __FUNCTION__ " START\n"); + + /* KISS: map each buffer seperately. */ + while (nents) { + sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction); + sg_dma_len(sglist) = sglist->length; + nents--; + sglist++; + } + + DBG_RUN(KERN_WARNING __FUNCTION__ " DONE\n"); + return tmp; +} + + +static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + DBG_RUN(KERN_WARNING __FUNCTION__ " : unmapping %d entries\n", nents); + while (nents) { + ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); + nents--; + sglist++; + } + return; +} + + +static struct pci_dma_ops ccio_ops = { + ccio_dma_supported, + ccio_alloc_consistent, + ccio_free_consistent, + ccio_map_single, + ccio_unmap_single, + ccio_map_sg, + ccio_unmap_sg, + NULL, /* dma_sync_single : NOP for U2/Uturn */ + NULL, /* dma_sync_sg : ditto */ +}; + +#if 0 +/* GRANT - is this needed for U2 or not? */ + +/* +** Get the size of the I/O TLB for this I/O MMU. +** +** If spa_shift is non-zero (ie probably U2), +** then calculate the I/O TLB size using spa_shift. +** +** Otherwise we are supposed to get the IODC entry point ENTRY TLB +** and execute it. However, both U2 and Uturn firmware supplies spa_shift. +** I think only Java (K/D/R-class too?) systems don't do this. +*/ +static int +ccio_get_iotlb_size(struct hp_device *d) +{ + if(d->spa_shift == 0) { + panic(__FUNCTION__ ": Can't determine I/O TLB size.\n"); + } + return(1 << d->spa_shift); +} +#else + +/* Uturn supports 256 TLB entries */ +#define CCIO_CHAINID_SHIFT 8 +#define CCIO_CHAINID_MASK 0xff + +#endif /* 0 */ + + +/* +** Figure out how big the I/O PDIR should be and alloc it. +** Also sets variables which depend on pdir size. +*/ +static void +ccio_alloc_pdir(struct ccio_device *ioa) +{ + extern unsigned long mem_max; /* arch.../setup.c */ + + u32 iova_space_size = 0; + void * pdir_base; + int pdir_size, iov_order; + + /* + ** Determine IOVA Space size from memory size. + ** Using "mem_max" is a kluge. + ** + ** Ideally, PCI drivers would register the maximum number + ** of DMA they can have outstanding for each device they + ** own. Next best thing would be to guess how much DMA + ** can be outstanding based on PCI Class/sub-class. Both + ** methods still require some "extra" to support PCI + ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD). + */ + /* limit IOVA space size to 1MB-1GB */ + if (mem_max < (ccio_mem_ratio*1024*1024)) { + iova_space_size = 1024*1024; +#ifdef __LP64__ + } else if (mem_max > (ccio_mem_ratio*512*1024*1024)) { + iova_space_size = 512*1024*1024; +#endif + } else { + iova_space_size = (u32) (mem_max/ccio_mem_ratio); + } + + /* + ** iova space must be log2() in size. + ** thus, pdir/res_map will also be log2(). + */ + + /* We could use larger page sizes in order to *decrease* the number + ** of mappings needed. (ie 8k pages means 1/2 the mappings). + ** + ** Note: Grant Grunder says "Using 8k I/O pages isn't trivial either + ** since the pages must also be physically contiguous - typically + ** this is the case under linux." + */ + + iov_order = get_order(iova_space_size); + ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */ + ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */ + iova_space_size = 1 << (iov_order + IOVP_SHIFT); + + ioa->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); + + ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */ + + /* Verify it's a power of two */ + ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT)); + + DBG_INIT(__FUNCTION__ " hpa 0x%p mem %dMB IOV %dMB (%d bits)\n PDIR size 0x%0x", + ioa->ccio_hpa, (int) (mem_max>>20), iova_space_size>>20, + iov_order + PAGE_SHIFT, pdir_size); + + ioa->pdir_base = + pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size)); + if (NULL == pdir_base) + { + panic(__FILE__ ":" __FUNCTION__ "() could not allocate I/O Page Table\n"); + } + memset(pdir_base, 0, pdir_size); + + ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base); + + DBG_INIT(" base %p", pdir_base); + + /* + ** Chainid is the upper most bits of an IOVP used to determine + ** which TLB entry an IOVP will use. + */ + ioa->chainid_shift = get_order(iova_space_size)+PAGE_SHIFT-CCIO_CHAINID_SHIFT; + + DBG_INIT(" chainid_shift 0x%x\n", ioa->chainid_shift); +} + + +static void +ccio_hw_init(struct ccio_device *ioa) +{ + int i; + + /* + ** Initialize IOA hardware + */ + WRITE_U32(CCIO_CHAINID_MASK << ioa->chainid_shift, &ioa->ccio_hpa->io_chain_id_mask); + WRITE_U32(virt_to_phys(ioa->pdir_base), &ioa->ccio_hpa->io_pdir_base); + + + /* + ** Go to "Virtual Mode" + */ + WRITE_U32(IOA_NORMAL_MODE, &ioa->ccio_hpa->io_control); + + /* + ** Initialize all I/O TLB entries to 0 (Valid bit off). + */ + WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_m); + WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_l); + + for (i = 1 << CCIO_CHAINID_SHIFT; i ; i--) { + WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioa->chainid_shift)), + &ioa->ccio_hpa->io_command); + } + +} + + +static void +ccio_resmap_init(struct ccio_device *ioa) +{ + u32 res_size; + + /* + ** Ok...we do more than just init resource map + */ + ioa->ccio_lock = SPIN_LOCK_UNLOCKED; + + ioa->res_hint = 16; /* next available IOVP - circular search */ + + /* resource map size dictated by pdir_size */ + res_size = ioa->pdir_size/sizeof(u64); /* entries */ + res_size >>= 3; /* convert bit count to byte count */ + DBG_INIT(__FUNCTION__ "() res_size 0x%x\n", res_size); + + ioa->res_size = res_size; + ioa->res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); + if (NULL == ioa->res_map) + { + panic(__FILE__ ":" __FUNCTION__ "() could not allocate resource map\n"); + } + memset(ioa->res_map, 0, res_size); +} + +/* CUJO20 KLUDGE start */ +static struct { + u16 hversion; + u8 spa; + u8 type; + u32 foo[3]; /* 16 bytes total */ +} cujo_iodc __attribute__ ((aligned (64))); +static unsigned long cujo_result[32] __attribute__ ((aligned (16))) = {0,0,0,0}; + +/* +** CUJO 2.0 incorrectly decodes a memory access for specific +** pages (every page at specific iotlb locations dependent +** upon where the cujo is flexed - diff on raven/firehawk. +** resulting in an hpmc and/or silent data corruption. +** Workaround is to prevent use of those I/O TLB entries +** by marking the suspect bitmap range entries as busy. +*/ +static void +ccio_cujo20_hack(struct ccio_device *ioa) +{ + unsigned long status; + unsigned int idx; + u8 *res_ptr = ioa->res_map; + u32 iovp=0x0; + unsigned long mask; + + status = pdc_iodc_read( &cujo_result, (void *) CUJO_RAVEN_LOC, 0, &cujo_iodc, 16); + if (status == 0) { + if (cujo_iodc.hversion==CUJO_20_BADHVERS) + iovp = CUJO_20_BADPAGE1; + } else { + status = pdc_iodc_read( &cujo_result, (void *) CUJO_FIREHAWK_LOC, 0, &cujo_iodc, 16); + if (status == 0) { + if (cujo_iodc.hversion==CUJO_20_BADHVERS) + iovp = CUJO_20_BADPAGE2; + } else { + /* not a defective system */ + return; + } + } + + printk(MODULE_NAME ": Cujo 2.0 bug needs a work around\n"); + ccio_cujo_bug = 1; + + /* + ** mark bit entries that match "bad page" + */ + idx = PDIR_INDEX(iovp)>>3; + mask = 0xff; + + while(idx * sizeof(u8) < ioa->res_size) { + res_ptr[idx] |= mask; + idx += (PDIR_INDEX(CUJO_20_STEP)>>3); + ccio_used_pages += 8; + ccio_used_bytes += 1; + } +} +/* CUJO20 KLUDGE end */ + +#ifdef CONFIG_PROC_FS +static int ccio_proc_info(char *buf, char **start, off_t offset, int len) +{ + unsigned long i = 0; + struct ccio_device *ioa = ccio_list; + unsigned long *res_ptr = (unsigned long *)ioa->res_map; + unsigned long total_pages = ioa->res_size << 3; /* 8 bits per byte */ + + sprintf(buf, "%s\nCujo 2.0 bug : %s\n", + parisc_getHWdescription(ioa->iodc->hw_type, ioa->iodc->hversion, + ioa->iodc->sversion), + (ccio_cujo_bug ? "yes" : "no")); + + sprintf(buf, "%sIO pdir size : %d bytes (%d entries)\n", + buf, ((ioa->res_size << 3) * sizeof(u64)), /* 8 bits per byte */ + ioa->res_size << 3); /* 8 bits per byte */ + + sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", + buf, ioa->res_size, ioa->res_size << 3); /* 8 bits per byte */ + + strcat(buf, " total: free: used: % used:\n"); + sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, ioa->res_size, + ioa->res_size - ccio_used_bytes, ccio_used_bytes, + (ccio_used_bytes * 100) / ioa->res_size); + + sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages, + total_pages - ccio_used_pages, ccio_used_pages, + (ccio_used_pages * 100 / total_pages)); + + sprintf(buf, "%sconsistent %8ld %8ld\n", buf, + ccio_alloc_size, ccio_free_size); + + strcat(buf, "\nResource bitmap:\n"); + + for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr) + len += sprintf(buf, "%s%08lx ", buf, *res_ptr); + + strcat(buf, "\n"); + return strlen(buf); +} +#endif + +/* +** Determine if ccio should claim this chip (return 0) or not (return 1). +** If so, initialize the chip and tell other partners in crime they +** have work to do. +*/ +static int +ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +{ + struct ccio_device *ioa; + + printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa); + + if (ccio_list) { + printk(MODULE_NAME ": already initialized one device\n"); + return(0); + } + + ioa = kmalloc(sizeof(struct ccio_device), GFP_KERNEL); + if (NULL == ioa) + { + printk(MODULE_NAME " - couldn't alloc ccio_device\n"); + return(1); + } + memset(ioa, 0, sizeof(struct ccio_device)); + + /* + ** ccio list is used mainly as a kluge to support a single instance. + ** Eventually, with core dumps, it'll be useful for debugging. + */ + ccio_list = ioa; + ioa->iodc = d; + +#if 1 +/* KLUGE: determine IOA hpa based on GSC port value. +** Needed until we have a PA bus walk. Can only discover IOA via +** walking the architected PA MMIO space as described by the I/O ACD. +** "Legacy" PA Firmware only tells us about unarchitected devices +** that can't be detected by PA/EISA/PCI bus walks. +*/ + switch((long) d->hpa) { + case 0xf3fbf000L: /* C110 IOA0 LBC (aka GSC port) */ + /* ccio_hpa same as C200 IOA0 */ + case 0xf203f000L: /* C180/C200/240/C360 IOA0 LBC (aka GSC port) */ + ioa->ccio_hpa = (struct ioa_registers *) 0xfff88000L; + break; + case 0xf103f000L: /* C180/C200/240/C360 IOA1 LBC (aka GSC port) */ + ioa->ccio_hpa = (struct ioa_registers *) 0xfff8A000L; + break; + default: + panic("ccio-dma.c doesn't know this GSC port Address!\n"); + break; + }; +#else + ioa->ccio_hpa = d->hpa; +#endif + + ccio_alloc_pdir(ioa); + ccio_hw_init(ioa); + ccio_resmap_init(ioa); + + /* CUJO20 KLUDGE start */ + ccio_cujo20_hack(ioa); + /* CUJO20 KLUDGE end */ + + hppa_dma_ops = &ccio_ops; + + create_proc_info_entry(MODULE_NAME, 0, proc_runway_root, ccio_proc_info); + return(0); +} + + + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/ccio-rm-dma.c linux/arch/parisc/kernel/ccio-rm-dma.c --- v2.4.0-test11/linux/arch/parisc/kernel/ccio-rm-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/ccio-rm-dma.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,212 @@ +/* + * ccio-rm-dma.c: + * DMA management routines for first generation cache-coherent machines. + * "Real Mode" operation refers to U2/Uturn chip operation. The chip + * can perform coherency checks w/o using the I/O MMU. That's all we + * need until support for more than 4GB phys mem is needed. + * + * This is the trivial case - basically what x86 does. + * + * Drawbacks of using Real Mode are: + * o outbound DMA is slower since one isn't using the prefetching + * U2 can do for outbound DMA. + * o Ability to do scatter/gather in HW is also lost. + * o only known to work with PCX-W processor. (eg C360) + * (PCX-U/U+ are not coherent with U2 in real mode.) + * + * + * 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. + * + * + * Original version/author: + * CVSROOT=:pserver:anonymous@198.186.203.37:/cvsroot/linux-parisc + * cvs -z3 co linux/arch/parisc/kernel/dma-rm.c + * + * (C) Copyright 2000 Philipp Rumpf + * + * + * Adopted for The Puffin Group's parisc-linux port by Grant Grundler. + * (C) Copyright 2000 Grant Grundler + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* Only chose "ccio" since that's what HP-UX calls it.... +** Make it easier for folks to migrate from one to the other :^) +*/ +#define MODULE_NAME "ccio" + +#define U2_IOA_RUNWAY 0x580 +#define U2_BC_GSC 0x501 +#define UTURN_IOA_RUNWAY 0x581 +#define UTURN_BC_GSC 0x502 + +static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *); + +static struct pa_iodc_driver ccio_drivers_for[] = { + + {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback}, + + {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback}, + + {0,0,0,0,0,0, + 0, + (char *) NULL, (char *) NULL, (void *) NULL } +}; + + +#define IS_U2(id) ( \ + (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \ + (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \ +) + +#define IS_UTURN(id) ( \ + (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \ + (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \ +) + + +void __init ccio_init(void) +{ + register_driver(ccio_drivers_for); +} + + +static int ccio_dma_supported( struct pci_dev *dev, dma_addr_t mask) +{ + if (dev == NULL) { + printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); + BUG(); + return(0); + } + + dev->dma_mask = mask; /* save it */ + + /* only support 32-bit devices (ie PCI/GSC) */ + return((int) (mask >= 0xffffffffUL)); +} + + +static void *ccio_alloc_consistent(struct pci_dev *dev, size_t size, + dma_addr_t *handle) +{ + void *ret; + + ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + + if (ret != NULL) { + memset(ret, 0, size); + *handle = virt_to_phys(ret); + } + return ret; +} + +static void ccio_free_consistent(struct pci_dev *dev, size_t size, + void *vaddr, dma_addr_t handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +static dma_addr_t ccio_map_single(struct pci_dev *dev, void *ptr, size_t size, + int direction) +{ + return virt_to_phys(ptr); +} + +static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t dma_addr, + size_t size, int direction) +{ + /* Nothing to do */ +} + + +static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + int tmp = nents; + + /* KISS: map each buffer seperately. */ + while (nents) { + sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction); + sg_dma_len(sglist) = sglist->length; + nents--; + sglist++; + } + + return tmp; +} + + +static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ +#if 0 + while (nents) { + ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); + nents--; + sglist++; + } + return; +#else + /* Do nothing (copied from current ccio_unmap_single() :^) */ +#endif +} + + +static struct pci_dma_ops ccio_ops = { + ccio_dma_supported, + ccio_alloc_consistent, + ccio_free_consistent, + ccio_map_single, + ccio_unmap_single, + ccio_map_sg, + ccio_unmap_sg, + NULL, /* dma_sync_single : NOP for U2 */ + NULL, /* dma_sync_sg : ditto */ + + +}; + + +/* +** Determine if u2 should claim this chip (return 0) or not (return 1). +** If so, initialize the chip and tell other partners in crime they +** have work to do. +*/ +static int +ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +{ + printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa); + +/* +** FIXME - should check U2 registers to verify it's really running +** in "Real Mode". +*/ + +#if 0 +/* will need this for "Virtual Mode" operation */ + ccio_hw_init(ccio_dev); + ccio_common_init(ccio_dev); +#endif + hppa_dma_ops = &ccio_ops; + return 0; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/drivers.c linux/arch/parisc/kernel/drivers.c --- v2.4.0-test11/linux/arch/parisc/kernel/drivers.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/drivers.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,134 @@ +/* + +drivers.c + +Copyright (c) 1999 The Puffin Group + +This is a collection of routines intended to register all the devices +in a system, and register device drivers. + +*/ + +#include +#include +#include +#include +#include +#include + + +extern struct hp_hardware *parisc_get_reference( + unsigned short hw_type, unsigned long hversion, + unsigned long sversion ); + + +/* I'm assuming there'll never be 64 devices. We should probably make + this more flexible. */ + +#define MAX_DEVICES 64 + +unsigned int num_devices = 0; + +struct hp_device devices[MAX_DEVICES]; + +static unsigned long pdc_result[32] __attribute__ ((aligned (16))) = {0,0,0,0}; +static u8 iodc_data[32] __attribute__ ((aligned (64))); + +/* + * XXX should we be using a locked array ? + */ + +int register_driver(struct pa_iodc_driver *driver) +{ + unsigned int i; + struct hp_device * device; + + for (;driver->check;driver++) { + + for (i=0;imanaged) continue; + + if ((driver->check & DRIVER_CHECK_HWTYPE) && + (driver->hw_type != device->hw_type)) + continue; + if ((driver->check & DRIVER_CHECK_HVERSION) && + (driver->hversion != device->hversion)) + continue; + if ((driver->check & DRIVER_CHECK_HVERSION_REV) && + (driver->hversion_rev != device->hversion_rev)) + continue; + if ((driver->check & DRIVER_CHECK_SVERSION) && + (driver->sversion != device->sversion)) + continue; + if ((driver->check & DRIVER_CHECK_SVERSION_REV) && + (driver->sversion_rev != device->sversion_rev)) + continue; + if ((driver->check & DRIVER_CHECK_OPT) && + (driver->opt != device->opt)) + continue; + if ( (*driver->callback)(device,driver) ==0) { + device->managed=1; + } else { + printk("Warning : device (%d, 0x%x, 0x%x, 0x%x, 0x%x) NOT claimed by %s %s\n", + device->hw_type, + device->hversion, device->hversion_rev, + device->sversion, device->sversion_rev, + driver->name, driver->version); + } + } + } + return 0; +} + + +struct hp_device * register_module(void *hpa) +{ + + struct hp_device * d; + int status; + + d = &devices[num_devices]; + status = pdc_iodc_read(&pdc_result,hpa,0,&iodc_data,32 ); + if (status !=PDC_RET_OK) { + /* There is no device here, so we'll skip it */ + return 0; + } + + d->hw_type = iodc_data[3]&0x1f; + d->hversion = (iodc_data[0]<<4)|((iodc_data[1]&0xf0)>>4); + d->sversion = + ((iodc_data[4]&0x0f)<<16)|(iodc_data[5]<<8)|(iodc_data[6]); + d->hversion_rev = iodc_data[1]&0x0f; + d->sversion_rev = iodc_data[4]>>4; + d->opt = iodc_data[7]; + d->hpa = hpa; + d->managed=0; + d->reference = parisc_get_reference(d->hw_type, d->hversion, + d->sversion); + + num_devices++; + + return d; +} + +void print_devices(char * buf) { + + int i; + struct hp_device *d; + printk("Found devices:\n"); + for (i=0;ireference) ? d->reference->name : "Unknown device", + d->hw_type,d->hpa, d->hversion, d->hversion_rev, + d->sversion, d->sversion_rev, d->opt); + + } + printk("That's a total of %d devices.\n",num_devices); +} + + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/entry.S linux/arch/parisc/kernel/entry.S --- v2.4.0-test11/linux/arch/parisc/kernel/entry.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/entry.S Wed Dec 6 11:46:39 2000 @@ -0,0 +1,1867 @@ +/*------------------------------------------------------------------------------ + * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) + * + * kernel entry points (interruptions, system call wrappers) + * Copyright (C) 1999,2000 Philipp Rumpf + * Copyright (C) 1999 SuSE GmbH Nuernberg + * Copyright (C) 2000 Hewlett-Packard (John Marvin) + * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include + +/* the following is the setup i think we should follow: + * whenever the CPU is interruptible, the following has to be true: + * CR30 is the kernel sp or 0 if we currently use the kernel stack + * CR31 is the kernel gp */ + +/* we have the following possibilities to act on an interruption: + * - handle in assembly and use shadowed registers only + * - save registers to kernel stack and handle in assembly or C */ + + .text + +#ifdef __LP64__ + .level 2.0w +#endif + +#define __ASSEMBLY__ +#include /* for LDREG/STREG defines */ +#include +#include +#include + +#ifdef __LP64__ +#define FRAME_SIZE 64 +#else +#define FRAME_SIZE 64 +#endif + + /* Switch to virtual mapping, trashing only %r1 */ + .macro virt_map rfi_type + mtsm %r0 + tovirt %r29 + tovirt %r30 + mfsp %sr7, %r1 + mtsp %r1, %sr3 + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + mtsp %r0, %sr7 + ldil L%KERNEL_PSW, %r1 + ldo R%KERNEL_PSW(%r1), %r1 + LDIL_FIXUP(%r1) + mtctl %r1, %cr22 + mtctl %r0, %cr17 + mtctl %r0, %cr17 + ldil L%.+28, %r1 + ldo R%.+24(%r1), %r1 + LDIL_FIXUP(%r1) + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + \rfi_type + nop + .endm + + .macro get_stack + mfctl %cr30, %r1 + comib,=,n 0, %r1, 0f /* forward so predicted not taken */ + + /* we save the registers in the task struct */ + ldo TASK_REGS(%r1), %r29 + tophys %r29 + STREG %r30, PT_GR30(%r29) + STREG %r1, PT_CR30(%r29) + ldo TASK_SZ_ALGN(%r1), %r30 + b 1f /* unconditional so predicted taken */ + mtctl %r0,%cr30 +0: + /* we put a struct pt_regs on the stack and save the registers there */ + copy %r30,%r29 + ldo PT_SZ_ALGN(%r30),%r30 + tophys %r29 + STREG %r30,PT_GR30(%r29) + STREG %r0,PT_CR30(%r29) +1: + .endm + + .macro rest_stack regs + LDREG PT_CR30(\regs), %r1 + comib,=,n 0, %r1, 2f/* forward so predicted not taken */ + + /* we restore the registers out of the task struct */ + mtctl %r1, %cr30 + LDREG PT_GR1(\regs), %r1 + LDREG PT_GR30(\regs),%r30 + b 3f + LDREG PT_GR29(\regs),%r29 +2: + /* we take a struct pt_regs off the stack */ + LDREG PT_GR1(\regs), %r1 + LDREG PT_GR29(\regs), %r29 + ldo -PT_SZ_ALGN(%r30), %r30 +3: + .endm + +#ifdef OLD + /* fixme interruption handler */ + .macro def code + /* WARNING!!! THIS IS DEBUG CODE ONLY!!! */ + b unimplemented_64bitirq + ldi \code, %r1 + .align 32 + .endm + + /* Use def to enable break - KWDB wants em + * (calls traps.c:handle_interruption) */ + .macro pass_break code + +#else + /* default interruption handler + * (calls traps.c:handle_interruption) */ + .macro def code +#endif + mtctl %r29, %cr31 + mtctl %r1, %cr28 + ldi \code, %r1 + b intr_save + mtctl %r1, %cr29 + .align 32 + .endm + + /* Interrupt interruption handler + * (calls irq.c:do_irq_mask) */ + .macro extint code + mtctl %r29, %cr31 + mtctl %r1, %cr28 + mfctl %cr23, %r1 + mtctl %r1, %cr23 + b intr_extint + mtctl %r1, %cr29 + .align 32 + .endm + + .import os_hpmc, code + + /* HPMC handler */ + .macro hpmc code + nop /* must be a NOP, will be patched later */ + ldil L%PA(os_hpmc), %r3 + ldo R%PA(os_hpmc)(%r3), %r3 + bv,n 0(%r3) + nop + .word 0 /* checksum (will be patched) */ + .word PA(os_hpmc) /* address of handler */ + .word 0 /* length of handler */ + .endm + + /* + * Performance Note: Instructions will be moved up into + * this part of the code later on, once we are sure + * that the tlb miss handlers are close to final form. + */ + + /* Register definitions for tlb miss handler macros */ + + va = r8 /* virtual address for which the trap occured */ + spc = r24 /* space for which the trap occured */ + +#ifndef __LP64__ + + /* + * itlb miss interruption handler (parisc 1.1 - 32 bit) + */ + + .macro itlb_11 code + + mfctl %pcsq, spc + b itlb_miss_11 + mfctl %pcoq, va + + .align 32 + .endm +#endif + + /* + * itlb miss interruption handler (parisc 2.0) + */ + + .macro itlb_20 code + + mfctl %pcsq, spc +#ifdef __LP64__ + b itlb_miss_20w +#else + b itlb_miss_20 +#endif + mfctl %pcoq, va + + .align 32 + .endm + +#ifndef __LP64__ + /* + * naitlb miss interruption handler (parisc 1.1 - 32 bit) + * + * Note: naitlb misses will be treated + * as an ordinary itlb miss for now. + * However, note that naitlb misses + * have the faulting address in the + * IOR/ISR. + */ + + .macro naitlb_11 code + + mfctl %isr,spc + b itlb_miss_11 + mfctl %ior,va + /* FIXME: If user causes a naitlb miss, the priv level may not be in + * lower bits of va, where the itlb miss handler is expecting them + */ + + .align 32 + .endm +#endif + + /* + * naitlb miss interruption handler (parisc 2.0) + * + * Note: naitlb misses will be treated + * as an ordinary itlb miss for now. + * However, note that naitlb misses + * have the faulting address in the + * IOR/ISR. + */ + + .macro naitlb_20 code + + mfctl %isr,spc +#ifdef __LP64__ + b itlb_miss_20w +#else + b itlb_miss_20 +#endif + mfctl %ior,va + /* FIXME: If user causes a naitlb miss, the priv level may not be in + * lower bits of va, where the itlb miss handler is expecting them + */ + + .align 32 + .endm + +#ifndef __LP64__ + /* + * dtlb miss interruption handler (parisc 1.1 - 32 bit) + */ + + .macro dtlb_11 code + + mfctl %isr, spc + b dtlb_miss_11 + mfctl %ior, va + + .align 32 + .endm +#endif + + /* + * dtlb miss interruption handler (parisc 2.0) + */ + + .macro dtlb_20 code + + mfctl %isr, spc +#ifdef __LP64__ + b dtlb_miss_20w +#else + b dtlb_miss_20 +#endif + mfctl %ior, va + + .align 32 + .endm + +#ifndef __LP64__ + /* nadtlb miss interruption handler (parisc 1.1 - 32 bit) + * + * Note: nadtlb misses will be treated + * as an ordinary dtlb miss for now. + * + */ + + .macro nadtlb_11 code + + mfctl %isr,spc + b dtlb_miss_11 + mfctl %ior,va + + .align 32 + .endm +#endif + + /* nadtlb miss interruption handler (parisc 2.0) + * + * Note: nadtlb misses will be treated + * as an ordinary dtlb miss for now. + * + */ + + .macro nadtlb_20 code + + mfctl %isr,spc +#ifdef __LP64__ + b dtlb_miss_20w +#else + b dtlb_miss_20 +#endif + mfctl %ior,va + + .align 32 + .endm + +#ifndef __LP64__ + /* + * dirty bit trap interruption handler (parisc 1.1 - 32 bit) + */ + + .macro dbit_11 code + + mfctl %isr,spc + b dbit_trap_11 + mfctl %ior,va + + .align 32 + .endm +#endif + + /* + * dirty bit trap interruption handler (parisc 2.0) + */ + + .macro dbit_20 code + + mfctl %isr,spc +#ifdef __LP64__ + b dbit_trap_20w +#else + b dbit_trap_20 +#endif + mfctl %ior,va + + .align 32 + .endm + + /* + * Align fault_vector_20 on 4K boundary so that both + * fault_vector_11 and fault_vector_20 are on the + * same page. This is only necessary as long as we + * write protect the kernel text, which we may stop + * doing once we use large parge translations to cover + * the static part of the kernel address space. + */ + + + .export fault_vector_20 + + .align 4096 + +fault_vector_20: + /* First vector is invalid (0) */ + .ascii "cows can fly" + .byte 0 + .align 32 + + hpmc 1 + def 2 + def 3 + extint 4 + def 5 + itlb_20 6 + def 7 + def 8 + def 9 + def 10 + def 11 + def 12 + def 13 + def 14 + dtlb_20 15 + naitlb_20 16 + nadtlb_20 17 + def 18 + def 19 + dbit_20 20 + def 21 + def 22 + def 23 + def 24 + def 25 + def 26 + def 27 + def 28 + def 29 + def 30 + def 31 + +#ifndef __LP64__ + + .export fault_vector_11 + + .align 2048 + +fault_vector_11: + /* First vector is invalid (0) */ + .ascii "cows can fly" + .byte 0 + .align 32 + + hpmc 1 + def 2 + def 3 + extint 4 + def 5 + itlb_11 6 + def 7 + def 8 + def 9 + def 10 + def 11 + def 12 + def 13 + def 14 + dtlb_11 15 + naitlb_11 16 + nadtlb_11 17 + def 18 + def 19 + dbit_11 20 + def 21 + def 22 + def 23 + def 24 + def 25 + def 26 + def 27 + def 28 + def 29 + def 30 + def 31 + +#endif + + .import handle_interruption,code + .import handle_real_interruption,code + .import do_irq_mask,code + .import parisc_stopkernel,code + .import cpu_irq_region,data + + /* + * r26 = function to be called + * r25 = argument to pass in + * r24 = flags for do_fork() + * + * Kernel threads don't ever return, so they don't need + * a true register context. We just save away the arguments + * for copy_thread/ret_ to properly set up the child. + */ + +#define CLONE_VM 0x100 /* Must agree with */ + + .export __kernel_thread, code + .import do_fork +__kernel_thread: + STREG %r2, -RP_OFFSET(%r30) + + copy %r30, %r1 + ldo PT_SZ_ALGN(%r30),%r30 +#ifdef __LP64__ + /* Yo, function pointers in wide mode are little structs... -PB */ + /* XXX FIXME do we need to honor the fptr's %dp value too? */ + ldd 16(%r26), %r26 +#endif + STREG %r26, PT_GR26(%r1) /* Store function & argument for child */ + STREG %r25, PT_GR25(%r1) + ldo CLONE_VM(%r0), %r26 /* Force CLONE_VM since only init_mm */ + or %r26, %r24, %r26 /* will have kernel mappings. */ + copy %r0, %r25 + bl do_fork, %r2 + copy %r1, %r24 + + /* Parent Returns here */ + + ldo -PT_SZ_ALGN(%r30), %r30 + LDREG -RP_OFFSET(%r30), %r2 + bv %r0(%r2) + nop + + /* + * Child Returns here + * + * copy_thread moved args from temp save area set up above + * into task save area. + */ + + .export ret_from_kernel_thread +ret_from_kernel_thread: + + LDREG TASK_PT_GR26-TASK_SZ_ALGN(%r30), %r1 + LDREG TASK_PT_GR25-TASK_SZ_ALGN(%r30), %r26 + ble 0(%sr7, %r1) + copy %r31, %r2 + + b sys_exit + ldi 0, %r26 + + .import sys_execve, code + .export __execve, code +__execve: + copy %r2, %r15 + copy %r23, %r17 + copy %r30, %r16 + ldo PT_SZ_ALGN(%r30), %r30 + STREG %r26, PT_GR26(%r16) + STREG %r25, PT_GR25(%r16) + STREG %r24, PT_GR24(%r16) + bl sys_execve, %r2 + copy %r16, %r26 + + comib,<>,n 0,%r28,__execve_failed + + b intr_return + STREG %r17, PT_CR30(%r16) + +__execve_failed: + /* yes, this will trap and die. */ + copy %r15, %r2 + bv %r0(%r2) + nop + + .align 4 + + /* + * struct task_struct *_switch_to(struct task_struct *prev, + * struct task_struct *next) + * + * switch kernel stacks and return prev */ + .export _switch_to, code +_switch_to: + STREG %r2, -RP_OFFSET(%r30) + + callee_save + + ldil L%_switch_to_ret, %r2 + ldo R%_switch_to_ret(%r2), %r2 + LDIL_FIXUP(%r2) + + STREG %r2, TASK_PT_KPC(%r26) + LDREG TASK_PT_KPC(%r25), %r2 + + STREG %r30, TASK_PT_KSP(%r26) + LDREG TASK_PT_KSP(%r25), %r30 + + bv %r0(%r2) + nop + +_switch_to_ret: + mtctl %r0, %cr0 /* Needed for single stepping */ + callee_rest + + LDREG -RP_OFFSET(%r30), %r2 + bv %r0(%r2) + copy %r26, %r28 + + /* + * Common rfi return path for interruptions, kernel execve, and some + * syscalls. The sys_rt_sigreturn syscall will return via this path + * if the signal was received when the process was running; if the + * process was blocked on a syscall then the normal syscall_exit + * path is used. All syscalls for traced proceses exit via + * intr_restore. + * Note that the following code uses a "relied upon translation". See + * the parisc ACD for details. The ssm is necessary due to a PCXT bug. + */ + + .align 4096 + + .export syscall_exit_rfi +syscall_exit_rfi: + copy %r30,%r16 + /* FIXME! depi below has hardcoded dependency on kernel stack size */ + depi 0,31,14,%r16 /* get task pointer */ + ldo TASK_REGS(%r16),%r16 + /* Force iaoq to userspace, as the user has had access to our current + * context via sigcontext. + * XXX do we need any other protection here? + */ + LDREG PT_IAOQ0(%r16),%r19 + depi 3,31,2,%r19 + STREG %r19,PT_IAOQ0(%r16) + LDREG PT_IAOQ1(%r16),%r19 + depi 3,31,2,%r19 + STREG %r19,PT_IAOQ1(%r16) + +intr_return: + + /* Check for software interrupts */ + + .import irq_stat,data + + ldil L%irq_stat,%r19 + ldo R%irq_stat(%r19),%r19 + LDIL_FIXUP(%r19) + +#ifdef CONFIG_SMP + copy %r30,%r1 + /* FIXME! depi below has hardcoded dependency on kernel stack size */ + depi 0,31,14,%r1 /* get task pointer */ + ldw TASK_PROCESSOR(%r1),%r20 /* get cpu # - int */ +#if (IRQSTAT_SZ == 32) + dep %r20,26,27,%r20 /* shift left 5 bits */ +#else +#error IRQSTAT_SZ changed, fix dep +#endif /* IRQSTAT_SZ */ + add %r19,%r20,%r19 +#endif /* CONFIG_SMP */ + + ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */ + ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */ + and %r19,%r20,%r20 + comib,<>,n 0,%r20,intr_do_softirq /* forward */ + +intr_check_resched: + + /* check for reschedule */ + copy %r30,%r1 + /* FIXME! depi below has hardcoded dependency on kernel stack size */ + depi 0,31,14,%r1 /* get task pointer */ + LDREG TASK_NEED_RESCHED(%r1),%r19 /* sched.h: long need_resched */ + comib,<>,n 0,%r19,intr_do_resched /* forward */ + +intr_check_sig: + /* As above */ + copy %r30,%r1 + depi 0,31,14,%r1 /* get task pointer */ + ldw TASK_SIGPENDING(%r1),%r19 /* sched.h: int sigpending */ + comib,<>,n 0,%r19,intr_do_signal /* forward */ + +intr_restore: + copy %r16, %r29 + ldo PT_FR31(%r29), %r29 + rest_fp %r29 + copy %r16, %r29 + rest_general %r29 + ssm 0,%r0 + nop + nop + nop + nop + nop + nop + nop + tophys %r29 + mtsm %r0 + rest_specials %r29 + rest_stack %r29 + rfi + nop + nop + nop + nop + nop + nop + nop + nop + + .import do_softirq,code +intr_do_softirq: + bl do_softirq,%r2 + nop + b intr_check_resched + nop + + .import schedule,code +intr_do_resched: + /* Only do reschedule if we are returning to user space */ + LDREG PT_SR7(%r16), %r20 + comib,= 0,%r20,intr_restore /* backward */ + nop + + bl schedule,%r2 + ssm PSW_SM_I, %r0 + + /* It's OK to leave I bit on */ + b intr_return /* start over if we got a resched */ + nop + + .import do_signal,code +intr_do_signal: + /* Only do signals if we are returning to user space */ + LDREG PT_SR7(%r16), %r20 + comib,= 0,%r20,intr_restore /* backward */ + nop + + copy %r0, %r24 /* unsigned long in_syscall */ + copy %r16, %r25 /* struct pt_regs *regs */ + ssm PSW_SM_I, %r0 + bl do_signal,%r2 + copy %r0, %r26 /* sigset_t *oldset = NULL */ + + b intr_restore + nop + + /* CR28 - saved GR1 + * CR29 - argument for do_irq_mask */ + + /* External interrupts */ +intr_extint: + get_stack + save_specials %r29 + virt_map rfi + save_general %r29 + + ldo PT_FR0(%r29), %r24 + save_fp %r24 + + loadgp + + copy %r29, %r24 /* arg2 is pt_regs */ + copy %r29, %r16 /* save pt_regs */ +#ifdef CONFIG_KWDB + copy %r29, %r3 /* KWDB - update frame pointer (gr3) */ +#endif + + /* sorry to put this cruft in the interrupt path */ + ldil L%cpu_irq_region, %r25 + ldo R%cpu_irq_region(%r25), %r25 + bl do_irq_mask,%r2 +#ifdef __LP64__ + LDIL_FIXUP(%r25) +#else + nop +#endif + + b intr_return + nop + + /* Generic interruptions (illegal insn, unaligned, page fault, etc) */ + + .export intr_save, code /* for os_hpmc */ + +intr_save: + get_stack + save_specials %r29 + + mfctl %cr20, %r1 + STREG %r1, PT_ISR(%r29) + mfctl %cr21, %r1 + STREG %r1, PT_IOR(%r29) + + virt_map rfi + save_general %r29 + + ldo PT_FR0(%r29), %r25 + save_fp %r25 + + loadgp + + copy %r29, %r25 /* arg1 is pt_regs */ +#ifdef CONFIG_KWDB + copy %r29, %r3 /* KWDB - update frame pointer (gr3) */ +#endif + + bl handle_interruption,%r2 + copy %r29, %r16 /* save pt_regs */ + + b intr_return + nop + + /* + * Note for all tlb miss handlers: + * + * cr24 contains a pointer to the kernel address space + * page directory. + * + * cr25 contains a pointer to the current user address + * space page directory. + * + * sr3 will contain the space id of the user address space + * of the current running thread while that thread is + * running in the kernel. + */ + + /* + * register number allocations. Note that these are all + * in the shadowed registers + */ + + t0 = r1 /* temporary register 0 */ + va = r8 /* virtual address for which the trap occured */ + t1 = r9 /* temporary register 1 */ + pte = r16 /* pte/phys page # */ + prot = r17 /* prot bits */ + spc = r24 /* space for which the trap occured */ + ptp = r25 /* page directory/page table pointer */ + +#ifdef __LP64__ + +dtlb_miss_20w: + + extrd,u spc,31,7,t1 /* adjust va */ + depd t1,31,7,va /* adjust va */ + depdi 0,31,7,spc /* adjust space */ + mfctl %cr25,ptp /* Assume user space miss */ + or,*<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extrd,u va,33,9,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,*= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,dtlb_fault /* forward */ + + /* First level page table lookup */ + + ldd,s t1(ptp),ptp + extrd,u va,42,9,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + depdi 0,63,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + ldd,s t0(ptp),ptp + extrd,u va,51,9,t0 /* get third-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + depdi 0,63,12,ptp /* clear prot bits */ + + /* Third level page table lookup */ + + shladd t0,3,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldd 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault + + /* Check whether the "accessed" bit was set, otherwise do so */ + + or t1,pte,t0 /* t0 has R bit set */ + and,*<> t1,pte,%r0 /* test and nullify if already set */ + std t0,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + + depd pte,8,7,prot + extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 + depdi 1,12,1,prot + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,32,pte + idtlbt %r16,%r17 + + rfir + nop +#else + +dtlb_miss_11: + mfctl %cr25,ptp /* Assume user space miss */ + or,<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extru va,9,10,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,dtlb_fault /* forward */ + + /* First level page table lookup */ + + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault + + /* Check whether the "accessed" bit was set, otherwise do so */ + + or t1,pte,t0 /* t0 has R bit set */ + and,<> t1,pte,%r0 /* test and nullify if already set */ + stw t0,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + dep pte,8,7,prot + + extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 + depi 1,12,1,prot + extru,= pte,_PAGE_USER_BIT,1,r0 + depi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extru,= pte,_PAGE_GATEWAY_BIT,1,r0 + depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlba */ + + depi 0,31,12,pte + extru pte,24,25,pte + + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + idtlba pte,(%sr1,va) + idtlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +dtlb_miss_20: + .level 2.0 + + mfctl %cr25,ptp /* Assume user space miss */ + or,<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extru va,9,10,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,dtlb_fault /* forward */ + + /* First level page table lookup */ + + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dtlb_fault + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,dtlb_fault + + /* Check whether the "accessed" bit was set, otherwise do so */ + + or t1,pte,t0 /* t0 has R bit set */ + and,<> t1,pte,%r0 /* test and nullify if already set */ + stw t0,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + + depd pte,8,7,prot + extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 + depdi 1,12,1,prot + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,25,pte + idtlbt %r16,%r17 + + .level 1.1 + + rfir + nop +#endif + +#ifdef __LP64__ +itlb_miss_20w: + + /* + * I miss is a little different, since we allow users to fault + * on the gateway page which is in the kernel address space. + */ + + extrd,u spc,31,7,t1 /* adjust va */ + depd t1,31,7,va /* adjust va */ + depdi 0,31,7,spc /* adjust space */ + cmpib,*= 0,spc,itlb_miss_kernel_20w + extrd,u va,33,9,t1 /* Get pgd index */ + + mfctl %cr25,ptp /* load user pgd */ + + mfsp %sr7,t0 /* Get current space */ + or,*= %r0,t0,%r0 /* If kernel, nullify following test */ + cmpb,*<>,n t0,spc,itlb_fault /* forward */ + + /* First level page table lookup */ + +itlb_miss_common_20w: + ldd,s t1(ptp),ptp + extrd,u va,42,9,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault + depdi 0,63,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + ldd,s t0(ptp),ptp + extrd,u va,51,9,t0 /* get third-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault + depdi 0,63,12,ptp /* clear prot bits */ + + /* Third level page table lookup */ + + shladd t0,3,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldd 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault + + /* Check whether the "accessed" bit was set, otherwise do so */ + + or t1,pte,t0 /* t0 has R bit set */ + and,*<> t1,pte,%r0 /* test and nullify if already set */ + std t0,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + + depd pte,8,7,prot + extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 + depdi 1,12,1,prot + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for iitlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,32,pte + iitlbt %r16,%r17 + + rfir + nop + +itlb_miss_kernel_20w: + b itlb_miss_common_20w + mfctl %cr24,ptp /* Load kernel pgd */ +#else + +itlb_miss_11: + + /* + * I miss is a little different, since we allow users to fault + * on the gateway page which is in the kernel address space. + */ + + comib,= 0,spc,itlb_miss_kernel_11 + extru va,9,10,t1 /* Get pgd index */ + + mfctl %cr25,ptp /* load user pgd */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,itlb_fault /* forward */ + + /* First level page table lookup */ + +itlb_miss_common_11: + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault + + /* Check whether the "accessed" bit was set, otherwise do so */ + + or t1,pte,t0 /* t0 has R bit set */ + and,<> t1,pte,%r0 /* test and nullify if already set */ + stw t0,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + dep pte,8,7,prot + + extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 + depi 1,12,1,prot + extru,= pte,_PAGE_USER_BIT,1,r0 + depi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extru,= pte,_PAGE_GATEWAY_BIT,1,r0 + depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for iitlba */ + + depi 0,31,12,pte + extru pte,24,25,pte + + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + iitlba pte,(%sr1,va) + iitlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +itlb_miss_kernel_11: + b itlb_miss_common_11 + mfctl %cr24,ptp /* Load kernel pgd */ + +itlb_miss_20: + + /* + * I miss is a little different, since we allow users to fault + * on the gateway page which is in the kernel address space. + */ + + comib,= 0,spc,itlb_miss_kernel_20 + extru va,9,10,t1 /* Get pgd index */ + + mfctl %cr25,ptp /* load user pgd */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,itlb_fault /* forward */ + + /* First level page table lookup */ + +itlb_miss_common_20: + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,itlb_fault + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi _PAGE_ACCESSED,t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,itlb_fault + + /* Check whether the "accessed" bit was set, otherwise do so */ + + or t1,pte,t0 /* t0 has R bit set */ + and,<> t1,pte,%r0 /* test and nullify if already set */ + stw t0,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + + .level 2.0 + + depd pte,8,7,prot + extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 + depdi 1,12,1,prot + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for iitlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,25,pte + iitlbt %r16,%r17 + .level 1.1 + + rfir + nop + + +itlb_miss_kernel_20: + b itlb_miss_common_20 + mfctl %cr24,ptp /* Load kernel pgd */ +#endif + +#ifdef __LP64__ + +dbit_trap_20w: + + extrd,u spc,31,7,t1 /* adjust va */ + depd t1,31,7,va /* adjust va */ + depdi 0,1,2,va /* adjust va */ + depdi 0,31,7,spc /* adjust space */ + mfctl %cr25,ptp /* Assume user space miss */ + or,*<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extrd,u va,33,9,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,*= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,dbit_fault /* forward */ + + /* First level page table lookup */ + + ldd,s t1(ptp),ptp + extrd,u va,42,9,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault + depdi 0,63,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + ldd,s t0(ptp),ptp + extrd,u va,51,9,t0 /* get third-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault + depdi 0,63,12,ptp /* clear prot bits */ + + /* Third level page table lookup */ + + shladd t0,3,ptp,ptp + ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1 + ldd 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault + + /* Set Accessed and Dirty bits in the pte */ + + or t1,pte,pte + std pte,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + + depd pte,8,7,prot + extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 + depdi 1,12,1,prot + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,32,pte + idtlbt %r16,%r17 + + rfir + nop +#else + +dbit_trap_11: + mfctl %cr25,ptp /* Assume user space trap */ + or,<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extru va,9,10,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,dbit_fault /* forward */ + + /* First level page table lookup */ + + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault + + /* Set Accessed and Dirty bits in the pte */ + + or t1,pte,pte + stw pte,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + dep pte,8,7,prot + + extru,= pte,_PAGE_NO_CACHE_BIT,1,r0 + depi 1,12,1,prot + extru,= pte,_PAGE_USER_BIT,1,r0 + depi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extru,= pte,_PAGE_GATEWAY_BIT,1,r0 + depi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlba */ + + depi 0,31,12,pte + extru pte,24,25,pte + + mfsp %sr1,t0 /* Save sr1 so we can use it in tlb inserts */ + mtsp spc,%sr1 + + idtlba pte,(%sr1,va) + idtlbp prot,(%sr1,va) + + mtsp t0, %sr1 /* Restore sr1 */ + + rfir + nop + +dbit_trap_20: + mfctl %cr25,ptp /* Assume user space trap */ + or,<> %r0,spc,%r0 /* If it is user space, nullify */ + mfctl %cr24,ptp /* Load kernel pgd instead */ + extru va,9,10,t1 /* Get pgd index */ + + mfsp %sr7,t0 /* Get current space */ + or,= %r0,t0,%r0 /* If kernel, nullify following test */ + comb,<>,n t0,spc,dbit_fault /* forward */ + + /* First level page table lookup */ + + ldwx,s t1(ptp),ptp + extru va,19,10,t0 /* get second-level index */ + bb,>=,n ptp,_PAGE_PRESENT_BIT,dbit_fault + depi 0,31,12,ptp /* clear prot bits */ + + /* Second level page table lookup */ + + sh2addl t0,ptp,ptp + ldi (_PAGE_ACCESSED|_PAGE_DIRTY),t1 + ldw 0(ptp),pte + bb,>=,n pte,_PAGE_PRESENT_BIT,dbit_fault + + /* Set Accessed and Dirty bits in the pte */ + + or t1,pte,pte + stw pte,0(ptp) /* write back pte */ + + copy spc,prot /* init prot with faulting space */ + + .level 2.0 + + depd pte,8,7,prot + extrd,u,*= pte,_PAGE_NO_CACHE_BIT+32,1,r0 + depdi 1,12,1,prot + extrd,u,*= pte,_PAGE_USER_BIT+32,1,r0 + depdi 7,11,3,prot /* Set for user space (1 rsvd for read) */ + extrd,u,*= pte,_PAGE_GATEWAY_BIT+32,1,r0 + depdi 0,11,2,prot /* If Gateway, Set PL2 to 0 */ + + /* Get rid of prot bits and convert to page addr for idtlbt */ + + depdi 0,63,12,pte + extrd,u pte,56,25,pte + idtlbt %r16,%r17 + + .level 1.1 + + rfir + nop +#endif + + .import handle_interruption,code + +kernel_bad_space: + b tlb_fault + ldi 31,%r1 /* Use an unused code */ + +dbit_fault: + b tlb_fault + ldi 20,%r1 + +itlb_fault: + b tlb_fault + ldi 6,%r1 + +dtlb_fault: + ldi 15,%r1 + + /* Fall Through */ + +tlb_fault: + mtctl %r1,%cr29 + mtctl %r29,%cr31 + + get_stack + save_specials %r29 /* Note this saves a trashed r1 */ + + SAVE_CR (%cr20, PT_ISR(%r29)) + SAVE_CR (%cr21, PT_IOR(%r29)) + + virt_map rfir + + STREG %r1,PT_GR1(%r29) /* save good value after rfir */ + + save_general %r29 + + ldo PT_FR0(%r29), %r25 + save_fp %r25 + + loadgp + + copy %r29, %r25 + + bl handle_interruption, %r2 + copy %r29, %r16 + + b intr_return + nop + + /* Register saving semantics for system calls: + + %r1 clobbered by system call macro in userspace + %r2 saved in PT_REGS by gateway page + %r3 - %r18 preserved by C code (saved by signal code) + %r19 - %r20 saved in PT_REGS by gateway page + %r21 - %r22 non-standard syscall args + stored in kernel stack by gateway page + %r23 - %r26 arg3-arg0, saved in PT_REGS by gateway page + %r27 - %r30 saved in PT_REGS by gateway page + %r31 syscall return pointer + */ + + /* Floating point registers (FIXME: what do we do with these?) + + %fr0 - %fr3 status/exception, not preserved + %fr4 - %fr7 arguments + %fr8 - %fr11 not preserved by C code + %fr12 - %fr21 preserved by C code + %fr22 - %fr31 not preserved by C code + */ + + .macro reg_save regs + STREG %r3, PT_GR3(\regs) + STREG %r4, PT_GR4(\regs) + STREG %r5, PT_GR5(\regs) + STREG %r6, PT_GR6(\regs) + STREG %r7, PT_GR7(\regs) + STREG %r8, PT_GR8(\regs) + STREG %r9, PT_GR9(\regs) + STREG %r10,PT_GR10(\regs) + STREG %r11,PT_GR11(\regs) + STREG %r12,PT_GR12(\regs) + STREG %r13,PT_GR13(\regs) + STREG %r14,PT_GR14(\regs) + STREG %r15,PT_GR15(\regs) + STREG %r16,PT_GR16(\regs) + STREG %r17,PT_GR17(\regs) + STREG %r18,PT_GR18(\regs) + .endm + + .macro reg_restore regs + LDREG PT_GR3(\regs), %r3 + LDREG PT_GR4(\regs), %r4 + LDREG PT_GR5(\regs), %r5 + LDREG PT_GR6(\regs), %r6 + LDREG PT_GR7(\regs), %r7 + LDREG PT_GR8(\regs), %r8 + LDREG PT_GR9(\regs), %r9 + LDREG PT_GR10(\regs),%r10 + LDREG PT_GR11(\regs),%r11 + LDREG PT_GR12(\regs),%r12 + LDREG PT_GR13(\regs),%r13 + LDREG PT_GR14(\regs),%r14 + LDREG PT_GR15(\regs),%r15 + LDREG PT_GR16(\regs),%r16 + LDREG PT_GR17(\regs),%r17 + LDREG PT_GR18(\regs),%r18 + .endm + + .export sys_fork_wrapper +sys_fork_wrapper: + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + reg_save %r1 + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 + + /* These are call-clobbered registers and therefore + also syscall-clobbered (we hope). */ + STREG %r2,PT_GR19(%r1) /* save for child */ + STREG %r30,PT_GR20(%r1) + ldil L%child_return, %r3 + ldo R%child_return(%r3), %r3 + LDIL_FIXUP(%r3) + STREG %r3,PT_GR21(%r1) /* save for child */ + + LDREG PT_GR30(%r1),%r25 + copy %r1,%r24 + bl sys_clone,%r2 + ldi SIGCHLD,%r26 + + LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 +wrapper_exit: + ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */ + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + + reg_restore %r1 + + bv %r0(%r2) + nop + + /* Set the return value for the child */ +child_return: + LDREG TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2 + b wrapper_exit + copy %r0,%r28 + + + .export sys_clone_wrapper +sys_clone_wrapper: + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + reg_save %r1 + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 + + STREG %r30,PT_GR20(%r1) + ldil L%child_return,%r3 + ldo R%child_return(%r3),%r3 + LDIL_FIXUP(%r3) + + bl sys_clone,%r2 + STREG %r3,PT_GR21(%r1) /* save for child */ + + b wrapper_exit + LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 + + + .export sys_vfork_wrapper +sys_vfork_wrapper: + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + reg_save %r1 + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 + + STREG %r30,PT_GR20(%r1) + ldil L%child_return,%r3 + ldo R%child_return(%r3),%r3 + LDIL_FIXUP(%r3) + STREG %r3,PT_GR21(%r1) /* save for child */ + + bl sys_vfork,%r2 + copy %r1,%r26 + + b wrapper_exit + LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r2 + + + .macro execve_wrapper execve + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + + /* + * Do we need to save/restore r3-r18 here? + * I don't think so. why would new thread need old + * threads registers? + */ + + /* %arg0 - %arg3 are already saved for us. */ + + STREG %r2,-RP_OFFSET(%r30) + ldo FRAME_SIZE(%r30),%r30 + bl \execve,%r2 + copy %r1,%arg0 + + ldo -FRAME_SIZE(%r30),%r30 + LDREG -RP_OFFSET(%r30),%r2 + + /* If exec succeeded we need to load the args */ + + ldo -1024(%r0),%r1 + comb,>>= %r28,%r1,error_\execve + copy %r2,%r19 + +error_\execve: + bv %r0(%r19) + nop + .endm + + .export sys_execve_wrapper + .import sys_execve + +sys_execve_wrapper: + execve_wrapper sys_execve + +#ifdef __LP64__ + .export sys32_execve_wrapper + .import sys32_execve + +sys32_execve_wrapper: + execve_wrapper sys32_execve +#endif + + .export sys_rt_sigreturn_wrapper +sys_rt_sigreturn_wrapper: + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r26 + /* Don't save regs, we are going to restore them from sigcontext. */ + STREG %r2, -RP_OFFSET(%r30) + bl sys_rt_sigreturn,%r2 + ldo FRAME_SIZE(%r30), %r30 + + ldo -FRAME_SIZE(%r30), %r30 + LDREG -RP_OFFSET(%r30), %r2 + + /* FIXME: I think we need to restore a few more things here. */ + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get pt regs */ + reg_restore %r1 + + /* If the signal was received while the process was blocked on a + * syscall, then r2 will take us to syscall_exit; otherwise r2 will + * take us to syscall_exit_rfi and on to intr_return. + */ + bv %r0(%r2) + LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */ + + .export sys_sigaltstack_wrapper +sys_sigaltstack_wrapper: + /* Get the user stack pointer */ + LDREG -TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24 + STREG %r2, -RP_OFFSET(%r30) + bl do_sigaltstack,%r2 + ldo FRAME_SIZE(%r30), %r30 + + ldo -FRAME_SIZE(%r30), %r30 + LDREG -RP_OFFSET(%r30), %r2 + bv %r0(%r2) + nop + + .export sys_rt_sigsuspend_wrapper +sys_rt_sigsuspend_wrapper: + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r24 + reg_save %r24 + + STREG %r2, -RP_OFFSET(%r30) + bl sys_rt_sigsuspend,%r2 + ldo FRAME_SIZE(%r30), %r30 + + ldo -FRAME_SIZE(%r30), %r30 + LDREG -RP_OFFSET(%r30), %r2 + + ldo TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 + reg_restore %r1 + + bv %r0(%r2) + nop + + .export syscall_exit +syscall_exit: + /* NOTE: HP-UX syscalls also come through here + after hpux_syscall_exit fixes up return + values. */ + /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit + * via syscall_exit_rfi if the signal was received while the process + * was running. All traced processes will probably exit via + * syscall_exit_rfi in the future. + */ + + /* save return value now */ + + STREG %r28,TASK_PT_GR28-TASK_SZ_ALGN-FRAME_SIZE(%r30) + +syscall_check_bh: + +/* #ifdef NOTNOW */ + /* Check for software interrupts */ + + .import irq_stat,data + + ldil L%irq_stat,%r19 + ldo R%irq_stat(%r19),%r19 + LDIL_FIXUP(%r19) + +#ifdef CONFIG_SMP + /* sched.h: int processor */ + ldw TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r20 /* get cpu # */ +#if (IRQSTAT_SZ == 32) + dep %r20,26,27,%r20 /* shift left 5 bits */ +#else +#error IRQSTAT_SZ changed, fix dep +#endif /* IRQSTAT_SZ */ + add %r19,%r20,%r19 +#endif /* CONFIG_SMP */ + + ldw IRQSTAT_SI_ACTIVE(%r19),%r20 /* hardirq.h: unsigned int */ + ldw IRQSTAT_SI_MASK(%r19),%r19 /* hardirq.h: unsigned int */ + and %r19,%r20,%r20 + comib,<>,n 0,%r20,syscall_do_softirq /* forward */ +/* #endif */ + + +syscall_check_resched: + + /* check for reschedule */ + + LDREG TASK_NEED_RESCHED-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19 /* long */ + comib,<>,n 0,%r19,syscall_do_resched /* forward */ + +syscall_check_sig: + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ + /* check for pending signals */ + ldw TASK_SIGPENDING(%r1),%r19 + comib,<>,n 0,%r19,syscall_do_signal /* forward */ + +syscall_restore: + /* disable interrupts while dicking with the kernel stack, */ + /* or life can become unpleasant */ + rsm PSW_SM_I, %r20 + LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */ + bb,<,n %r19,31,syscall_restore_rfi + LDREG TASK_PT_GR20(%r1),%r19 + mtctl %r19, %cr27 + + LDREG TASK_PT_GR2(%r1),%r2 /* restore user rp */ + LDREG TASK_PT_GR21(%r1),%r21 + LDREG TASK_PT_GR22(%r1),%r22 + LDREG TASK_PT_GR23(%r1),%r23 + LDREG TASK_PT_GR24(%r1),%r24 + LDREG TASK_PT_GR25(%r1),%r25 + LDREG TASK_PT_GR26(%r1),%r26 + LDREG TASK_PT_GR27(%r1),%r27 /* restore user dp */ + LDREG TASK_PT_GR28(%r1),%r28 /* syscall return value */ + LDREG TASK_PT_GR29(%r1),%r29 + LDREG TASK_PT_GR30(%r1),%r30 /* restore user sp */ + LDREG TASK_PT_GR31(%r1),%r31 /* restore syscall rp */ + ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */ + rest_fp %r19 + LDREG TASK_PT_SAR(%r1),%r19 /* restore SAR */ + mtsar %r19 + LDREG TASK_PT_GR19(%r1),%r19 + + mtctl %r1,%cr30 /* intrhandler okay. */ + mfsp %sr3,%r1 /* Get users space id */ + mtsp %r1,%sr4 /* Restore sr4 */ + mtsp %r1,%sr5 /* Restore sr5 */ + mtsp %r1,%sr6 /* Restore sr6 */ + + depi 3,31,2,%r31 /* ensure return to user mode. */ + + mtsm %r20 /* restore irq state */ + mfctl %cr27,%r20 + + /* + * Due to a dependency in the tlb miss handlers on sr7, it + * is essential that sr7 get set in the delay slot. + */ + +#ifdef __LP64__ + + /* Note the be (and mtsp) is executed in narrow mode. This is OK + * for 32 bit processes, but won't work once we support 64 bit + * processes. + */ + + rsm PSW_SM_W, %r0 + be 0(%sr3,%r31) /* return to user space */ + mtsp %r1,%sr7 /* Restore sr7 */ +#else + be 0(%sr3,%r31) /* return to user space */ + mtsp %r1,%sr7 /* Restore sr7 */ +#endif + + /* We have to return via an RFI, so that PSW T and R bits can be set + * appropriately. + * This sets up pt_regs so we can return via intr_restore, which is not + * the most efficient way of doing things, but it works. + */ +syscall_restore_rfi: + ldo -1(%r0),%r2 /* Set recovery cntr to -1 */ + mtctl %r2,%cr0 /* for immediate trap */ + copy %r0,%r2 /* Create a reasonable PSW */ + /* XXX W bit??? */ + depi -1,13,1,%r2 + depi -1,28,1,%r2 + depi -1,30,1,%r2 + depi -1,31,1,%r2 + bb,<,n %r19,15,set_rbit /* PT_SINGLESTEP */ + bb,>=,n %r19,14,set_nobit /* PT_BLOCKSTEP, see ptrace.c */ +set_tbit: + depi -1,7,1,%r2 + b,n set_nobit +set_rbit: + depi -1,27,1,%r2 +set_nobit: + STREG %r2,TASK_PT_PSW(%r1) + STREG %r1,TASK_PT_CR30(%r1) + mfsp %sr0,%r2 + STREG %r2,TASK_PT_SR0(%r1) + mfsp %sr1,%r2 + STREG %r2,TASK_PT_SR1(%r1) + mfsp %sr2,%r2 + STREG %r2,TASK_PT_SR2(%r1) + mfsp %sr3,%r2 + STREG %r2,TASK_PT_SR3(%r1) + STREG %r2,TASK_PT_SR4(%r1) + STREG %r2,TASK_PT_SR5(%r1) + STREG %r2,TASK_PT_SR6(%r1) + STREG %r2,TASK_PT_SR7(%r1) + STREG %r2,TASK_PT_IASQ0(%r1) + STREG %r2,TASK_PT_IASQ1(%r1) + LDREG TASK_PT_GR31(%r1),%r2 + depi 3,31,2,%r2 /* ensure return to user mode. */ + STREG %r2,TASK_PT_IAOQ0(%r1) + ldo 4(%r2),%r2 + STREG %r2,TASK_PT_IAOQ1(%r1) + ldo TASK_REGS(%r1),%r25 + reg_save %r25 /* Save r3 to r18 */ + copy %r25,%r16 + b intr_restore + nop + + .import do_softirq,code +syscall_do_softirq: + bl do_softirq,%r2 + nop + b syscall_check_resched + ssm PSW_SM_I, %r0 /* do_softirq returns with I bit off */ + + .import schedule,code +syscall_do_resched: + bl schedule,%r2 + nop + b syscall_check_bh /* if resched, we start over again */ + nop + + .import do_signal,code +syscall_do_signal: + /* Save callee-save registers (for sigcontext). + FIXME: After this point the process structure should be + consistent with all the relevant state of the process + before the syscall. We need to verify this. */ + ldo TASK_REGS(%r1), %r25 /* struct pt_regs *regs */ + reg_save %r25 + + ldi 1, %r24 /* unsigned long in_syscall */ + + bl do_signal,%r2 + copy %r0, %r26 /* sigset_t *oldset = NULL */ + + ldo -TASK_SZ_ALGN-FRAME_SIZE(%r30), %r1 /* reload task ptr */ + ldo TASK_REGS(%r1), %r20 /* reload pt_regs */ + reg_restore %r20 + + b,n syscall_restore + +#ifdef __LP64__ +unimplemented_64bitirq: + ssm PSW_SM_Q+PSW_SM_I, %r0 + /* indicate that we had an interrupt */ + ldi 0x77, %r28 + ldi 0x77, %r29 + /* save interrupt registers in GRs for diagnosis */ + mfctl %cr17, %r17 + mfctl %cr18, %r18 + mfctl %cr19, %r19 + mfctl %cr20, %r20 + mfctl %cr21, %r21 + mfctl %cr22, %r22 + b,n . + nop +#endif diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/hardware.c linux/arch/parisc/kernel/hardware.c --- v2.4.0-test11/linux/arch/parisc/kernel/hardware.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/hardware.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,1446 @@ +/* + * Hardware descriptions for HP 9000 based hardware, including + * system types, SCSI controllers, DMA controllers, HPPB controllers + * and lots more. + * + * Based on the document "PA-RISC 1.1 I/O Firmware Architecture + * Reference Specification", March 7, 1999, version 0.96. This + * is available at ?. + * + * Copyright 1999 by Alex deVries + * and copyright 1999 The Puffin Group Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + + +#include +#include +#include + +#define HPHW_NUM_TYPES 3431 + +static char * hw_type_name[16] = { + "Processor", + "Memory", + "B DMA", + "Obsolete", + "A DMA", + "A Direct", + "Obsolete", + "Bus Converter Port", + "HP CIO Adapter", + "Console", + "Foreign I/O Module", + "Bus Adapter", + "IOA (?)", + "Bus Bridge to Foreign Bus", + "HP Clothing: Fabric Component" +}; + +/* + * XXX Could this be __init ?? + */ + +static struct hp_hardware hp_hardware_list[] = { + {HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"}, + {HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"}, + {HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"}, + {HPHW_NPROC,0xB,0x4,0x01,"Technical Shogun (845, 645)"}, + {HPHW_NPROC,0xF,0x4,0x01,"Commercial Shogun (949)"}, + {HPHW_NPROC,0xC,0x4,0x01,"Cheetah (850, 950)"}, + {HPHW_NPROC,0x80,0x4,0x01,"Cheetah (950S)"}, + {HPHW_NPROC,0x81,0x4,0x01,"Jaguar (855, 955)"}, + {HPHW_NPROC,0x82,0x4,0x01,"Cougar (860, 960)"}, + {HPHW_NPROC,0x83,0x4,0x13,"Panther (865, 870, 980)"}, + {HPHW_NPROC,0x100,0x4,0x01,"Burgundy (810)"}, + {HPHW_NPROC,0x101,0x4,0x01,"SilverFox Low (822, 922)"}, + {HPHW_NPROC,0x102,0x4,0x01,"SilverFox High (832, 932)"}, + {HPHW_NPROC,0x103,0x4,0x01,"Lego, SilverLite (815, 808, 920)"}, + {HPHW_NPROC,0x104,0x4,0x03,"SilverBullet Low (842, 948)"}, + {HPHW_NPROC,0x105,0x4,0x03,"SilverBullet High (852, 958)"}, + {HPHW_NPROC,0x106,0x4,0x81,"Oboe"}, + {HPHW_NPROC,0x180,0x4,0x12,"Dragon"}, + {HPHW_NPROC,0x181,0x4,0x13,"Chimera (890, 990, 992)"}, + {HPHW_NPROC,0x182,0x4,0x91,"TNT 100 (891,T500)"}, + {HPHW_NPROC,0x183,0x4,0x91,"TNT 120 (892,T520)"}, + {HPHW_NPROC,0x184,0x4,0x91,"Jade 180 U (893,T540)"}, + {HPHW_NPROC,0x1FF,0x4,0x91,"Hitachi X Processor"}, + {HPHW_NPROC,0x200,0x4,0x81,"Cobra (720)"}, + {HPHW_NPROC,0x201,0x4,0x81,"Coral (750)"}, + {HPHW_NPROC,0x202,0x4,0x81,"King Cobra (730)"}, + {HPHW_NPROC,0x203,0x4,0x81,"Hardball (735/99)"}, + {HPHW_NPROC,0x204,0x4,0x81,"Coral II (755/99)"}, + {HPHW_NPROC,0x205,0x4,0x81,"Coral II (755/125)"}, + {HPHW_NPROC,0x205,0x4,0x91,"Snake Eagle "}, + {HPHW_NPROC,0x206,0x4,0x81,"Snake Cheetah (735/130)"}, + {HPHW_NPROC,0x280,0x4,0x81,"Nova Low (817, 827, 957, 957LX)"}, + {HPHW_NPROC,0x281,0x4,0x81,"Nova High (837, 847, 857, 967, 967LX)"}, + {HPHW_NPROC,0x282,0x4,0x81,"Nova8 (807, 917, 917LX, 927,927LX, 937, 937LX, 947,947LX)"}, + {HPHW_NPROC,0x283,0x4,0x81,"Nova64 (867, 877, 977)"}, + {HPHW_NPROC,0x284,0x4,0x81,"TNova (887, 897, 987)"}, + {HPHW_NPROC,0x285,0x4,0x81,"TNova64"}, + {HPHW_NPROC,0x286,0x4,0x91,"Hydra64 (Nova)"}, + {HPHW_NPROC,0x287,0x4,0x91,"Hydra96 (Nova)"}, + {HPHW_NPROC,0x288,0x4,0x81,"TNova96"}, + {HPHW_NPROC,0x300,0x4,0x81,"Bushmaster (710)"}, + {HPHW_NPROC,0x302,0x4,0x81,"Flounder (705)"}, + {HPHW_NPROC,0x310,0x4,0x81,"Scorpio (715/50)"}, + {HPHW_NPROC,0x311,0x4,0x81,"Scorpio Jr.(715/33)"}, + {HPHW_NPROC,0x312,0x4,0x81,"Strider-50 (715S/50)"}, + {HPHW_NPROC,0x313,0x4,0x81,"Strider-33 (715S/33)"}, + {HPHW_NPROC,0x314,0x4,0x81,"Trailways-50 (715T/50)"}, + {HPHW_NPROC,0x315,0x4,0x81,"Trailways-33 (715T/33)"}, + {HPHW_NPROC,0x316,0x4,0x81,"Scorpio Sr.(715/75)"}, + {HPHW_NPROC,0x317,0x4,0x81,"Scorpio 100 (715/100)"}, + {HPHW_NPROC,0x318,0x4,0x81,"Spectra (725/50)"}, + {HPHW_NPROC,0x319,0x4,0x81,"Spectra (725/75)"}, + {HPHW_NPROC,0x320,0x4,0x81,"Spectra (725/100)"}, + {HPHW_NPROC,0x401,0x4,0x81,"Pace (745i, 747i)"}, + {HPHW_NPROC,0x402,0x4,0x81,"Sidewinder (742i)"}, + {HPHW_NPROC,0x403,0x4,0x81,"Fast Pace"}, + {HPHW_NPROC,0x480,0x4,0x81,"Orville (E23)"}, + {HPHW_NPROC,0x481,0x4,0x81,"Wilbur (E25)"}, + {HPHW_NPROC,0x482,0x4,0x81,"WB-80 (E35)"}, + {HPHW_NPROC,0x483,0x4,0x81,"WB-96 (E45)"}, + {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-100 (811/D210,D310)"}, + {HPHW_NPROC,0x48,0x4,0x81,"UL Proc L-75 (801/D200)"}, + {HPHW_NPROC,0x501,0x4,0x81,"Merlin L2 132 (9000/778/B132L)"}, + {HPHW_NPROC,0x502,0x4,0x81,"Merlin L2 160 (9000/778/B160L)"}, + {HPHW_NPROC,0x503,0x4,0x81,"Merlin L2+ 132 (9000/778/B132L)"}, + {HPHW_NPROC,0x504,0x4,0x81,"Merlin L2+ 180 (9000/778/B180L)"}, + {HPHW_NPROC,0x505,0x4,0x81,"Raven L2 132 (9000/778/C132L)"}, + {HPHW_NPROC,0x506,0x4,0x81,"Raven L2 160 (9000/779/C160L)"}, + {HPHW_NPROC,0x507,0x4,0x81,"Raven L2 180 (9000/779/C180L)"}, + {HPHW_NPROC,0x508,0x4,0x81,"Raven L2 160 (9000/779/C160L)"}, + {HPHW_NPROC,0x509,0x4,0x81,"712/132 L2 Upgrade"}, + {HPHW_NPROC,0x50A,0x4,0x81,"712/160 L2 Upgrade"}, + {HPHW_NPROC,0x50B,0x4,0x81,"715/132 L2 Upgrade"}, + {HPHW_NPROC,0x50C,0x4,0x81,"715/160 L2 Upgrade"}, + {HPHW_NPROC,0x50D,0x4,0x81,"Rocky2 L2 120"}, + {HPHW_NPROC,0x50E,0x4,0x81,"Rocky2 L2 150"}, + {HPHW_NPROC,0x50F,0x4,0x81,"Anole L2 132 (744)"}, + {HPHW_NPROC,0x510,0x4,0x81,"Anole L2 165 (744)"}, + {HPHW_NPROC,0x511,0x4,0x81,"Kiji L2 132"}, + {HPHW_NPROC,0x512,0x4,0x81,"UL L2 132 (803/D220,D320)"}, + {HPHW_NPROC,0x513,0x4,0x81,"UL L2 160 (813/D220,D320)"}, + {HPHW_NPROC,0x514,0x4,0x81,"Merlin Jr L2 132"}, + {HPHW_NPROC,0x515,0x4,0x81,"Staccato L2 132"}, + {HPHW_NPROC,0x516,0x4,0x81,"Staccato L2 180 (A Class 180)"}, + {HPHW_NPROC,0x580,0x4,0x81,"KittyHawk DC2-100 (K100)"}, + {HPHW_NPROC,0x581,0x4,0x91,"KittyHawk DC3-120 (K210)"}, + {HPHW_NPROC,0x582,0x4,0x91,"KittyHawk DC3 100 (K400)"}, + {HPHW_NPROC,0x583,0x4,0x91,"KittyHawk DC3 120 (K410)"}, + {HPHW_NPROC,0x584,0x4,0x91,"LighteningHawk T120"}, + {HPHW_NPROC,0x585,0x4,0x91,"SkyHawk 100"}, + {HPHW_NPROC,0x586,0x4,0x91,"SkyHawk 120"}, + {HPHW_NPROC,0x587,0x4,0x81,"UL Proc 1-way T'120"}, + {HPHW_NPROC,0x588,0x4,0x91,"UL Proc 2-way T'120"}, + {HPHW_NPROC,0x589,0x4,0x81,"UL Proc 1-way T'100 (821/D250,D350)"}, + {HPHW_NPROC,0x58A,0x4,0x91,"UL Proc 2-way T'100 (831/D250,D350)"}, + {HPHW_NPROC,0x58B,0x4,0x91,"KittyHawk DC2 100 (K200)"}, + {HPHW_NPROC,0x58C,0x4,0x91,"ThunderHawk DC3- 120 1M (K220)"}, + {HPHW_NPROC,0x58D,0x4,0x91,"ThunderHawk DC3 120 1M (K420)"}, + {HPHW_NPROC,0x58E,0x4,0x81,"Raven 120 T'"}, + {HPHW_NPROC,0x58F,0x4,0x91,"Mohawk 160 U 1M DC3 (K450)"}, + {HPHW_NPROC,0x590,0x4,0x91,"Mohawk 180 U 1M DC3 (K460)"}, + {HPHW_NPROC,0x591,0x4,0x91,"Mohawk 200 U 1M DC3"}, + {HPHW_NPROC,0x592,0x4,0x81,"Raven 100 T'"}, + {HPHW_NPROC,0x593,0x4,0x91,"FireHawk 160 U"}, + {HPHW_NPROC,0x594,0x4,0x91,"FireHawk 180 U"}, + {HPHW_NPROC,0x595,0x4,0x91,"FireHawk 220 U"}, + {HPHW_NPROC,0x596,0x4,0x91,"FireHawk 240 U"}, + {HPHW_NPROC,0x597,0x4,0x91,"SPP2000 processor"}, + {HPHW_NPROC,0x598,0x4,0x81,"Raven U 230 (9000/780/C230)"}, + {HPHW_NPROC,0x599,0x4,0x81,"Raven U 240 (9000/780/C240)"}, + {HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"}, + {HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"}, + {HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"}, + {HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"}, + {HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"}, + {HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780/\?\?\?\?)"}, + {HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"}, + {HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"}, + {HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"}, + {HPHW_NPROC,0x5A3,0x4,0x91,"UL 2w U160 512K/512K (871/D270,D370)"}, + {HPHW_NPROC,0x5A4,0x4,0x91,"Mohawk 160 U 1M DC3- (K250)"}, + {HPHW_NPROC,0x5A5,0x4,0x91,"Mohawk 180 U 1M DC3- (K260)"}, + {HPHW_NPROC,0x5A6,0x4,0x91,"Mohawk 200 U 1M DC3-"}, + {HPHW_NPROC,0x5A7,0x4,0x81,"UL proc 1-way U160 1M/1M"}, + {HPHW_NPROC,0x5A8,0x4,0x91,"UL proc 2-way U160 1M/1M"}, + {HPHW_NPROC,0x5A9,0x4,0x81,"UL proc 1-way U180 1M/1M"}, + {HPHW_NPROC,0x5AA,0x4,0x91,"UL proc 2-way U180 1M/1M"}, + {HPHW_NPROC,0x5AB,0x4,0x91,"Obsolete"}, + {HPHW_NPROC,0x5AB,0x4,0x81,"Obsolete"}, + {HPHW_NPROC,0x5AC,0x4,0x91,"Obsolete"}, + {HPHW_NPROC,0x5AC,0x4,0x81,"Obsolete"}, + {HPHW_NPROC,0x5AD,0x4,0x91,"BraveHawk 180MHz DC3-"}, + {HPHW_NPROC,0x5AE,0x4,0x91,"BraveHawk 200MHz DC3- (898/K370)"}, + {HPHW_NPROC,0x5AF,0x4,0x91,"BraveHawk 220MHz DC3-"}, + {HPHW_NPROC,0x5B0,0x4,0x91,"BraveHawk 180MHz DC3"}, + {HPHW_NPROC,0x5B1,0x4,0x91,"BraveHawk 200MHz DC3 (899/K570)"}, + {HPHW_NPROC,0x5B2,0x4,0x91,"BraveHawk 220MHz DC3"}, + {HPHW_NPROC,0x5B3,0x4,0x91,"FireHawk 200"}, + {HPHW_NPROC,0x5B4,0x4,0x91,"SPP2500"}, + {HPHW_NPROC,0x5B5,0x4,0x91,"SummitHawk U+"}, + {HPHW_NPROC,0x5B6,0x4,0x91,"DragonHawk U+ 240 DC3"}, + {HPHW_NPROC,0x5B7,0x4,0x91,"DragonHawk U+ 240 DC3-"}, + {HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"}, + {HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"}, + {HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"}, + {HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W "}, + {HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"}, + {HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"}, + {HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"}, + {HPHW_NPROC,0x5BF,0x4,0x91,"Forte W 4-way"}, + {HPHW_NPROC,0x5C0,0x4,0x91,"M2250"}, + {HPHW_NPROC,0x5C1,0x4,0x91,"M2500"}, + {HPHW_NPROC,0x5C2,0x4,0x91,"Sonata 440"}, + {HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"}, + {HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"}, + {HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"}, + {HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780/\?\?\?\?)"}, + {HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"}, + {HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"}, + {HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"}, + {HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"}, + {HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"}, + {HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"}, + {HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"}, + {HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"}, + {HPHW_NPROC,0x602,0x4,0x81,"Gecko 100 (712/100)"}, + {HPHW_NPROC,0x603,0x4,0x81,"Anole 64 (743/64)"}, + {HPHW_NPROC,0x604,0x4,0x81,"Anole 100 (743/100)"}, + {HPHW_NPROC,0x605,0x4,0x81,"Gecko 120 (712/120)"}, + {HPHW_NPROC,0x606,0x4,0x81,"Gila 80"}, + {HPHW_NPROC,0x607,0x4,0x81,"Gila 100"}, + {HPHW_NPROC,0x608,0x4,0x81,"Gila 120"}, + {HPHW_NPROC,0x609,0x4,0x81,"Scorpio-L 80"}, + {HPHW_NPROC,0x60A,0x4,0x81,"Mirage Jr (715/64)"}, + {HPHW_NPROC,0x60B,0x4,0x81,"Mirage 100"}, + {HPHW_NPROC,0x60C,0x4,0x81,"Mirage 100+"}, + {HPHW_NPROC,0x60D,0x4,0x81,"Electra 100"}, + {HPHW_NPROC,0x60E,0x4,0x81,"Electra 120"}, + {HPHW_NPROC,0x610,0x4,0x81,"Scorpio-L 100"}, + {HPHW_NPROC,0x611,0x4,0x81,"Scorpio-L 120"}, + {HPHW_NPROC,0x612,0x4,0x81,"Spectra-L 80"}, + {HPHW_NPROC,0x613,0x4,0x81,"Spectra-L 100"}, + {HPHW_NPROC,0x614,0x4,0x81,"Spectra-L 120"}, + {HPHW_NPROC,0x615,0x4,0x81,"Piranha 100"}, + {HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"}, + {HPHW_NPROC,0x617,0x4,0x81,"Jason 50"}, + {HPHW_NPROC,0x618,0x4,0x81,"Jason 100"}, + {HPHW_NPROC,0x619,0x4,0x81,"Mirage 80 "}, + {HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"}, + {HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"}, + {HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"}, + {HPHW_NPROC,0x67E,0x4,0x81,"Hitachi Tiny 80"}, + {HPHW_NPROC,0x67F,0x4,0x81,"Hitachi Tiny 64"}, + {HPHW_NPROC,0x700,0x4,0x91,"NEC Aska Processor"}, + {HPHW_A_DIRECT, 0x004, 0x0000D, 0x00, "Arrakis MUX"}, + {HPHW_A_DIRECT, 0x005, 0x0000D, 0x00, "Dyun Kiuh MUX"}, + {HPHW_A_DIRECT, 0x006, 0x0000D, 0x00, "Baat Kiuh AP/MUX (40299B)"}, + {HPHW_A_DIRECT, 0x007, 0x0000D, 0x00, "Dino AP"}, + {HPHW_A_DIRECT, 0x009, 0x0000D, 0x00, "Solaris Direct Connect MUX (J2092A)"}, + {HPHW_A_DIRECT, 0x00A, 0x0000D, 0x00, "Solaris RS-422/423 MUX (J2093A)"}, + {HPHW_A_DIRECT, 0x00B, 0x0000D, 0x00, "Solaris RS-422/423 Quadriloops MUX"}, + {HPHW_A_DIRECT, 0x00C, 0x0000D, 0x00, "Solaris Modem MUX (J2094A)"}, + {HPHW_A_DIRECT, 0x00D, 0x0000D, 0x00, "Twins Direct Connect MUX"}, + {HPHW_A_DIRECT, 0x00E, 0x0000D, 0x00, "Twins Modem MUX"}, + {HPHW_A_DIRECT, 0x00F, 0x0000D, 0x00, "Nautilus RS-485"}, + {HPHW_A_DIRECT, 0x010, 0x0000D, 0x00, "UltraLight CAP/MUX"}, + {HPHW_A_DIRECT, 0x015, 0x0000D, 0x00, "Eole CAP/MUX"}, + {HPHW_A_DIRECT, 0x024, 0x0000D, 0x00, "Sahp Kiuh AP/MUX"}, + {HPHW_A_DIRECT, 0x034, 0x0000D, 0x00, "Sahp Kiuh Low AP/MUX"}, + {HPHW_A_DIRECT, 0x044, 0x0000D, 0x00, "Sahp Baat Kiuh AP/MUX"}, + {HPHW_A_DIRECT, 0x004, 0x0000E, 0x80, "Burgundy RS-232"}, + {HPHW_A_DIRECT, 0x005, 0x0000E, 0x80, "Silverfox RS-232"}, + {HPHW_A_DIRECT, 0x006, 0x0000E, 0x80, "Lego RS-232"}, + {HPHW_A_DIRECT, 0x004, 0x0000F, 0x00, "Peacock Graphics"}, + {HPHW_A_DIRECT, 0x004, 0x00014, 0x80, "Burgundy HIL"}, + {HPHW_A_DIRECT, 0x005, 0x00014, 0x80, "Peacock HIL"}, + {HPHW_A_DIRECT, 0x004, 0x00015, 0x80, "Leonardo"}, + {HPHW_A_DIRECT, 0x004, 0x00016, 0x80, "HP-PB HRM"}, + {HPHW_A_DIRECT, 0x004, 0x00017, 0x80, "HP-PB HRC"}, + {HPHW_A_DIRECT, 0x004, 0x0003A, 0x80, "Skunk Centronics (28655A)"}, + {HPHW_A_DIRECT, 0x024, 0x0003A, 0x80, "Sahp Kiuh Centronics"}, + {HPHW_A_DIRECT, 0x044, 0x0003A, 0x80, "Sahp Baat Kiuh Centronics"}, + {HPHW_A_DIRECT, 0x004, 0x0004E, 0x80, "AT&T DataKit (AMSO)"}, + {HPHW_A_DIRECT, 0x004, 0x0009B, 0x80, "Test&Meas GSC HPIB"}, + {HPHW_A_DIRECT, 0x004, 0x000A8, 0x00, "Rocky2-120 Front Keyboard"}, + {HPHW_A_DIRECT, 0x005, 0x000A8, 0x00, "Rocky2-150 Front Keyboard"}, + {HPHW_A_DIRECT, 0x004, 0x00101, 0x80, "Hitachi Console Module"}, + {HPHW_A_DIRECT, 0x004, 0x00102, 0x80, "Hitachi Boot Module"}, + {HPHW_A_DIRECT, 0x004, 0x00203, 0x80, "MELCO HBMLA MLAIT"}, + {HPHW_A_DIRECT, 0x004, 0x00208, 0x80, "MELCO HBDPC"}, + {HPHW_A_DIRECT, 0x004, 0x00300, 0x00, "DCI TWINAX TERM IO MUX"}, + {HPHW_A_DMA, 0x004, 0x00039, 0x80, "Skunk SCSI (28655A)"}, + {HPHW_A_DMA, 0x005, 0x00039, 0x80, "KittyHawk CSY Core SCSI"}, + {HPHW_A_DMA, 0x014, 0x00039, 0x80, "Diablo SCSI"}, + {HPHW_A_DMA, 0x024, 0x00039, 0x80, "Sahp Kiuh SCSI"}, + {HPHW_A_DMA, 0x034, 0x00039, 0x80, "Sahp Kiuh Low SCSI"}, + {HPHW_A_DMA, 0x044, 0x00039, 0x80, "Sahp Baat Kiuh SCSI"}, + {HPHW_A_DMA, 0x004, 0x0003B, 0x80, "Wizard SCSI"}, + {HPHW_A_DMA, 0x005, 0x0003B, 0x80, "KittyHawk CSY Core FW-SCSI"}, + {HPHW_A_DMA, 0x006, 0x0003B, 0x80, "Symbios EPIC FW-SCSI"}, + {HPHW_A_DMA, 0x004, 0x00040, 0x80, "HP-PB Shazam HPIB (28650A)"}, + {HPHW_A_DMA, 0x005, 0x00040, 0x80, "Burgundy HPIB"}, + {HPHW_A_DMA, 0x004, 0x00041, 0x80, "HP-PB HP-FL"}, + {HPHW_A_DMA, 0x004, 0x00042, 0x80, "HP-PB LoQuix HPIB (28650B)"}, + {HPHW_A_DMA, 0x004, 0x00043, 0x80, "HP-PB Crypt LoQuix"}, + {HPHW_A_DMA, 0x004, 0x00044, 0x80, "HP-PB Shazam GPIO (28651A)"}, + {HPHW_A_DMA, 0x004, 0x00045, 0x80, "HP-PB LoQuix GPIO"}, + {HPHW_A_DMA, 0x004, 0x00046, 0x80, "2-Port X.25 NIO_ACC (AMSO)"}, + {HPHW_A_DMA, 0x004, 0x00047, 0x80, "4-Port X.25 NIO_ACC (AMSO)"}, + {HPHW_A_DMA, 0x004, 0x0004B, 0x80, "LGB Control"}, + {HPHW_A_DMA, 0x004, 0x0004C, 0x80, "Martian RTI (AMSO)"}, + {HPHW_A_DMA, 0x004, 0x0004D, 0x80, "ACC Mux (AMSO)"}, + {HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"}, + {HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"}, + {HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"}, + {HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"}, + {HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"}, + {HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"}, + {HPHW_A_DMA, 0x015, 0x00089, 0x80, "KittyHawk GSY Core FW-SCSI"}, + {HPHW_A_DMA, 0x017, 0x00089, 0x80, "Shrike Jade Add-on FW-SCSI (A3644A)"}, + {HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"}, + {HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"}, + {HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"}, + {HPHW_A_DMA, 0x03d, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"}, + {HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"}, + {HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"}, + {HPHW_A_DMA, 0x058, 0x00089, 0x80, "FireHawk 200 FW-SCSI"}, + {HPHW_A_DMA, 0x05C, 0x00089, 0x80, "SummitHawk 230 Ultra-SCSI"}, + {HPHW_A_DMA, 0x014, 0x00091, 0x80, "Baby Hugo Add-on Net FC (A3406A)"}, + {HPHW_A_DMA, 0x020, 0x00091, 0x80, "Baby Jade Add-on Net FC (A3638A)"}, + {HPHW_A_DMA, 0x004, 0x00092, 0x80, "GSC+ YLIASTER ATM"}, + {HPHW_A_DMA, 0x004, 0x00095, 0x80, "Hamlyn GSC+ Network Card"}, + {HPHW_A_DMA, 0x004, 0x00098, 0x80, "Lo-fat Emulator"}, + {HPHW_A_DMA, 0x004, 0x0009A, 0x80, "GSC+ Venus ATM"}, + {HPHW_A_DMA, 0x005, 0x0009A, 0x80, "GSC+ Samorobrive ATM"}, + {HPHW_A_DMA, 0x004, 0x0009D, 0x80, "HP HSC-PCI Cards"}, + {HPHW_A_DMA, 0x004, 0x0009E, 0x80, "Alaxis GSC+ 155Mb ATM"}, + {HPHW_A_DMA, 0x005, 0x0009E, 0x80, "Alaxis GSC+ 622Mb ATM"}, + {HPHW_A_DMA, 0x05C, 0x0009F, 0x80, "SummitHawk 230 USB"}, + {HPHW_A_DMA, 0x05C, 0x000A0, 0x80, "SummitHawk 230 100BaseT"}, + {HPHW_A_DMA, 0x015, 0x000A7, 0x80, "Baby Hugo Add-on mass FC (A3404A)"}, + {HPHW_A_DMA, 0x018, 0x000A7, 0x80, "Mombasa GS Add-on mass FC (A3591)"}, + {HPHW_A_DMA, 0x021, 0x000A7, 0x80, "Baby Jade Add-on mass FC (A3636A)"}, + {HPHW_A_DMA, 0x004, 0x00201, 0x80, "MELCO HCMAP"}, + {HPHW_A_DMA, 0x004, 0x00202, 0x80, "MELCO HBMLA MLAMA"}, + {HPHW_A_DMA, 0x004, 0x00205, 0x80, "MELCO HBRFU"}, + {HPHW_A_DMA, 0x004, 0x00380, 0x80, "Interphase NIO-FC"}, + {HPHW_A_DMA, 0x004, 0x00381, 0x80, "Interphase NIO-ATM"}, + {HPHW_A_DMA, 0x004, 0x00382, 0x80, "Interphase NIO-100BaseTX"}, + {HPHW_BA, 0x004, 0x00070, 0x0, "Cobra Core BA"}, + {HPHW_BA, 0x005, 0x00070, 0x0, "Coral Core BA"}, + {HPHW_BA, 0x006, 0x00070, 0x0, "Bushmaster Core BA"}, + {HPHW_BA, 0x007, 0x00070, 0x0, "Scorpio Core BA"}, + {HPHW_BA, 0x008, 0x00070, 0x0, "Flounder Core BA"}, + {HPHW_BA, 0x009, 0x00070, 0x0, "Outfield Core BA"}, + {HPHW_BA, 0x00A, 0x00070, 0x0, "CoralII Core BA"}, + {HPHW_BA, 0x00B, 0x00070, 0x0, "Scorpio Jr. Core BA"}, + {HPHW_BA, 0x00C, 0x00070, 0x0, "Strider-50 Core BA"}, + {HPHW_BA, 0x00D, 0x00070, 0x0, "Strider-33 Core BA"}, + {HPHW_BA, 0x00E, 0x00070, 0x0, "Trailways-50 Core BA"}, + {HPHW_BA, 0x00F, 0x00070, 0x0, "Trailways-33 Core BA"}, + {HPHW_BA, 0x010, 0x00070, 0x0, "Pace Core BA"}, + {HPHW_BA, 0x011, 0x00070, 0x0, "Sidewinder Core BA"}, + {HPHW_BA, 0x019, 0x00070, 0x0, "Scorpio Sr. Core BA"}, + {HPHW_BA, 0x020, 0x00070, 0x0, "Scorpio 100 Core BA"}, + {HPHW_BA, 0x021, 0x00070, 0x0, "Spectra 50 Core BA"}, + {HPHW_BA, 0x022, 0x00070, 0x0, "Spectra 75 Core BA"}, + {HPHW_BA, 0x023, 0x00070, 0x0, "Spectra 100 Core BA"}, + {HPHW_BA, 0x024, 0x00070, 0x0, "Fast Pace Core BA"}, + {HPHW_BA, 0x026, 0x00070, 0x0, "CoralII Jaguar Core BA"}, + {HPHW_BA, 0x004, 0x00076, 0x0, "Cobra EISA BA"}, + {HPHW_BA, 0x005, 0x00076, 0x0, "Coral EISA BA"}, + {HPHW_BA, 0x007, 0x00076, 0x0, "Scorpio EISA BA"}, + {HPHW_BA, 0x00A, 0x00076, 0x0, "CoralII EISA BA"}, + {HPHW_BA, 0x00B, 0x00076, 0x0, "Scorpio Jr. EISA BA"}, + {HPHW_BA, 0x00C, 0x00076, 0x0, "Strider-50 Core EISA"}, + {HPHW_BA, 0x00D, 0x00076, 0x0, "Strider-33 Core EISA"}, + {HPHW_BA, 0x00E, 0x00076, 0x0, "Trailways-50 Core EISA"}, + {HPHW_BA, 0x00F, 0x00076, 0x0, "Trailways-33 Core EISA"}, + {HPHW_BA, 0x010, 0x00076, 0x0, "Pace Core EISA"}, + {HPHW_BA, 0x019, 0x00076, 0x0, "Scorpio Sr. EISA BA"}, + {HPHW_BA, 0x020, 0x00076, 0x0, "Scorpio 100 EISA BA"}, + {HPHW_BA, 0x021, 0x00076, 0x0, "Spectra 50 EISA BA"}, + {HPHW_BA, 0x022, 0x00076, 0x0, "Spectra 75 EISA BA"}, + {HPHW_BA, 0x023, 0x00076, 0x0, "Spectra 100 EISA BA"}, + {HPHW_BA, 0x026, 0x00076, 0x0, "CoralII Jaguar EISA BA"}, + {HPHW_BA, 0x010, 0x00078, 0x0, "Pace VME BA"}, + {HPHW_BA, 0x011, 0x00078, 0x0, "Sidewinder VME BA"}, + {HPHW_BA, 0x01A, 0x00078, 0x0, "Anole 64 VME BA"}, + {HPHW_BA, 0x01B, 0x00078, 0x0, "Anole 100 VME BA"}, + {HPHW_BA, 0x024, 0x00078, 0x0, "Fast Pace VME BA"}, + {HPHW_BA, 0x034, 0x00078, 0x0, "Anole T VME BA"}, + {HPHW_BA, 0x04A, 0x00078, 0x0, "Anole L2 132 BME BA"}, + {HPHW_BA, 0x04C, 0x00078, 0x0, "Anole L2 165 VME BA"}, + {HPHW_BA, 0x011, 0x00081, 0x0, "WB-96 Core BA"}, + {HPHW_BA, 0x012, 0x00081, 0x0, "Orville UX Core BA"}, + {HPHW_BA, 0x013, 0x00081, 0x0, "Wilbur UX Core BA"}, + {HPHW_BA, 0x014, 0x00081, 0x0, "WB-80 Core BA"}, + {HPHW_BA, 0x015, 0x00081, 0x0, "KittyHawk GSY Core BA"}, + {HPHW_BA, 0x016, 0x00081, 0x0, "Gecko Core BA"}, + {HPHW_BA, 0x018, 0x00081, 0x0, "Gecko Optional BA"}, + {HPHW_BA, 0x01A, 0x00081, 0x0, "Anole 64 Core BA"}, + {HPHW_BA, 0x01B, 0x00081, 0x0, "Anole 100 Core BA"}, + {HPHW_BA, 0x01C, 0x00081, 0x0, "Gecko 80 Core BA"}, + {HPHW_BA, 0x01D, 0x00081, 0x0, "Gecko 100 Core BA"}, + {HPHW_BA, 0x01F, 0x00081, 0x0, "SkyHawk 100/120 Core BA"}, + {HPHW_BA, 0x027, 0x00081, 0x0, "Piranha 100 Core BA"}, + {HPHW_BA, 0x028, 0x00081, 0x0, "Mirage Jr Core BA"}, + {HPHW_BA, 0x029, 0x00081, 0x0, "Mirage Core BA"}, + {HPHW_BA, 0x02A, 0x00081, 0x0, "Electra Core BA"}, + {HPHW_BA, 0x02B, 0x00081, 0x0, "Mirage 80 Core BA"}, + {HPHW_BA, 0x02C, 0x00081, 0x0, "Mirage 100+ Core BA"}, + {HPHW_BA, 0x02E, 0x00081, 0x0, "UL 350 Lasi Core BA"}, + {HPHW_BA, 0x02F, 0x00081, 0x0, "UL 550 Lasi Core BA"}, + {HPHW_BA, 0x032, 0x00081, 0x0, "Raven T' Core BA"}, + {HPHW_BA, 0x033, 0x00081, 0x0, "Anole T Core BA"}, + {HPHW_BA, 0x034, 0x00081, 0x0, "SAIC L-80 Core BA"}, + {HPHW_BA, 0x035, 0x00081, 0x0, "PCX-L2 712/132 Core BA"}, + {HPHW_BA, 0x036, 0x00081, 0x0, "PCX-L2 712/160 Core BA"}, + {HPHW_BA, 0x03B, 0x00081, 0x0, "Raven U/L2 Core BA"}, + {HPHW_BA, 0x03C, 0x00081, 0x0, "Merlin 132 Core BA"}, + {HPHW_BA, 0x03D, 0x00081, 0x0, "Merlin 160 Core BA"}, + {HPHW_BA, 0x03E, 0x00081, 0x0, "Merlin+ 132 Core BA"}, + {HPHW_BA, 0x03F, 0x00081, 0x0, "Merlin+ 180 Core BA"}, + {HPHW_BA, 0x044, 0x00081, 0x0, "Mohawk Core BA"}, + {HPHW_BA, 0x045, 0x00081, 0x0, "Rocky1 Core BA"}, + {HPHW_BA, 0x046, 0x00081, 0x0, "Rocky2 120 Core BA"}, + {HPHW_BA, 0x047, 0x00081, 0x0, "Rocky2 150 Core BA"}, + {HPHW_BA, 0x04B, 0x00081, 0x0, "Anole L2 132 Core BA"}, + {HPHW_BA, 0x04D, 0x00081, 0x0, "Anole L2 165 Core BA"}, + {HPHW_BA, 0x04E, 0x00081, 0x0, "Kiji L2 132 Core BA"}, + {HPHW_BA, 0x050, 0x00081, 0x0, "Merlin Jr 132 Core BA"}, + {HPHW_BA, 0x051, 0x00081, 0x0, "Firehawk Core BA"}, + {HPHW_BA, 0x056, 0x00081, 0x0, "Raven+ w SE FWSCSI Core BA"}, + {HPHW_BA, 0x057, 0x00081, 0x0, "Raven+ w Diff FWSCSI Core BA"}, + {HPHW_BA, 0x058, 0x00081, 0x0, "FireHawk 200 Core BA"}, + {HPHW_BA, 0x05C, 0x00081, 0x0, "SummitHawk 230 Core BA"}, + {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 132 Core BA"}, + {HPHW_BA, 0x05E, 0x00081, 0x0, "Staccato 180 Core BA"}, + {HPHW_BA, 0x05F, 0x00081, 0x0, "Staccato 180 Lasi"}, + {HPHW_BA, 0x800, 0x00081, 0x0, "Hitachi Tiny 64 Core BA"}, + {HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"}, + {HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"}, + {HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"}, + {HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"}, + {HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"}, + {HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"}, + {HPHW_BA, 0x014, 0x0008E, 0x0, "Electra Wax BA"}, + {HPHW_BA, 0x017, 0x0008E, 0x0, "Raven Backplane Wax BA"}, + {HPHW_BA, 0x01E, 0x0008E, 0x0, "Raven T' Wax BA"}, + {HPHW_BA, 0x01F, 0x0008E, 0x0, "SkyHawk Wax BA"}, + {HPHW_BA, 0x023, 0x0008E, 0x0, "Rocky1 Wax BA"}, + {HPHW_BA, 0x02B, 0x0008E, 0x0, "Mirage 80 Wax BA"}, + {HPHW_BA, 0x02C, 0x0008E, 0x0, "Mirage 100+ Wax BA"}, + {HPHW_BA, 0x030, 0x0008E, 0x0, "UL 350 Core Wax BA"}, + {HPHW_BA, 0x031, 0x0008E, 0x0, "UL 550 Core Wax BA"}, + {HPHW_BA, 0x034, 0x0008E, 0x0, "SAIC L-80 Wax BA"}, + {HPHW_BA, 0x03A, 0x0008E, 0x0, "Merlin+ Wax BA"}, + {HPHW_BA, 0x040, 0x0008E, 0x0, "Merlin 132 Wax BA"}, + {HPHW_BA, 0x041, 0x0008E, 0x0, "Merlin 160 Wax BA"}, + {HPHW_BA, 0x043, 0x0008E, 0x0, "Merlin 132/160 Wax BA"}, + {HPHW_BA, 0x052, 0x0008E, 0x0, "Raven+ Hi Power Backplane w/EISA Wax BA"}, + {HPHW_BA, 0x054, 0x0008E, 0x0, "Raven+ Lo Power Backplane w/EISA Wax BA"}, + {HPHW_BA, 0x059, 0x0008E, 0x0, "FireHawk 200 Wax BA"}, + {HPHW_BA, 0x05A, 0x0008E, 0x0, "Raven+ L2 Backplane w/EISA Wax BA"}, + {HPHW_BA, 0x05D, 0x0008E, 0x0, "SummitHawk Wax BA"}, + {HPHW_BA, 0x800, 0x0008E, 0x0, "Hitachi Tiny 64 Wax BA"}, + {HPHW_BA, 0x801, 0x0008E, 0x0, "Hitachi Tiny 80 Wax BA"}, + {HPHW_BA, 0x011, 0x00090, 0x0, "SuperPace Wax EISA BA"}, + {HPHW_BA, 0x017, 0x00090, 0x0, "Raven Backplane Wax EISA BA"}, + {HPHW_BA, 0x01E, 0x00090, 0x0, "Raven T' Wax EISA BA"}, + {HPHW_BA, 0x01F, 0x00090, 0x0, "SkyHawk 100/120 Wax EISA BA"}, + {HPHW_BA, 0x027, 0x00090, 0x0, "Piranha 100 Wax EISA BA"}, + {HPHW_BA, 0x028, 0x00090, 0x0, "Mirage Jr Wax EISA BA"}, + {HPHW_BA, 0x029, 0x00090, 0x0, "Mirage Wax EISA BA"}, + {HPHW_BA, 0x02A, 0x00090, 0x0, "Electra Wax EISA BA"}, + {HPHW_BA, 0x02B, 0x00090, 0x0, "Mirage 80 Wax EISA BA"}, + {HPHW_BA, 0x02C, 0x00090, 0x0, "Mirage 100+ Wax EISA BA"}, + {HPHW_BA, 0x030, 0x00090, 0x0, "UL 350 Wax EISA BA"}, + {HPHW_BA, 0x031, 0x00090, 0x0, "UL 550 Wax EISA BA"}, + {HPHW_BA, 0x034, 0x00090, 0x0, "SAIC L-80 Wax EISA BA"}, + {HPHW_BA, 0x03A, 0x00090, 0x0, "Merlin+ Wax EISA BA"}, + {HPHW_BA, 0x040, 0x00090, 0x0, "Merlin 132 Wax EISA BA"}, + {HPHW_BA, 0x041, 0x00090, 0x0, "Merlin 160 Wax EISA BA"}, + {HPHW_BA, 0x043, 0x00090, 0x0, "Merlin 132/160 Wax EISA BA"}, + {HPHW_BA, 0x052, 0x00090, 0x0, "Raven Hi Power Backplane Wax EISA BA"}, + {HPHW_BA, 0x054, 0x00090, 0x0, "Raven Lo Power Backplane Wax EISA BA"}, + {HPHW_BA, 0x059, 0x00090, 0x0, "FireHawk 200 Wax EISA BA"}, + {HPHW_BA, 0x05A, 0x00090, 0x0, "Raven L2 Backplane Wax EISA BA"}, + {HPHW_BA, 0x05D, 0x00090, 0x0, "SummitHawk Wax EISA BA"}, + {HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"}, + {HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"}, + {HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"}, + {HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 64 TIMI BA"}, + {HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"}, + {HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"}, + {HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"}, + {HPHW_BA, 0x582, 0x000A5, 0x00, "Epic PCI Bridge"}, + {HPHW_BCPORT, 0x504, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"}, + {HPHW_BCPORT, 0x505, 0x00000, 0x00, "Phantom PseudoBC GSC+ Port"}, + {HPHW_BCPORT, 0x503, 0x0000C, 0x00, "Java BC GSC+ Port"}, + {HPHW_BCPORT, 0x57F, 0x0000C, 0x00, "Hitachi Ghostview GSC+ Port"}, + {HPHW_BCPORT, 0x501, 0x0000C, 0x00, "U2-IOA BC GSC+ Port"}, + {HPHW_BCPORT, 0x502, 0x0000C, 0x00, "Uturn-IOA BC GSC+ Port"}, + {HPHW_BCPORT, 0x780, 0x0000C, 0x00, "Astro BC Ropes Port"}, + {HPHW_BCPORT, 0x506, 0x0000C, 0x00, "NEC-IOS BC HSC Port"}, + {HPHW_BCPORT, 0x004, 0x0000C, 0x00, "Cheetah BC SMB Port"}, + {HPHW_BCPORT, 0x006, 0x0000C, 0x00, "Cheetah BC MID_BUS Port"}, + {HPHW_BCPORT, 0x005, 0x0000C, 0x00, "Condor BC MID_BUS Port"}, + {HPHW_BCPORT, 0x100, 0x0000C, 0x00, "Condor BC HP-PB Port"}, + {HPHW_BCPORT, 0x184, 0x0000C, 0x00, "Summit BC Port"}, + {HPHW_BCPORT, 0x101, 0x0000C, 0x00, "Summit BC HP-PB Port"}, + {HPHW_BCPORT, 0x102, 0x0000C, 0x00, "HP-PB Port (prefetch)"}, + {HPHW_BCPORT, 0x500, 0x0000C, 0x00, "Gecko BOA BC GSC+ Port"}, + {HPHW_BCPORT, 0x103, 0x0000C, 0x00, "Gecko BOA BC HP-PB Port"}, + {HPHW_BCPORT, 0x507, 0x0000C, 0x00, "Keyaki BC GSC+ Port"}, + {HPHW_BCPORT, 0x508, 0x0000C, 0x00, "Keyaki-DX BC GSC+ Port"}, + {HPHW_BCPORT, 0x584, 0x0000C, 0x10, "DEW BC Runway Port"}, + {HPHW_BCPORT, 0x800, 0x0000C, 0x10, "DEW BC Merced Port"}, + {HPHW_BCPORT, 0x801, 0x0000C, 0x10, "SMC Bus Interface Merced Bus0"}, + {HPHW_BCPORT, 0x802, 0x0000C, 0x10, "SMC Bus INterface Merced Bus1"}, + {HPHW_BCPORT, 0x803, 0x0000C, 0x10, "IKE I/O Bus Converter Merced Port"}, + {HPHW_BCPORT, 0x781, 0x0000C, 0x00, "IKE I/O Bus Converter Ropes Port"}, + {HPHW_BCPORT, 0x804, 0x0000C, 0x10, "REO I/O Bus Converter Merced Port"}, + {HPHW_BCPORT, 0x782, 0x0000C, 0x00, "REO I/O Bus Converter Ropes Port"}, + {HPHW_BRIDGE, 0x680, 0x0000A, 0x00, "Dino PCI Bridge"}, + {HPHW_BRIDGE, 0x682, 0x0000A, 0x00, "Cujo PCI Bridge"}, + {HPHW_BRIDGE, 0x782, 0x0000A, 0x00, "Elroy PCI Bridge"}, + {HPHW_BRIDGE, 0x583, 0x000A5, 0x00, "Saga PCI Bridge"}, + {HPHW_B_DMA, 0x004, 0x00018, 0x00, "Parallel I/O"}, + {HPHW_B_DMA, 0x004, 0x00019, 0x00, "Parallel RDB"}, + {HPHW_B_DMA, 0x004, 0x00020, 0x80, "MID_BUS PSI"}, + {HPHW_B_DMA, 0x004, 0x0002F, 0x80, "HP-PB Transit PSI (36960A)"}, + {HPHW_B_DMA, 0x008, 0x00051, 0x80, "HP-PB Transit 802.3"}, + {HPHW_B_DMA, 0x004, 0x00052, 0x80, "Miura LAN/Console (J2146A)"}, + {HPHW_B_DMA, 0x008, 0x00058, 0x80, "HP-PB Transit 802.4"}, + {HPHW_B_DMA, 0x005, 0x00060, 0x80, "KittyHawk CSY Core LAN/Console"}, + {HPHW_B_DMA, 0x014, 0x00060, 0x80, "Diablo LAN/Console"}, + {HPHW_B_DMA, 0x054, 0x00060, 0x80, "Countach LAN/Console"}, + {HPHW_B_DMA, 0x004, 0x00094, 0x80, "KittyHawk GSC+ Exerciser"}, + {HPHW_B_DMA, 0x004, 0x00100, 0x80, "HP-PB HF Interface"}, + {HPHW_B_DMA, 0x000, 0x00206, 0x80, "MELCO HMPHA"}, + {HPHW_B_DMA, 0x005, 0x00206, 0x80, "MELCO HMPHA_10"}, + {HPHW_B_DMA, 0x006, 0x00206, 0x80, "MELCO HMQHA"}, + {HPHW_B_DMA, 0x007, 0x00206, 0x80, "MELCO HMQHA_10"}, + {HPHW_B_DMA, 0x004, 0x207, 0x80, "MELCO HNDWA MDWS-70"}, + {HPHW_CIO, 0x004, 0x00010, 0x00, "VLSI CIO"}, + {HPHW_CIO, 0x005, 0x00010, 0x00, "Silverfox CIO"}, + {HPHW_CIO, 0x006, 0x00010, 0x00, "Emerald CIO"}, + {HPHW_CIO, 0x008, 0x00010, 0x00, "Discrete CIO"}, + {HPHW_CONSOLE, 0x004, 0x0001C, 0x00, "Cheetah console"}, + {HPHW_CONSOLE, 0x005, 0x0001C, 0x00, "Emerald console"}, + {HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"}, + {HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"}, + {HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"}, + {HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"}, + {HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"}, + {HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"}, + {HPHW_FIO, 0x004, 0x0004F, 0x0, "8-Port X.25 EISA-ACC (AMSO)"}, + {HPHW_FIO, 0x004, 0x00071, 0x0, "Cobra Core SCSI"}, + {HPHW_FIO, 0x005, 0x00071, 0x0, "Coral Core SCSI"}, + {HPHW_FIO, 0x006, 0x00071, 0x0, "Bushmaster Core SCSI"}, + {HPHW_FIO, 0x007, 0x00071, 0x0, "Scorpio Core SCSI"}, + {HPHW_FIO, 0x008, 0x00071, 0x0, "Flounder Core SCSI"}, + {HPHW_FIO, 0x009, 0x00071, 0x0, "Outfield Core SCSI"}, + {HPHW_FIO, 0x00A, 0x00071, 0x0, "CoralII Core SCSI"}, + {HPHW_FIO, 0x00B, 0x00071, 0x0, "Scorpio Jr. Core SCSI"}, + {HPHW_FIO, 0x00C, 0x00071, 0x0, "Strider-50 Core SCSI"}, + {HPHW_FIO, 0x00D, 0x00071, 0x0, "Strider-33 Core SCSI"}, + {HPHW_FIO, 0x00E, 0x00071, 0x0, "Trailways-50 Core SCSI"}, + {HPHW_FIO, 0x00F, 0x00071, 0x0, "Trailways-33 Core SCSI"}, + {HPHW_FIO, 0x010, 0x00071, 0x0, "Pace Core SCSI"}, + {HPHW_FIO, 0x011, 0x00071, 0x0, "Sidewinder Core SCSI"}, + {HPHW_FIO, 0x019, 0x00071, 0x0, "Scorpio Sr. Core SCSI"}, + {HPHW_FIO, 0x020, 0x00071, 0x0, "Scorpio 100 Core SCSI"}, + {HPHW_FIO, 0x021, 0x00071, 0x0, "Spectra 50 Core SCSI"}, + {HPHW_FIO, 0x022, 0x00071, 0x0, "Spectra 75 Core SCSI"}, + {HPHW_FIO, 0x023, 0x00071, 0x0, "Spectra 100 Core SCSI"}, + {HPHW_FIO, 0x024, 0x00071, 0x0, "Fast Pace Core SCSI"}, + {HPHW_FIO, 0x026, 0x00071, 0x0, "CoralII Jaguar Core SCSI"}, + {HPHW_FIO, 0x004, 0x00072, 0x0, "Cobra Core LAN (802.3)"}, + {HPHW_FIO, 0x005, 0x00072, 0x0, "Coral Core LAN (802.3)"}, + {HPHW_FIO, 0x006, 0x00072, 0x0, "Bushmaster Core LAN (802.3)"}, + {HPHW_FIO, 0x007, 0x00072, 0x0, "Scorpio Core LAN (802.3)"}, + {HPHW_FIO, 0x008, 0x00072, 0x0, "Flounder Core LAN (802.3)"}, + {HPHW_FIO, 0x009, 0x00072, 0x0, "Outfield Core LAN (802.3)"}, + {HPHW_FIO, 0x00A, 0x00072, 0x0, "CoralII Core LAN (802.3)"}, + {HPHW_FIO, 0x00B, 0x00072, 0x0, "Scorpio Jr. Core LAN (802.3)"}, + {HPHW_FIO, 0x00C, 0x00072, 0x0, "Strider-50 Core LAN (802.3)"}, + {HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"}, + {HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"}, + {HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"}, + {HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core Lan (802.3)"}, + {HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core Lan (802.3)"}, + {HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"}, + {HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"}, + {HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"}, + {HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"}, + {HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"}, + {HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core Lan (802.3)"}, + {HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"}, + {HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"}, + {HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"}, + {HPHW_FIO, 0x006, 0x00073, 0x0, "Bushmaster Core HIL"}, + {HPHW_FIO, 0x007, 0x00073, 0x0, "Scorpio Core HIL"}, + {HPHW_FIO, 0x008, 0x00073, 0x0, "Flounder Core HIL"}, + {HPHW_FIO, 0x009, 0x00073, 0x0, "Outfield Core HIL"}, + {HPHW_FIO, 0x00A, 0x00073, 0x0, "CoralII Core HIL"}, + {HPHW_FIO, 0x00B, 0x00073, 0x0, "Scorpio Jr. Core HIL"}, + {HPHW_FIO, 0x00C, 0x00073, 0x0, "Strider-50 Core HIL"}, + {HPHW_FIO, 0x00D, 0x00073, 0x0, "Strider-33 Core HIL"}, + {HPHW_FIO, 0x00E, 0x00073, 0x0, "Trailways-50 Core HIL"}, + {HPHW_FIO, 0x00F, 0x00073, 0x0, "Trailways-33 Core HIL"}, + {HPHW_FIO, 0x010, 0x00073, 0x0, "Pace Core HIL"}, + {HPHW_FIO, 0x011, 0x00073, 0xcc, "SuperPace Wax HIL"}, + {HPHW_FIO, 0x012, 0x00073, 0x0, "Mirage Jr Wax HIL"}, + {HPHW_FIO, 0x013, 0x00073, 0x0, "Mirage 100 Wax HIL"}, + {HPHW_FIO, 0x014, 0x00073, 0x0, "Electra Wax HIL"}, + {HPHW_FIO, 0x017, 0x00073, 0x0, "Raven Backplane Wax HIL"}, + {HPHW_FIO, 0x019, 0x00073, 0x0, "Scorpio Sr. Core HIL"}, + {HPHW_FIO, 0x01E, 0x00073, 0x0, "Raven T' Wax HIL"}, + {HPHW_FIO, 0x01F, 0x00073, 0x0, "SkyHawk 100/120 Wax HIL"}, + {HPHW_FIO, 0x020, 0x00073, 0x0, "Scorpio 100 Core HIL"}, + {HPHW_FIO, 0x021, 0x00073, 0x0, "Spectra 50 Core HIL"}, + {HPHW_FIO, 0x022, 0x00073, 0x0, "Spectra 75 Core HIL"}, + {HPHW_FIO, 0x023, 0x00073, 0x0, "Spectra 100 Core HIL"}, + {HPHW_FIO, 0x024, 0x00073, 0x0, "Fast Pace Core HIL"}, + {HPHW_FIO, 0x026, 0x00073, 0x0, "CoralII Jaguar Core HIL"}, + {HPHW_FIO, 0x02B, 0x00073, 0x0, "Mirage 80 Wax HIL"}, + {HPHW_FIO, 0x02C, 0x00073, 0x0, "Mirage 100+ Wax HIL"}, + {HPHW_FIO, 0x03A, 0x00073, 0x0, "Merlin+ Wax HIL"}, + {HPHW_FIO, 0x040, 0x00073, 0x0, "Merlin 132 Wax HIL"}, + {HPHW_FIO, 0x041, 0x00073, 0x0, "Merlin 160 Wax HIL"}, + {HPHW_FIO, 0x043, 0x00073, 0x0, "Merlin 132/160 Wax HIL"}, + {HPHW_FIO, 0x052, 0x00073, 0x0, "Raven+ Hi Power Backplane w/EISA Wax HIL"}, + {HPHW_FIO, 0x053, 0x00073, 0x0, "Raven+ Hi Power Backplane wo/EISA Wax HIL"}, + {HPHW_FIO, 0x054, 0x00073, 0x0, "Raven+ Lo Power Backplane w/EISA Wax HIL"}, + {HPHW_FIO, 0x055, 0x00073, 0x0, "Raven+ Lo Power Backplane wo/EISA Wax HIL"}, + {HPHW_FIO, 0x059, 0x00073, 0x0, "FireHawk 200 Wax HIL"}, + {HPHW_FIO, 0x05A, 0x00073, 0x0, "Raven+ L2 Backplane w/EISA Wax HIL"}, + {HPHW_FIO, 0x05B, 0x00073, 0x0, "Raven+ L2 Backplane wo/EISA Wax HIL"}, + {HPHW_FIO, 0x05D, 0x00073, 0x0, "SummitHawk Wax HIL"}, + {HPHW_FIO, 0x800, 0x00073, 0x0, "Hitachi Tiny 64 Wax HIL"}, + {HPHW_FIO, 0x801, 0x00073, 0x0, "Hitachi Tiny 80 Wax HIL"}, + {HPHW_FIO, 0x004, 0x00074, 0x0, "Cobra Core Centronics"}, + {HPHW_FIO, 0x005, 0x00074, 0x0, "Coral Core Centronics"}, + {HPHW_FIO, 0x006, 0x00074, 0x0, "Bushmaster Core Centronics"}, + {HPHW_FIO, 0x007, 0x00074, 0x0, "Scorpio Core Centronics"}, + {HPHW_FIO, 0x008, 0x00074, 0x0, "Flounder Core Centronics"}, + {HPHW_FIO, 0x009, 0x00074, 0x0, "Outfield Core Centronics"}, + {HPHW_FIO, 0x00A, 0x00074, 0x0, "CoralII Core Centronics"}, + {HPHW_FIO, 0x00B, 0x00074, 0x0, "Scorpio Jr. Core Centronics"}, + {HPHW_FIO, 0x00C, 0x00074, 0x0, "Strider-50 Core Centronics"}, + {HPHW_FIO, 0x00D, 0x00074, 0x0, "Strider-33 Core Centronics"}, + {HPHW_FIO, 0x00E, 0x00074, 0x0, "Trailways-50 Core Centronics"}, + {HPHW_FIO, 0x00F, 0x00074, 0x0, "Trailways-33 Core Centronics"}, + {HPHW_FIO, 0x010, 0x00074, 0x0, "Pace Core Centronics"}, + {HPHW_FIO, 0x011, 0x00074, 0x0, "Sidewinder Core Centronics"}, + {HPHW_FIO, 0x015, 0x00074, 0x0, "KittyHawk GSY Core Centronics"}, + {HPHW_FIO, 0x016, 0x00074, 0x0, "Gecko Core Centronics"}, + {HPHW_FIO, 0x019, 0x00074, 0x0, "Scorpio Sr. Core Centronics"}, + {HPHW_FIO, 0x01A, 0x00074, 0x0, "Anole 64 Core Centronics"}, + {HPHW_FIO, 0x01B, 0x00074, 0x0, "Anole 100 Core Centronics"}, + {HPHW_FIO, 0x01C, 0x00074, 0x0, "Gecko 80 Core Centronics"}, + {HPHW_FIO, 0x01D, 0x00074, 0x0, "Gecko 100 Core Centronics"}, + {HPHW_FIO, 0x01F, 0x00074, 0x0, "SkyHawk 100/120 Core Centronics"}, + {HPHW_FIO, 0x020, 0x00074, 0x0, "Scorpio 100 Core Centronics"}, + {HPHW_FIO, 0x021, 0x00074, 0x0, "Spectra 50 Core Centronics"}, + {HPHW_FIO, 0x022, 0x00074, 0x0, "Spectra 75 Core Centronics"}, + {HPHW_FIO, 0x023, 0x00074, 0x0, "Spectra 100 Core Centronics"}, + {HPHW_FIO, 0x024, 0x00074, 0x0, "Fast Pace Core Centronics"}, + {HPHW_FIO, 0x026, 0x00074, 0x0, "CoralII Jaguar Core Centronics"}, + {HPHW_FIO, 0x027, 0x00074, 0x0, "Piranha 100 Core Centronics"}, + {HPHW_FIO, 0x028, 0x00074, 0x0, "Mirage Jr Core Centronics"}, + {HPHW_FIO, 0x029, 0x00074, 0x0, "Mirage Core Centronics"}, + {HPHW_FIO, 0x02A, 0x00074, 0x0, "Electra Core Centronics"}, + {HPHW_FIO, 0x02B, 0x00074, 0x0, "Mirage 80 Core Centronics"}, + {HPHW_FIO, 0x02C, 0x00074, 0x0, "Mirage 100+ Core Centronics"}, + {HPHW_FIO, 0x02E, 0x00074, 0x0, "UL 350 Core Centronics"}, + {HPHW_FIO, 0x02F, 0x00074, 0x0, "UL 550 Core Centronics"}, + {HPHW_FIO, 0x032, 0x00074, 0x0, "Raven T' Core Centronics"}, + {HPHW_FIO, 0x033, 0x00074, 0x0, "Anole T Core Centronics"}, + {HPHW_FIO, 0x034, 0x00074, 0x0, "SAIC L-80 Core Centronics"}, + {HPHW_FIO, 0x035, 0x00074, 0x0, "PCX-L2 712/132 Core Centronics"}, + {HPHW_FIO, 0x036, 0x00074, 0x0, "PCX-L2 712/160 Core Centronics"}, + {HPHW_FIO, 0x03B, 0x00074, 0x0, "Raven U/L2 Core Centronics"}, + {HPHW_FIO, 0x03C, 0x00074, 0x0, "Merlin 132 Core Centronics"}, + {HPHW_FIO, 0x03D, 0x00074, 0x0, "Merlin 160 Core Centronics"}, + {HPHW_FIO, 0x03E, 0x00074, 0x0, "Merlin+ 132 Core Centronics"}, + {HPHW_FIO, 0x03F, 0x00074, 0x0, "Merlin+ 180 Core Centronics"}, + {HPHW_FIO, 0x044, 0x00074, 0x0, "Mohawk Core Centronics"}, + {HPHW_FIO, 0x045, 0x00074, 0x0, "Rocky1 Core Centronics"}, + {HPHW_FIO, 0x046, 0x00074, 0x0, "Rocky2 120 Core Centronics"}, + {HPHW_FIO, 0x047, 0x00074, 0x0, "Rocky2 150 Core Centronics"}, + {HPHW_FIO, 0x04B, 0x00074, 0x0, "Anole L2 132 Core Centronics"}, + {HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"}, + {HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"}, + {HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"}, + {HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ wSE FWSCSI Core Centronics"}, + {HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ wDiff FWSCSI Core Centronics"}, + {HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"}, + {HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"}, + {HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"}, + {HPHW_FIO, 0x801, 0x00074, 0x0, "Hitachi Tiny 80 Core Centronics"}, + {HPHW_FIO, 0x004, 0x00075, 0x0, "Cobra Core RS-232"}, + {HPHW_FIO, 0x005, 0x00075, 0x0, "Coral Core RS-232"}, + {HPHW_FIO, 0x006, 0x00075, 0x0, "Bushmaster Core RS-232"}, + {HPHW_FIO, 0x007, 0x00075, 0x0, "Scorpio Core RS-232"}, + {HPHW_FIO, 0x008, 0x00075, 0x0, "Flounder Core RS-232"}, + {HPHW_FIO, 0x009, 0x00075, 0x0, "Outfield Core RS-232"}, + {HPHW_FIO, 0x00A, 0x00075, 0x0, "CoralII Core RS-232"}, + {HPHW_FIO, 0x00B, 0x00075, 0x0, "Scorpio Jr. Core RS-232"}, + {HPHW_FIO, 0x00C, 0x00075, 0x0, "Strider-50 Core RS-232"}, + {HPHW_FIO, 0x00D, 0x00075, 0x0, "Strider-33 Core RS-232"}, + {HPHW_FIO, 0x00E, 0x00075, 0x0, "Trailways-50 Core RS-232"}, + {HPHW_FIO, 0x00F, 0x00075, 0x0, "Trailways-33 Core RS-232"}, + {HPHW_FIO, 0x010, 0x00075, 0x0, "Pace Core RS-232"}, + {HPHW_FIO, 0x011, 0x00075, 0x0, "Sidewinder Core RS-232"}, + {HPHW_FIO, 0x019, 0x00075, 0x0, "Scorpio Sr. Core RS-232"}, + {HPHW_FIO, 0x020, 0x00075, 0x0, "Scorpio 100 Core RS-232"}, + {HPHW_FIO, 0x021, 0x00075, 0x0, "Spectra 50 Core RS-232"}, + {HPHW_FIO, 0x022, 0x00075, 0x0, "Spectra 75 Core RS-232"}, + {HPHW_FIO, 0x023, 0x00075, 0x0, "Spectra 100 Core RS-232"}, + {HPHW_FIO, 0x024, 0x00075, 0x0, "Fast Pace Core RS-232"}, + {HPHW_FIO, 0x026, 0x00075, 0x0, "CoralII Jaguar Core RS-232"}, + {HPHW_FIO, 0x004, 0x00077, 0x0, "Coral SGC Graphics"}, + {HPHW_FIO, 0x005, 0x00077, 0x0, "Hyperdrive Optional Graphics"}, + {HPHW_FIO, 0x006, 0x00077, 0x0, "Stinger Optional Graphics"}, + {HPHW_FIO, 0x007, 0x00077, 0x0, "Scorpio Builtin Graphics"}, + {HPHW_FIO, 0x008, 0x00077, 0x0, "Anole Hyperdrive Optional Graphics"}, + {HPHW_FIO, 0x009, 0x00077, 0x0, "Thunder II graphics EISA form"}, + {HPHW_FIO, 0x00A, 0x00077, 0x0, "Thunder II graphics GSA form"}, + {HPHW_FIO, 0x00B, 0x00077, 0x0, "Scorpio Jr Builtin Graphics"}, + {HPHW_FIO, 0x00C, 0x00077, 0x0, "Strider-50 SSC Graphics"}, + {HPHW_FIO, 0x00D, 0x00077, 0x0, "Strider-33 SSC Graphics"}, + {HPHW_FIO, 0x00E, 0x00077, 0x0, "Trailways-50 SSC Graphics"}, + {HPHW_FIO, 0x00F, 0x00077, 0x0, "Trailways-33 SSC Graphics"}, + {HPHW_FIO, 0x010, 0x00077, 0x0, "Pace SGC Graphics"}, + {HPHW_FIO, 0x011, 0x00077, 0x0, "Mohawk Opt. 2D Graphics (Kid)"}, + {HPHW_FIO, 0x012, 0x00077, 0x0, "Raven Opt. 2D Graphics (Goat)"}, + {HPHW_FIO, 0x016, 0x00077, 0x0, "Lego 24 SCG Graphics"}, + {HPHW_FIO, 0x017, 0x00077, 0x0, "Lego 24Z SCG Graphics"}, + {HPHW_FIO, 0x018, 0x00077, 0x0, "Lego 48Z SCG Graphics"}, + {HPHW_FIO, 0x019, 0x00077, 0x0, "Scorpio Sr Builtin Graphics"}, + {HPHW_FIO, 0x020, 0x00077, 0x0, "Scorpio 100 Builtin Graphics"}, + {HPHW_FIO, 0x021, 0x00077, 0x0, "Spectra 50 Builtin Graphics"}, + {HPHW_FIO, 0x022, 0x00077, 0x0, "Spectra 75 Builtin Graphics"}, + {HPHW_FIO, 0x023, 0x00077, 0x0, "Spectra 100 Builtin Graphics"}, + {HPHW_FIO, 0x024, 0x00077, 0x0, "Fast Pace SGC Graphics"}, + {HPHW_FIO, 0x006, 0x0007A, 0x0, "Bushmaster Audio"}, + {HPHW_FIO, 0x008, 0x0007A, 0x0, "Flounder Audio"}, + {HPHW_FIO, 0x004, 0x0007B, 0x0, "UL Optional Audio"}, + {HPHW_FIO, 0x007, 0x0007B, 0x0, "Scorpio Audio"}, + {HPHW_FIO, 0x00B, 0x0007B, 0x0, "Scorpio Jr. Audio"}, + {HPHW_FIO, 0x00C, 0x0007B, 0x0, "Strider-50 Audio"}, + {HPHW_FIO, 0x00D, 0x0007B, 0x0, "Strider-33 Audio"}, + {HPHW_FIO, 0x00E, 0x0007B, 0x0, "Trailways-50 Audio"}, + {HPHW_FIO, 0x00F, 0x0007B, 0x0, "Trailways-33 Audio"}, + {HPHW_FIO, 0x016, 0x0007B, 0x0, "Gecko Audio"}, + {HPHW_FIO, 0x019, 0x0007B, 0x0, "Scorpio Sr. Audio"}, + {HPHW_FIO, 0x01A, 0x0007B, 0x0, "Anole 64 Audio"}, + {HPHW_FIO, 0x01B, 0x0007B, 0x0, "Anole 100 Audio"}, + {HPHW_FIO, 0x01C, 0x0007B, 0x0, "Gecko 80 Audio"}, + {HPHW_FIO, 0x01D, 0x0007B, 0x0, "Gecko 100 Audio"}, + {HPHW_FIO, 0x01F, 0x0007B, 0x0, "SkyHawk 100/120 Audio"}, + {HPHW_FIO, 0x020, 0x0007B, 0x0, "Scorpio 100 Audio"}, + {HPHW_FIO, 0x021, 0x0007B, 0x0, "Spectra 50 Audio"}, + {HPHW_FIO, 0x022, 0x0007B, 0x0, "Spectra 75 Audio"}, + {HPHW_FIO, 0x023, 0x0007B, 0x0, "Spectra 100 Audio"}, + {HPHW_FIO, 0x028, 0x0007B, 0x0, "Mirage Jr Audio"}, + {HPHW_FIO, 0x029, 0x0007B, 0x0, "Mirage Audio"}, + {HPHW_FIO, 0x02A, 0x0007B, 0x0, "Electra Audio"}, + {HPHW_FIO, 0x02B, 0x0007B, 0x0, "Mirage 80 Audio"}, + {HPHW_FIO, 0x02C, 0x0007B, 0x0, "Mirage 100+ Audio"}, + {HPHW_FIO, 0x032, 0x0007B, 0x0, "Raven T' Audio"}, + {HPHW_FIO, 0x034, 0x0007B, 0x0, "SAIC L-80 Audio"}, + {HPHW_FIO, 0x035, 0x0007B, 0x0, "PCX-L2 712/132 Core Audio"}, + {HPHW_FIO, 0x036, 0x0007B, 0x0, "PCX-L2 712/160 Core Audio"}, + {HPHW_FIO, 0x03B, 0x0007B, 0x0, "Raven U/L2 Core Audio"}, + {HPHW_FIO, 0x03C, 0x0007B, 0x0, "Merlin 132 Core Audio"}, + {HPHW_FIO, 0x03D, 0x0007B, 0x0, "Merlin 160 Core Audio"}, + {HPHW_FIO, 0x03E, 0x0007B, 0x0, "Merlin+ 132 Core Audio"}, + {HPHW_FIO, 0x03F, 0x0007B, 0x0, "Merlin+ 180 Core Audio"}, + {HPHW_FIO, 0x044, 0x0007B, 0x0, "Mohawk Core Audio"}, + {HPHW_FIO, 0x046, 0x0007B, 0x0, "Rocky2 120 Core Audio"}, + {HPHW_FIO, 0x047, 0x0007B, 0x0, "Rocky2 150 Core Audio"}, + {HPHW_FIO, 0x04B, 0x0007B, 0x0, "Anole L2 132 Core Audio"}, + {HPHW_FIO, 0x04D, 0x0007B, 0x0, "Anole L2 165 Core Audio"}, + {HPHW_FIO, 0x04E, 0x0007B, 0x0, "Kiji L2 132 Core Audio"}, + {HPHW_FIO, 0x050, 0x0007B, 0x0, "Merlin Jr 132 Core Audio"}, + {HPHW_FIO, 0x051, 0x0007B, 0x0, "Firehawk Audio"}, + {HPHW_FIO, 0x056, 0x0007B, 0x0, "Raven+ w SE FWSCSU Core Audio"}, + {HPHW_FIO, 0x057, 0x0007B, 0x0, "Raven+ w Diff FWSCSU Core Audio"}, + {HPHW_FIO, 0x058, 0x0007B, 0x0, "FireHawk 200 Audio"}, + {HPHW_FIO, 0x05C, 0x0007B, 0x0, "SummitHawk 230 Core Audio"}, + {HPHW_FIO, 0x800, 0x0007B, 0x0, "Hitachi Tiny 64 Audio"}, + {HPHW_FIO, 0x801, 0x0007B, 0x0, "Hitachi Tiny 80 Audio"}, + {HPHW_FIO, 0x009, 0x0007C, 0x0, "Outfield FW SCSI"}, + {HPHW_FIO, 0x00A, 0x0007C, 0x0, "CoralII FW SCSI"}, + {HPHW_FIO, 0x026, 0x0007C, 0x0, "CoralII Jaguar FW SCSI"}, + {HPHW_FIO, 0x009, 0x0007D, 0x0, "Outfield FDDI"}, + {HPHW_FIO, 0x00A, 0x0007D, 0x0, "CoralII FDDI"}, + {HPHW_FIO, 0x026, 0x0007D, 0x0, "CoralII Jaguar FDDI"}, + {HPHW_FIO, 0x010, 0x0007E, 0x0, "Pace Audio"}, + {HPHW_FIO, 0x024, 0x0007E, 0x0, "Fast Pace Audio"}, + {HPHW_FIO, 0x009, 0x0007F, 0x0, "Outfield Audio"}, + {HPHW_FIO, 0x00A, 0x0007F, 0x0, "CoralII Audio"}, + {HPHW_FIO, 0x026, 0x0007F, 0x0, "CoralII Jaguar Audio"}, + {HPHW_FIO, 0x010, 0x00080, 0x0, "Pace Core HPIB"}, + {HPHW_FIO, 0x024, 0x00080, 0x0, "Fast Pace Core HPIB"}, + {HPHW_FIO, 0x016, 0x00082, 0x0, "Gecko Core SCSI"}, + {HPHW_FIO, 0x01A, 0x00082, 0x0, "Anole 64 Core SCSI"}, + {HPHW_FIO, 0x01B, 0x00082, 0x0, "Anole 100 Core SCSI"}, + {HPHW_FIO, 0x01C, 0x00082, 0x0, "Gecko 80 Core SCSI"}, + {HPHW_FIO, 0x01D, 0x00082, 0x0, "Gecko 100 Core SCSI"}, + {HPHW_FIO, 0x01F, 0x00082, 0x0, "SkyHawk 100/120 Core SCSI"}, + {HPHW_FIO, 0x027, 0x00082, 0x0, "Piranha 100 Core SCSI"}, + {HPHW_FIO, 0x028, 0x00082, 0x0, "Mirage Jr Core SCSI"}, + {HPHW_FIO, 0x029, 0x00082, 0x0, "Mirage Core SCSI"}, + {HPHW_FIO, 0x02A, 0x00082, 0x0, "Electra Core SCSI"}, + {HPHW_FIO, 0x02B, 0x00082, 0x0, "Mirage 80 Core SCSI"}, + {HPHW_FIO, 0x02C, 0x00082, 0x0, "Mirage 100+ Core SCSI"}, + {HPHW_FIO, 0x02E, 0x00082, 0x0, "UL 350 Core SCSI"}, + {HPHW_FIO, 0x02F, 0x00082, 0x0, "UL 550 Core SCSI"}, + {HPHW_FIO, 0x032, 0x00082, 0x0, "Raven T' Core SCSI"}, + {HPHW_FIO, 0x033, 0x00082, 0x0, "Anole T Core SCSI"}, + {HPHW_FIO, 0x034, 0x00082, 0x0, "SAIC L-80 Core SCSI"}, + {HPHW_FIO, 0x035, 0x00082, 0x0, "PCX-L2 712/132 Core SCSI"}, + {HPHW_FIO, 0x036, 0x00082, 0x0, "PCX-L2 712/160 Core SCSI"}, + {HPHW_FIO, 0x03B, 0x00082, 0x0, "Raven U/L2 Core SCSI"}, + {HPHW_FIO, 0x03C, 0x00082, 0x0, "Merlin 132 Core SCSI"}, + {HPHW_FIO, 0x03D, 0x00082, 0x0, "Merlin 160 Core SCSI"}, + {HPHW_FIO, 0x03E, 0x00082, 0x0, "Merlin+ 132 Core SCSI"}, + {HPHW_FIO, 0x03F, 0x00082, 0x0, "Merlin+ 180 Core SCSI"}, + {HPHW_FIO, 0x044, 0x00082, 0x0, "Mohawk Core SCSI"}, + {HPHW_FIO, 0x045, 0x00082, 0x0, "Rocky1 Core SCSI"}, + {HPHW_FIO, 0x046, 0x00082, 0x0, "Rocky2 120 Core SCSI"}, + {HPHW_FIO, 0x047, 0x00082, 0x0, "Rocky2 150 Core SCSI"}, + {HPHW_FIO, 0x04B, 0x00082, 0x0, "Anole L2 132 Core SCSI"}, + {HPHW_FIO, 0x04D, 0x00082, 0x0, "Anole L2 165 Core SCSI"}, + {HPHW_FIO, 0x04E, 0x00082, 0x0, "Kiji L2 132 Core SCSI"}, + {HPHW_FIO, 0x050, 0x00082, 0x0, "Merlin Jr 132 Core SCSI"}, + {HPHW_FIO, 0x051, 0x00082, 0x0, "Firehawk Core SCSI"}, + {HPHW_FIO, 0x056, 0x00082, 0x0, "Raven+ w SE FWSCSI Core SCSI"}, + {HPHW_FIO, 0x057, 0x00082, 0x0, "Raven+ w Diff FWSCSI Core SCSI"}, + {HPHW_FIO, 0x058, 0x00082, 0x0, "FireHawk 200 Core SCSI"}, + {HPHW_FIO, 0x05C, 0x00082, 0x0, "SummitHawk 230 Core SCSI"}, + {HPHW_FIO, 0x05E, 0x00082, 0x0, "Staccato 132 Core SCSI"}, + {HPHW_FIO, 0x05F, 0x00082, 0x0, "Staccato 180 Core SCSI"}, + {HPHW_FIO, 0x800, 0x00082, 0x0, "Hitachi Tiny 64 Core SCSI"}, + {HPHW_FIO, 0x801, 0x00082, 0x0, "Hitachi Tiny 80 Core SCSI"}, + {HPHW_FIO, 0x016, 0x00083, 0x0, "Gecko Core PC Floppy"}, + {HPHW_FIO, 0x01C, 0x00083, 0x0, "Gecko 80 Core PC Floppy"}, + {HPHW_FIO, 0x01D, 0x00083, 0x0, "Gecko 100 Core PC Floppy"}, + {HPHW_FIO, 0x051, 0x00083, 0x0, "Firehawk Core PC Floppy"}, + {HPHW_FIO, 0x058, 0x00083, 0x0, "FireHawk 200 Core PC Floppy"}, + {HPHW_FIO, 0x027, 0x00083, 0x0, "Piranha 100 Core PC Floppy"}, + {HPHW_FIO, 0x028, 0x00083, 0x0, "Mirage Jr Core PC Floppy"}, + {HPHW_FIO, 0x029, 0x00083, 0x0, "Mirage Core PC Floppy"}, + {HPHW_FIO, 0x02A, 0x00083, 0x0, "Electra Core PC Floppy"}, + {HPHW_FIO, 0x02B, 0x00083, 0x0, "Mirage 80 Core PC Floppy"}, + {HPHW_FIO, 0x02C, 0x00083, 0x0, "Mirage 100+ Core PC Floppy"}, + {HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"}, + {HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"}, + {HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"}, + {HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floopy"}, + {HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floopy"}, + {HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floopy"}, + {HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floopy"}, + {HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floopy"}, + {HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floopy"}, + {HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floopy"}, + {HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floopy"}, + {HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floopy"}, + {HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floopy"}, + {HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floopy"}, + {HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floopy"}, + {HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floopy"}, + {HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floopy"}, + {HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floopy"}, + {HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floopy"}, + {HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floopy"}, + {HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PC Keyboard"}, + {HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PC Keyboard"}, + {HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PC Keyboard"}, + {HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PC Keyboard"}, + {HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PC Keyboard"}, + {HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PC Keyboard"}, + {HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PC Keyboard"}, + {HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PC Keyboard"}, + {HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PC Keyboard"}, + {HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PC Keyboard"}, + {HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PC Keyboard"}, + {HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PC Keyboard"}, + {HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PC Keyboard"}, + {HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PC Keyboard"}, + {HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PC Keyboard"}, + {HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PC Keyboard"}, + {HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PC Keyboard"}, + {HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PC Keyboard"}, + {HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PC Keyboard"}, + {HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core Keyboard"}, + {HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core Keyboard"}, + {HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PC Keyboard"}, + {HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PC Keyboard"}, + {HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PC Keyboard"}, + {HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PC Keyboard"}, + {HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PC Keyboard"}, + {HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PC Keyboard"}, + {HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PC Keyboard"}, + {HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PC Keyboard"}, + {HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PC Keyboard"}, + {HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PC Keyboard"}, + {HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PC Keyboard"}, + {HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PC Keyboard"}, + {HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PC Keyboard"}, + {HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PC Keyboard"}, + {HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PC Keyboard"}, + {HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PC Keyboard"}, + {HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PC Keyboard"}, + {HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PC Keyboard"}, + {HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PC Keyboard"}, + {HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PC Keyboard"}, + {HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PC Keyboard"}, + {HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PC Keyboard"}, + {HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"}, + {HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"}, + {HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"}, + {HPHW_FIO, 0x010, 0x00085, 0x0, "Mirage 80 GSC Builtin Graphics"}, + {HPHW_FIO, 0x011, 0x00085, 0x0, "Mirage 100+ GSC Builtin Graphics"}, + {HPHW_FIO, 0x012, 0x00085, 0x0, "Mirage Jr GSC Builtin Graphics"}, + {HPHW_FIO, 0x013, 0x00085, 0x0, "Mirage GSC Builtin Graphics"}, + {HPHW_FIO, 0x014, 0x00085, 0x0, "Electra GSC Builtin Graphics"}, + {HPHW_FIO, 0x016, 0x00085, 0x0, "Gecko GSC Core Graphics"}, + {HPHW_FIO, 0x017, 0x00085, 0x0, "Gecko GSC Optional Graphics"}, + {HPHW_FIO, 0x01A, 0x00085, 0x0, "Anole 64 Artist Builtin Graphics"}, + {HPHW_FIO, 0x01B, 0x00085, 0x0, "Anole 100 Artist Builtin Graphics"}, + {HPHW_FIO, 0x01C, 0x00085, 0x0, "Gecko 80 GSC Core Graphics"}, + {HPHW_FIO, 0x01D, 0x00085, 0x0, "Gecko 100 GSC Core Graphics"}, + {HPHW_FIO, 0x032, 0x00085, 0x0, "Raven T' GSC Core Graphics"}, + {HPHW_FIO, 0x033, 0x00085, 0x0, "Anole T Artist Builtin Graphics"}, + {HPHW_FIO, 0x034, 0x00085, 0x0, "SAIC L-80 GSC Core Graphics"}, + {HPHW_FIO, 0x035, 0x00085, 0x0, "PCX-L2 712/132 Core Graphics"}, + {HPHW_FIO, 0x036, 0x00085, 0x0, "PCX-L2 712/160 Core Graphics"}, + {HPHW_FIO, 0x03B, 0x00085, 0x0, "Raven U/L2 Core Graphics"}, + {HPHW_FIO, 0x03C, 0x00085, 0x0, "Merlin 132 Core Graphics"}, + {HPHW_FIO, 0x03D, 0x00085, 0x0, "Merlin 160 Core Graphics"}, + {HPHW_FIO, 0x03E, 0x00085, 0x0, "Merlin+ 132 Core Graphics"}, + {HPHW_FIO, 0x03F, 0x00085, 0x0, "Merlin+ 180 Core Graphics"}, + {HPHW_FIO, 0x045, 0x00085, 0x0, "Rocky1 Core Graphics"}, + {HPHW_FIO, 0x046, 0x00085, 0x0, "Rocky2 120 Core Graphics"}, + {HPHW_FIO, 0x047, 0x00085, 0x0, "Rocky2 150 Core Graphics"}, + {HPHW_FIO, 0x04B, 0x00085, 0x0, "Anole L2 132 Core Graphics"}, + {HPHW_FIO, 0x04D, 0x00085, 0x0, "Anole L2 165 Core Graphics"}, + {HPHW_FIO, 0x04E, 0x00085, 0x0, "Kiji L2 132 Core Graphics"}, + {HPHW_FIO, 0x050, 0x00085, 0x0, "Merlin Jr 132 Core Graphics"}, + {HPHW_FIO, 0x056, 0x00085, 0x0, "Raven+ w SE FWSCSI Core Graphics"}, + {HPHW_FIO, 0x057, 0x00085, 0x0, "Raven+ w Diff FWSCSI Core Graphics"}, + {HPHW_FIO, 0x800, 0x00085, 0x0, "Hitachi Tiny 64 Core Graphics"}, + {HPHW_FIO, 0x801, 0x00085, 0x0, "Hitachi Tiny 80 Core Graphics"}, + {HPHW_FIO, 0x004, 0x00086, 0x0, "GSC IBM Token Ring"}, + {HPHW_FIO, 0x015, 0x00087, 0x0, "Gecko Optional ISDN"}, + {HPHW_FIO, 0x016, 0x00087, 0x0, "Gecko Core ISDN"}, + {HPHW_FIO, 0x01C, 0x00087, 0x0, "Gecko 80 Core ISDN"}, + {HPHW_FIO, 0x01D, 0x00087, 0x0, "Gecko 100 Core ISDN"}, + {HPHW_FIO, 0x010, 0x00088, 0x0, "Pace VME Networking"}, + {HPHW_FIO, 0x011, 0x00088, 0x0, "Sidewinder VME Networking"}, + {HPHW_FIO, 0x01A, 0x00088, 0x0, "Anole 64 VME Networking"}, + {HPHW_FIO, 0x01B, 0x00088, 0x0, "Anole 100 VME Networking"}, + {HPHW_FIO, 0x024, 0x00088, 0x0, "Fast Pace VME Networking"}, + {HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"}, + {HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"}, + {HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"}, + {HPHW_FIO, 0x03B, 0x00089, 0x0, "Raven U/L2 Core FW-SCSI"}, + {HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core Lan (802.3)"}, + {HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core Lan (802.3)"}, + {HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core Lan (802.3)"}, + {HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core Lan (802.3)"}, + {HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core Lan (802.3)"}, + {HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core Lan (802.3)"}, + {HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional Lan (802.3)"}, + {HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core Lan (802.3)"}, + {HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core Lan (802.3)"}, + {HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core Lan (802.3)"}, + {HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core Lan (802.3)"}, + {HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"}, + {HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"}, + {HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"}, + {HPHW_FIO, 0x029, 0x0008A, 0x0, "Mirage Core LAN (802.3)"}, + {HPHW_FIO, 0x02A, 0x0008A, 0x0, "Electra Core LAN (802.3)"}, + {HPHW_FIO, 0x02B, 0x0008A, 0x0, "Mirage 80 Core LAN (802.3)"}, + {HPHW_FIO, 0x02C, 0x0008A, 0x0, "Mirage 100+ Core LAN (802.3)"}, + {HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, + {HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, + {HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"}, + {HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core Lan (802.3)"}, + {HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core Lan (802.3)"}, + {HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core Lan (802.3)"}, + {HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core Lan (802.3)"}, + {HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core Lan (802.3)"}, + {HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core Lan (802.3)"}, + {HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core Lan (802.3)"}, + {HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core Lan (802.3)"}, + {HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"}, + {HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"}, + {HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"}, + {HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"}, + {HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"}, + {HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"}, + {HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core Lan (802.3)"}, + {HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"}, + {HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core Lan (802.3)"}, + {HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core Lan (802.3)"}, + {HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"}, + {HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"}, + {HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"}, + {HPHW_FIO, 0x007, 0x0008C, 0x0, "Dino RS-232"}, + {HPHW_FIO, 0x008, 0x0008C, 0x0, "Merlin 132 Dino RS-232"}, + {HPHW_FIO, 0x009, 0x0008C, 0x0, "Merlin 160 Dino RS-232"}, + {HPHW_FIO, 0x00A, 0x0008C, 0x0, "Merlin Jr 132 Dino RS-232"}, + {HPHW_FIO, 0x010, 0x0008C, 0x0, "Mirage 80 Wax RS-232"}, + {HPHW_FIO, 0x011, 0x0008C, 0x0, "Mirage 100+ Wax RS-232"}, + {HPHW_FIO, 0x012, 0x0008C, 0x0, "Mirage Jr Wax RS-232"}, + {HPHW_FIO, 0x013, 0x0008C, 0x0, "Mirage Wax RS-232"}, + {HPHW_FIO, 0x014, 0x0008C, 0x0, "Electra Wax RS-232"}, + {HPHW_FIO, 0x015, 0x0008C, 0x0, "KittyHawk GSY Core RS-232"}, + {HPHW_FIO, 0x016, 0x0008C, 0x0, "Gecko Core RS-232"}, + {HPHW_FIO, 0x017, 0x0008C, 0x0, "Raven Backplane RS-232"}, + {HPHW_FIO, 0x018, 0x0008C, 0x0, "Gecko Optional RS-232"}, + {HPHW_FIO, 0x019, 0x0008C, 0x0, "Merlin+ 180 Dino RS-232"}, + {HPHW_FIO, 0x01A, 0x0008C, 0x0, "Anole 64 Core RS-232"}, + {HPHW_FIO, 0x01B, 0x0008C, 0x0, "Anole 100 Core RS-232"}, + {HPHW_FIO, 0x01C, 0x0008C, 0x0, "Gecko 80 Core RS-232"}, + {HPHW_FIO, 0x01D, 0x0008C, 0x0, "Gecko 100 Core RS-232"}, + {HPHW_FIO, 0x01E, 0x0008C, 0x0, "Raven T' Wax RS-232"}, + {HPHW_FIO, 0x01F, 0x0008C, 0x0, "SkyHawk 100/120 Core RS-232"}, + {HPHW_FIO, 0x020, 0x0008C, 0x0, "Anole 64 Timi RS-232"}, + {HPHW_FIO, 0x021, 0x0008C, 0x0, "Anole 100 Timi RS-232"}, + {HPHW_FIO, 0x022, 0x0008C, 0x0, "Merlin+ 132 Dino RS-232"}, + {HPHW_FIO, 0x023, 0x0008C, 0x0, "Rocky1 Wax RS-232"}, + {HPHW_FIO, 0x025, 0x0008C, 0x0, "Armyknife Optional RS-232"}, + {HPHW_FIO, 0x026, 0x0008C, 0x0, "Piranha 100 Wax RS-232"}, + {HPHW_FIO, 0x027, 0x0008C, 0x0, "Piranha 100 Core RS-232"}, + {HPHW_FIO, 0x028, 0x0008C, 0x0, "Mirage Jr Core RS-232"}, + {HPHW_FIO, 0x029, 0x0008C, 0x0, "Mirage Core RS-232"}, + {HPHW_FIO, 0x02A, 0x0008C, 0x0, "Electra Core RS-232"}, + {HPHW_FIO, 0x02B, 0x0008C, 0x0, "Mirage 80 Core RS-232"}, + {HPHW_FIO, 0x02C, 0x0008C, 0x0, "Mirage 100+ Core RS-232"}, + {HPHW_FIO, 0x02E, 0x0008C, 0x0, "UL 350 Lasi Core RS-232"}, + {HPHW_FIO, 0x02F, 0x0008C, 0x0, "UL 550 Lasi Core RS-232"}, + {HPHW_FIO, 0x030, 0x0008C, 0x0, "UL 350 Wax Core RS-232"}, + {HPHW_FIO, 0x031, 0x0008C, 0x0, "UL 550 Wax Core RS-232"}, + {HPHW_FIO, 0x032, 0x0008C, 0x0, "Raven T' Lasi Core RS-232"}, + {HPHW_FIO, 0x033, 0x0008C, 0x0, "Anole T Core RS-232"}, + {HPHW_FIO, 0x034, 0x0008C, 0x0, "SAIC L-80 Core RS-232"}, + {HPHW_FIO, 0x035, 0x0008C, 0x0, "PCX-L2 712/132 Core RS-232"}, + {HPHW_FIO, 0x036, 0x0008C, 0x0, "PCX-L2 712/160 Core RS-232"}, + {HPHW_FIO, 0x03A, 0x0008C, 0x0, "Merlin+ Wax RS-232"}, + {HPHW_FIO, 0x03B, 0x0008C, 0x0, "Raven U/L2 Core RS-232"}, + {HPHW_FIO, 0x03C, 0x0008C, 0x0, "Merlin 132 Core RS-232"}, + {HPHW_FIO, 0x03D, 0x0008C, 0x0, "Merlin 160 Core RS-232"}, + {HPHW_FIO, 0x03E, 0x0008C, 0x0, "Merlin+ 132 Core RS-232"}, + {HPHW_FIO, 0x03F, 0x0008C, 0x0, "Merlin+ 180 Core RS-232"}, + {HPHW_FIO, 0x040, 0x0008C, 0x0, "Merlin 132 Wax RS-232"}, + {HPHW_FIO, 0x041, 0x0008C, 0x0, "Merlin 160 Wax RS-232"}, + {HPHW_FIO, 0x043, 0x0008C, 0x0, "Merlin 132/160 Wax RS-232"}, + {HPHW_FIO, 0x044, 0x0008C, 0x0, "Mohawk Core RS-232"}, + {HPHW_FIO, 0x045, 0x0008C, 0x0, "Rocky1 Core RS-232"}, + {HPHW_FIO, 0x046, 0x0008C, 0x0, "Rocky2 120 Core RS-232"}, + {HPHW_FIO, 0x047, 0x0008C, 0x0, "Rocky2 150 Core RS-232"}, + {HPHW_FIO, 0x048, 0x0008C, 0x0, "Rocky2 120 Dino RS-232"}, + {HPHW_FIO, 0x049, 0x0008C, 0x0, "Rocky2 150 Dino RS-232"}, + {HPHW_FIO, 0x04A, 0x0008C, 0x0, "Anole L2 132 TIMI RS-232"}, + {HPHW_FIO, 0x04B, 0x0008C, 0x0, "Anole L2 l32 Core RS-232"}, + {HPHW_FIO, 0x04C, 0x0008D, 0x0, "Anole L2 165 TIMI RS-232"}, + {HPHW_FIO, 0x04D, 0x0008C, 0x0, "Anole L2 165 Core RS-232"}, + {HPHW_FIO, 0x04E, 0x0008C, 0x0, "Kiji L2 132 Core RS-232"}, + {HPHW_FIO, 0x04F, 0x0008C, 0x0, "Kiji L2 132 Dino RS-232"}, + {HPHW_FIO, 0x050, 0x0008C, 0x0, "Merlin Jr 132 Core RS-232"}, + {HPHW_FIO, 0x051, 0x0008C, 0x0, "Firehawk Core RS-232"}, + {HPHW_FIO, 0x052, 0x0008C, 0x0, "Raven+ Hi Power Backplane w EISA RS-232"}, + {HPHW_FIO, 0x053, 0x0008C, 0x0, "Raven+ Hi Power Backplane w/o EISA RS-232"}, + {HPHW_FIO, 0x054, 0x0008C, 0x0, "Raven+ Lo Power Backplane w EISA RS-232"}, + {HPHW_FIO, 0x055, 0x0008C, 0x0, "Raven+ Lo Power Backplane w/o EISA RS-232"}, + {HPHW_FIO, 0x056, 0x0008C, 0x0, "Raven+ w SE FWSCSI Core RS-232"}, + {HPHW_FIO, 0x057, 0x0008C, 0x0, "Raven+ w Diff FWSCSI Core RS-232"}, + {HPHW_FIO, 0x058, 0x0008C, 0x0, "FireHawk 200 Core RS-232"}, + {HPHW_FIO, 0x059, 0x0008C, 0x0, "FireHawk 200 Wax RS-232"}, + {HPHW_FIO, 0x05A, 0x0008C, 0x0, "Raven+ L2 Backplane w EISA RS-232"}, + {HPHW_FIO, 0x05B, 0x0008C, 0x0, "Raven+ L2 Backplane w/o EISA RS-232"}, + {HPHW_FIO, 0x05D, 0x0008C, 0x0, "SummitHawk Dino RS-232"}, + {HPHW_FIO, 0x05E, 0x0008C, 0x0, "Staccato 132 Core LAN RS-232"}, + {HPHW_FIO, 0x05F, 0x0008C, 0x0, "Staccato 180 Core LAN RS-232"}, + {HPHW_FIO, 0x800, 0x0008C, 0x0, "Hitachi Tiny 64 Core RS-232"}, + {HPHW_FIO, 0x801, 0x0008C, 0x0, "Hitachi Tiny 80 Core RS-232"}, + {HPHW_FIO, 0x015, 0x0008D, 0x0, "Gecko Optional RJ-16"}, + {HPHW_FIO, 0x016, 0x0008D, 0x0, "Gecko Core RJ-16"}, + {HPHW_FIO, 0x01C, 0x0008D, 0x0, "Gecko 80 Core RJ-16"}, + {HPHW_FIO, 0x01D, 0x0008D, 0x0, "Gecko 100 Core RJ-16"}, + {HPHW_FIO, 0x004, 0x0008F, 0x0, "Anole Boot Rom"}, + {HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"}, + {HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"}, + {HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"}, + {HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS2 Keyboard"}, + {HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS2 Keyboard"}, + {HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS2 Keyboard"}, + {HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS2 Keyboard"}, + {HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS2 Keyboard"}, + {HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS2 Keyboard"}, + {HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS2 Keyboard"}, + {HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG lan"}, + {HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"}, + {HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"}, + {HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"}, + {HPHW_FIO, 0x004, 0x000A1, 0x0, "SPP2000 Console TTY"}, + {HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"}, + {HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"}, + {HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"}, + {HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in Lan"}, + {HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT Lan"}, + {HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI Lan"}, + {HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI Lan"}, + {HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI Lan"}, + {HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI Lan"}, + {HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI Lan"}, + {HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI Lan"}, + {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"}, + {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"}, + {HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"}, + {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI LVD Ultra2 SCSI"}, + {HPHW_FIO, 0x005, 0x000A3, 0x0, "AllegroLow Core PCI IDE/ATAPI CD-ROM"}, + {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI LVD Ultra2 SCSI"}, + {HPHW_FIO, 0x006, 0x000A3, 0x0, "AllegroHigh Core PCI IDE/ATAPI CD-ROM"}, + {HPHW_FIO, 0x007, 0x000A3, 0x0, "PCI Plug-in Disk"}, + {HPHW_FIO, 0x008, 0x000A3, 0x0, "A5158A S FC Tachlite HBA"}, + {HPHW_FIO, 0x009, 0x000A3, 0x0, "A5157A D FC HBA"}, + {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI LVD Ultra2 SCSI"}, + {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI NSE UltraSCSI"}, + {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI WSE UltraSCSI"}, + {HPHW_FIO, 0x00A, 0x000A3, 0x0, "Lego 360 Core PCI IDE/ATAPI CD-ROM"}, + {HPHW_FIO, 0x03E, 0x000A3, 0x0, "Merlin+ 132 Core SE FWSCSI PCI Disk"}, + {HPHW_FIO, 0x03F, 0x000A3, 0x0, "Merlin+ 180 Core SE FWSCSI PCI Disk"}, + {HPHW_FIO, 0x056, 0x000A3, 0x0, "Raven+ w SE FWSCSI Core PCI Disk"}, + {HPHW_FIO, 0x057, 0x000A3, 0x0, "Raven+ w Diff FWSCSI Core PCI Disk"}, + {HPHW_FIO, 0x004, 0x000A4, 0x0, "SPP2000 Core BA"}, + {HPHW_FIO, 0x004, 0x000A6, 0x0, "Sonic Ethernet 802.3 Card"}, + {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI SuperIO RS-232"}, + {HPHW_FIO, 0x004, 0x000A9, 0x00, "Forte Core PCI USB KB"}, + {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI SuperIO RS-232"}, + {HPHW_FIO, 0x005, 0x000A9, 0x00, "AllegroLow Core PCI USB KB"}, + {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI SuperIO RS-232"}, + {HPHW_FIO, 0x006, 0x000A9, 0x00, "AllegroHigh Core PCI USB KB"}, + {HPHW_FIO, 0x007, 0x000A9, 0x0, "Miscelaneous PCI Plug-in"}, + {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI SuperIO RS-232"}, + {HPHW_FIO, 0x00A, 0x000A9, 0x0, "Lego 360 Core PCI USB KB"}, + {HPHW_FIO, 0x004, 0x00320, 0x0, "Metheus Frame Buffer"}, + {HPHW_FIO, 0x004, 0x00340, 0x0, "BARCO CX4500 VME Grphx Cnsl"}, + {HPHW_FIO, 0x004, 0x00360, 0x0, "Hughes TOG VME FDDI"}, + {HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"}, + {HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"}, + {HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"}, + {HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"}, + {HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"}, + {HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"}, + {HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"}, + {HPHW_MEMORY, 0x00C, 0x00008, 0x08, "Kahlua 8MB"}, + {HPHW_MEMORY, 0x00D, 0x00008, 0x08, "Kahlua 4MB"}, + {HPHW_MEMORY, 0x00E, 0x00008, 0x08, "Tequila 16MB"}, + {HPHW_MEMORY, 0x00F, 0x00008, 0x08, "Tequila 32MB"}, + {HPHW_MEMORY, 0x040, 0x00008, 0x00, "Hitachi"}, + {HPHW_MEMORY, 0x004, 0x00009, 0x00, "Cheetah"}, + {HPHW_MEMORY, 0x005, 0x00009, 0x00, "Emerald"}, + {HPHW_MEMORY, 0x008, 0x00009, 0x00, "Indigo 3MB/5MB"}, + {HPHW_MEMORY, 0x00C, 0x00009, 0x00, "Indigo 8MB"}, + {HPHW_MEMORY, 0x00D, 0x00009, 0x00, "Paradise 4MB"}, + {HPHW_MEMORY, 0x00E, 0x00009, 0x00, "Burgundy Onboard"}, + {HPHW_MEMORY, 0x012, 0x00009, 0x00, "Indigo 12MB/20MB"}, + {HPHW_MEMORY, 0x013, 0x00009, 0x00, "Cobra"}, + {HPHW_MEMORY, 0x014, 0x00009, 0x00, "Nova"}, + {HPHW_MEMORY, 0x015, 0x00009, 0x00, "Coral"}, + {HPHW_MEMORY, 0x016, 0x00009, 0x00, "Bushmaster"}, + {HPHW_MEMORY, 0x017, 0x00009, 0x00, "Scorpio"}, + {HPHW_MEMORY, 0x018, 0x00009, 0x00, "Flounder"}, + {HPHW_MEMORY, 0x019, 0x00009, 0x00, "Hardball"}, + {HPHW_MEMORY, 0x01A, 0x00009, 0x00, "CoralII 99"}, + {HPHW_MEMORY, 0x01B, 0x00009, 0x00, "Scorpio Jr."}, + {HPHW_MEMORY, 0x01C, 0x00009, 0x00, "Strider-50 (715T)"}, + {HPHW_MEMORY, 0x01D, 0x00009, 0x00, "Strider-33 (707T)"}, + {HPHW_MEMORY, 0x01E, 0x00009, 0x00, "Trailways-50 (715S)"}, + {HPHW_MEMORY, 0x01F, 0x00009, 0x00, "Trailways-33 (707S)"}, + {HPHW_MEMORY, 0x020, 0x00009, 0x00, "Pace"}, + {HPHW_MEMORY, 0x021, 0x00009, 0x00, "Sidewinder"}, + {HPHW_MEMORY, 0x022, 0x00009, 0x00, "Orville"}, + {HPHW_MEMORY, 0x023, 0x00009, 0x00, "Wilbur"}, + {HPHW_MEMORY, 0x026, 0x00009, 0x00, "Gecko"}, + {HPHW_MEMORY, 0x027, 0x00009, 0x00, "Scorpio Sr."}, + {HPHW_MEMORY, 0x028, 0x00009, 0x00, "Scorpio 100"}, + {HPHW_MEMORY, 0x029, 0x00009, 0x00, "Spectra 50"}, + {HPHW_MEMORY, 0x02A, 0x00009, 0x00, "CoralII 132"}, + {HPHW_MEMORY, 0x02F, 0x00009, 0x00, "KittyHawk DC2-"}, + {HPHW_MEMORY, 0x030, 0x00009, 0x00, "Spectra 75"}, + {HPHW_MEMORY, 0x031, 0x00009, 0x00, "Spectra 100"}, + {HPHW_MEMORY, 0x032, 0x00009, 0x00, "KittyHawk DC3"}, + {HPHW_MEMORY, 0x033, 0x00009, 0x00, "Fast Pace"}, + {HPHW_MEMORY, 0x034, 0x00009, 0x00, "Snake Eagle"}, + {HPHW_MEMORY, 0x035, 0x00009, 0x00, "Anole 64"}, + {HPHW_MEMORY, 0x036, 0x00009, 0x00, "Anole 100"}, + {HPHW_MEMORY, 0x037, 0x00009, 0x00, "Snake Cheetah"}, + {HPHW_MEMORY, 0x038, 0x00009, 0x00, "Gecko 80"}, + {HPHW_MEMORY, 0x039, 0x00009, 0x00, "Gecko 100"}, + {HPHW_MEMORY, 0x03A, 0x00009, 0x00, "Gecko 120"}, + {HPHW_MEMORY, 0x03B, 0x00009, 0x00, "Gila 80"}, + {HPHW_MEMORY, 0x03C, 0x00009, 0x00, "Gila 100"}, + {HPHW_MEMORY, 0x03D, 0x00009, 0x00, "Gila 120"}, + {HPHW_MEMORY, 0x03E, 0x00009, 0x00, "Scorpio-L 80"}, + {HPHW_MEMORY, 0x03F, 0x00009, 0x00, "Scorpio-L 100"}, + {HPHW_MEMORY, 0x040, 0x00009, 0x00, "Scorpio-L 120"}, + {HPHW_MEMORY, 0x041, 0x00009, 0x00, "Spectra-L 80"}, + {HPHW_MEMORY, 0x042, 0x00009, 0x00, "Spectra-L 100"}, + {HPHW_MEMORY, 0x043, 0x00009, 0x00, "Spectra-L 120"}, + {HPHW_MEMORY, 0x044, 0x00009, 0x00, "Piranha 100"}, + {HPHW_MEMORY, 0x045, 0x00009, 0x00, "Piranha 120"}, + {HPHW_MEMORY, 0x046, 0x00009, 0x00, "Jason 50"}, + {HPHW_MEMORY, 0x047, 0x00009, 0x00, "Jason 100"}, + {HPHW_MEMORY, 0x049, 0x00009, 0x00, "SkyHawk 100/120"}, + {HPHW_MEMORY, 0x04A, 0x00009, 0x00, "Mirage Jr"}, + {HPHW_MEMORY, 0x04B, 0x00009, 0x00, "Mirage 100"}, + {HPHW_MEMORY, 0x04C, 0x00009, 0x00, "Mirage 100+"}, + {HPHW_MEMORY, 0x04D, 0x00009, 0x00, "Electra 100"}, + {HPHW_MEMORY, 0x04E, 0x00009, 0x00, "Electra 120"}, + {HPHW_MEMORY, 0x04F, 0x00009, 0x00, "Mirage 80"}, + {HPHW_MEMORY, 0x050, 0x00009, 0x00, "UL Proc 1 way T'100"}, + {HPHW_MEMORY, 0x051, 0x00009, 0x00, "UL Proc 1 way T'120"}, + {HPHW_MEMORY, 0x052, 0x00009, 0x00, "UL Proc 2 way T'100"}, + {HPHW_MEMORY, 0x053, 0x00009, 0x00, "KittyHawk DC3-"}, + {HPHW_MEMORY, 0x054, 0x00009, 0x00, "UL Proc 2 way T'120"}, + {HPHW_MEMORY, 0x055, 0x00009, 0x00, "Raven 120 mem"}, + {HPHW_MEMORY, 0x056, 0x00009, 0x00, "UL Proc L 75"}, + {HPHW_MEMORY, 0x057, 0x00009, 0x00, "UL Proc L 100"}, + {HPHW_MEMORY, 0x058, 0x00009, 0x00, "Anole T"}, + {HPHW_MEMORY, 0x059, 0x00009, 0x00, "SAIC L-80"}, + {HPHW_MEMORY, 0x05A, 0x00009, 0x00, "Merlin+ L2 180"}, + {HPHW_MEMORY, 0x05B, 0x00009, 0x00, "Raven U 200 2-way"}, + {HPHW_MEMORY, 0x05C, 0x00009, 0x00, "Raven U 180+"}, + {HPHW_MEMORY, 0x05D, 0x00009, 0x00, "Raven U 200"}, + {HPHW_MEMORY, 0x05E, 0x00009, 0x00, "Rocky2 150 Memory"}, + {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"}, + {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"}, + {HPHW_MEMORY, 0x05F, 0x00009, 0x00, "SPP2000 Memory"}, + {HPHW_MEMORY, 0x060, 0x00009, 0x00, "Merlin L2 132"}, + {HPHW_MEMORY, 0x061, 0x00009, 0x00, "Merlin+ L2 132"}, + {HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"}, + {HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"}, + {HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"}, + {HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"}, + {HPHW_MEMORY, 0x067, 0x00009, 0x00, "Merlin 160/ThunderHawk Memory"}, + {HPHW_MEMORY, 0x068, 0x00009, 0x00, "LightningHawk Memory"}, + {HPHW_MEMORY, 0x069, 0x00009, 0x00, "Rocky1 Memory"}, + {HPHW_MEMORY, 0x06A, 0x00009, 0x00, "Raven L2 132"}, + {HPHW_MEMORY, 0x06B, 0x00009, 0x00, "Raven L2 160"}, + {HPHW_MEMORY, 0x06C, 0x00009, 0x00, "Raven L2 187"}, + {HPHW_MEMORY, 0x06D, 0x00009, 0x00, "Raven L2 200"}, + {HPHW_MEMORY, 0x06E, 0x00009, 0x00, "Raven U 230"}, + {HPHW_MEMORY, 0x06F, 0x00009, 0x00, "Raven U 240"}, + {HPHW_MEMORY, 0x070, 0x00009, 0x00, "Rocky2 120 Memory"}, + {HPHW_MEMORY, 0x071, 0x00009, 0x00, "Raven U 160"}, + {HPHW_MEMORY, 0x072, 0x00009, 0x00, "Raven U 180"}, + {HPHW_MEMORY, 0x072, 0x00009, 0x00, "UL Proc 1 way T'120 1MB/1MB"}, + {HPHW_MEMORY, 0x073, 0x00009, 0x00, "UL Proc 2 way T'120 1MB/1MB"}, + {HPHW_MEMORY, 0x074, 0x00009, 0x00, "Anole L2 132 memory"}, + {HPHW_MEMORY, 0x075, 0x00009, 0x00, "Anole L2 165 memory"}, + {HPHW_MEMORY, 0x076, 0x00009, 0x00, "UL 1 way U160 512K/512K memory"}, + {HPHW_MEMORY, 0x077, 0x00009, 0x00, "UL 2 way U160 512K/512K memory"}, + {HPHW_MEMORY, 0x078, 0x00009, 0x00, "Kiji L2 132 memory"}, + {HPHW_MEMORY, 0x079, 0x00009, 0x00, "UL 1 way U160 1M/1M memory"}, + {HPHW_MEMORY, 0x07A, 0x00009, 0x00, "UL 2 way U160 1M/1M memory"}, + {HPHW_MEMORY, 0x07B, 0x00009, 0x00, "UL 1 way U180 1M/1M memory"}, + {HPHW_MEMORY, 0x07C, 0x00009, 0x00, "UL 2 way U180 1M/1M memory"}, + {HPHW_MEMORY, 0x07D, 0x00009, 0x00, "UL 1 way U240 U+ 2M/2M memory"}, + {HPHW_MEMORY, 0x07E, 0x00009, 0x00, "UL 2 way U240 U+ 2M/2M memory"}, + {HPHW_MEMORY, 0x07F, 0x00009, 0x00, "UL L2 132 memory"}, + {HPHW_MEMORY, 0x080, 0x00009, 0x00, "UL L2 160 memory"}, + {HPHW_MEMORY, 0x081, 0x00009, 0x00, "Merlin Jr 132 memory"}, + {HPHW_MEMORY, 0x082, 0x00009, 0x00, "FireHawk 200 Memory"}, + {HPHW_MEMORY, 0x083, 0x00009, 0x00, "SummitHawk Memory"}, + {HPHW_MEMORY, 0x084, 0x00009, 0x00, "Jade Upgrade Memory"}, + {HPHW_MEMORY, 0x085, 0x00009, 0x00, "SPP2500 Memory"}, + {HPHW_MEMORY, 0x086, 0x00009, 0x00, "AllegroHigh Memory"}, + {HPHW_MEMORY, 0x087, 0x00009, 0x00, "AllegroLow Memory"}, + {HPHW_MEMORY, 0x088, 0x00009, 0x00, "Forte 2w Memory"}, + {HPHW_MEMORY, 0x089, 0x00009, 0x00, "Forte 4w Memory"}, + {HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"}, + {HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"}, + {HPHW_MEMORY, 0x090, 0x00009, 0x00, "Prelude SMC Memory"}, + {HPHW_MEMORY, 0x091, 0x00009, 0x00, "Lego 360 Memory"}, + {HPHW_MEMORY, 0x7FF, 0x00009, 0x00, "NEC Aska memory"}, + {HPHW_MEMORY, 0x800, 0x00009, 0x00, "Hitachi Tiny 64"}, + {HPHW_MEMORY, 0x801, 0x00009, 0x00, "Hitachi Tiny 80"}, + {HPHW_MEMORY, 0x8FF, 0x00009, 0x00, "Hitachi X memory"}, + {HPHW_MEMORY, 0x091, 0x00009, 0x00, "M2250 Memory"}, + {HPHW_MEMORY, 0x092, 0x00009, 0x00, "M2500 Memory"}, + {HPHW_MEMORY, 0x093, 0x00009, 0x00, "Sonata 440 Memory"}, + {HPHW_MEMORY, 0x094, 0x00009, 0x00, "Sonata 360 Memory"}, + {HPHW_MEMORY, 0x095, 0x00009, 0x00, "Rhapsody 440 Memory"}, + {HPHW_MEMORY, 0x096, 0x00009, 0x00, "Rhapsody 360 Memory"}, + {HPHW_MEMORY, 0x097, 0x00009, 0x00, "Raven W 360 Memory"}, + {HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W 440 Memory"}, + {HPHW_MEMORY, 0x099, 0x00009, 0x00, "Rhapsody DC- 440 Memory"}, + {HPHW_MEMORY, 0x09A, 0x00009, 0x00, "Rhapsody DC- 360 Memory"}, + {HPHW_MEMORY, 0x09B, 0x00009, 0x00, "Crescendo Memory"}, + {HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"}, + {HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"}, + {HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"}, + {HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"}, + {0, } /* leave the last entry empty ! */ +}; + + +static struct hp_cpu_type_mask { + unsigned short model; + unsigned short mask; + enum cpu_type cpu; +} hp_cpu_type_mask_list[] = { + + { 0x0000, 0x0ff0, pcx }, /* 0x0000 - 0x000f */ + { 0x0048, 0x0ff0, pcxl }, /* 0x0040 - 0x004f */ + { 0x0080, 0x0ff0, pcx }, /* 0x0080 - 0x008f */ + { 0x0100, 0x0ff0, pcx }, /* 0x0100 - 0x010f */ + { 0x0182, 0x0ffe, pcx }, /* 0x0182 - 0x0183 */ + { 0x0182, 0x0ffe, pcxt }, /* 0x0182 - 0x0183 */ + { 0x0184, 0x0fff, pcxu }, /* 0x0184 - 0x0184 */ + { 0x0200, 0x0ffe, pcxs }, /* 0x0200 - 0x0201 */ + { 0x0202, 0x0fff, pcxs }, /* 0x0202 - 0x0202 */ + { 0x0203, 0x0fff, pcxt }, /* 0x0203 - 0x0203 */ + { 0x0204, 0x0ffc, pcxt }, /* 0x0204 - 0x0207 */ + { 0x0280, 0x0ffc, pcxs }, /* 0x0280 - 0x0283 */ + { 0x0284, 0x0ffc, pcxt }, /* 0x0284 - 0x0287 */ + { 0x0288, 0x0fff, pcxt }, /* 0x0288 - 0x0288 */ + { 0x0300, 0x0ffc, pcxs }, /* 0x0300 - 0x0303 */ + { 0x0310, 0x0ff0, pcxt }, /* 0x0310 - 0x031f */ + { 0x0320, 0x0ff0, pcxt }, /* 0x0320 - 0x032f */ + { 0x0400, 0x0ff0, pcxt }, /* 0x0400 - 0x040f */ + { 0x0480, 0x0ff0, pcxl }, /* 0x0480 - 0x048f */ + { 0x0500, 0x0ff0, pcxl2 }, /* 0x0500 - 0x050f */ + { 0x0510, 0x0ff0, pcxl2 }, /* 0x0510 - 0x051f */ + { 0x0580, 0x0ff8, pcxt_ }, /* 0x0580 - 0x0587 */ + { 0x0588, 0x0ffc, pcxt_ }, /* 0x0588 - 0x058b */ + { 0x058c, 0x0ffe, pcxt_ }, /* 0x058c - 0x058d */ + { 0x058e, 0x0fff, pcxt_ }, /* 0x058e - 0x058e */ + { 0x058f, 0x0fff, pcxu }, /* 0x058f - 0x058f */ + { 0x0590, 0x0ffe, pcxu }, /* 0x0590 - 0x0591 */ + { 0x0592, 0x0fff, pcxt_ }, /* 0x0592 - 0x0592 */ + { 0x0593, 0x0fff, pcxu }, /* 0x0593 - 0x0593 */ + { 0x0594, 0x0ffc, pcxu }, /* 0x0594 - 0x0597 */ + { 0x0598, 0x0ffc, pcxu }, /* 0x0598 - 0x059b */ + { 0x059c, 0x0ffe, pcxu_ }, /* 0x059c - 0x059d */ + { 0x059e, 0x0fff, pcxt_ }, /* 0x059e - 0x059e */ + { 0x059f, 0x0fff, pcxu }, /* 0x059f - 0x059f */ + { 0x05a0, 0x0ffe, pcxt_ }, /* 0x05a0 - 0x05a1 */ + { 0x05a2, 0x0ffe, pcxu }, /* 0x05a2 - 0x05a3 */ + { 0x05a4, 0x0ffc, pcxu }, /* 0x05a4 - 0x05a7 */ + { 0x05a8, 0x0ffc, pcxu }, /* 0x05a8 - 0x05ab */ + { 0x05ad, 0x0fff, pcxu_ }, /* 0x05ad - 0x05ad */ + { 0x05ae, 0x0ffe, pcxu_ }, /* 0x05ae - 0x05af */ + { 0x05b0, 0x0ffe, pcxu_ }, /* 0x05b0 - 0x05b1 */ + { 0x05b2, 0x0fff, pcxu_ }, /* 0x05b2 - 0x05b2 */ + { 0x05b3, 0x0fff, pcxu }, /* 0x05b3 - 0x05b3 */ + { 0x05b4, 0x0fff, pcxw }, /* 0x05b4 - 0x05b4 */ + { 0x05b5, 0x0fff, pcxu_ }, /* 0x05b5 - 0x05b5 */ + { 0x05b6, 0x0ffe, pcxu_ }, /* 0x05b6 - 0x05b7 */ + { 0x05b8, 0x0ffe, pcxu_ }, /* 0x05b8 - 0x05b9 */ + { 0x05ba, 0x0fff, pcxu_ }, /* 0x05ba - 0x05ba */ + { 0x05bb, 0x0fff, pcxw }, /* 0x05bb - 0x05bb */ + { 0x05bc, 0x0ffc, pcxw }, /* 0x05bc - 0x05bf */ + { 0x05c0, 0x0fc0, pcxw }, /* 0x05c0 - 0x05ff */ + { 0x0600, 0x0ff0, pcxl }, /* 0x0600 - 0x060f */ + { 0x0610, 0x0ff0, pcxl }, /* 0x0610 - 0x061f */ + { 0x0000, 0x0000, pcx } /* terminate table */ +}; + +char *cpu_name_version[][2] = { + [pcx] { "PA7000 (PCX)", "1.0" }, + [pcxs] { "PA7000 (PCX-S)", "1.1a" }, + [pcxt] { "PA7100 (PCX-T)", "1.1b" }, + [pcxt_] { "PA7200 (PCX-T')", "1.1c" }, + [pcxl] { "PA7100LC (PCX-L)", "1.1d" }, + [pcxl2] { "PA7300LC (PCX-L2)", "1.1e" }, + [pcxu] { "PA8000 (PCX-U)", "2.0" }, + [pcxu_] { "PA8200 (PCX-U+)", "2.0" }, + [pcxw] { "PA8500 (PCX-W)", "2.0" }, + [pcxw_] { "PA8600 (PCX-W+)", "2.0" } +}; + +char *parisc_getHWtype(unsigned short hw_type) +{ + if (hw_type <= HPHW_CIO) { + return hw_type_name[hw_type]; + } else { + return "Unknown Type"; + } +} + +char *parisc_getHWdescription(unsigned short hw_type, unsigned long hversion, + unsigned long sversion) +{ + struct hp_hardware *listptr; + + for (listptr = hp_hardware_list; listptr->name; listptr++) { + if ((listptr->hw_type==hw_type) && + (listptr->hversion==hversion) && + (listptr->sversion==sversion)){ + return listptr->name; + } + } + return "unknown device"; +} + + +/* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */ +enum cpu_type parisc_get_cpu_type(unsigned long hversion) +{ + struct hp_cpu_type_mask *ptr; + unsigned short model = ((unsigned short) (hversion)) >> 4; + + for (ptr = hp_cpu_type_mask_list; 0 != ptr->mask; ptr++) { + if (ptr->model == (model & ptr->mask)) + return ptr->cpu; + } + panic("parisc_get_cpu_type() could not identify CPU type\n"); + + return pcx; /* not reached: */ +} + + +struct hp_hardware *parisc_get_reference(unsigned short hw_type, + unsigned long hversion, unsigned long sversion) +{ + struct hp_hardware *listptr = hp_hardware_list; + + for (listptr = hp_hardware_list; listptr->name; listptr++) { + if ((listptr->hw_type == hw_type) && + (listptr->hversion == hversion) && + (listptr->sversion == sversion)) { + return listptr; + } + } + return NULL; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/head.S linux/arch/parisc/kernel/head.S --- v2.4.0-test11/linux/arch/parisc/kernel/head.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/head.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,156 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 by Helge Deller + * Copyright 1999 SuSE GmbH (Philipp Rumpf) + * Copyright 1999 Philipp Rumpf (prumpf@tux.org) + * + * Initial Version 04-23-1999 by Helge Deller (helge.deller@ruhr-uni-bochum.de) + */ + + +#include +#include + +#define __ASSEMBLY__ +/********* +#include +*********/ +#include +#include + + + .level 1.1 + + .section .initcall.init + .align 4 + .export __initcall_start +__initcall_start: + .export __initcall_end +__initcall_end: + .export __setup_start +__setup_start: + .export __setup_end +__setup_end: + + .text + .align 4 + .import init_task_union,data + .import $global$ /* forward declaration */ + .import fault_vector_11,code /* IVA parisc 1.1 32 bit */ + .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ + .import start_parisc,code /* then enable VM and go here */ + + .export stext + .export _stext,data /* Kernel want it this way! */ +_stext: +stext: + .proc + .callinfo + + /* Make sure sr4-sr7 are set to zero for the kernel address space */ + + mtsp %r0,%sr4 + mtsp %r0,%sr5 + mtsp %r0,%sr6 + mtsp %r0,%sr7 + + /* Initialize startup VM. Just map first 8 MB of memory */ + + ldil L%PA(pg0),%r1 + ldo R%PA(pg0)(%r1),%r1 + ldo _PAGE_TABLE(%r1),%r3 + ldil L%PA(swapper_pg_dir),%r4 + ldo R%PA(swapper_pg_dir)(%r4),%r4 + mtctl %r4,%cr24 /* Initialize kernel root pointer */ + mtctl %r4,%cr25 /* Initialize user root pointer */ + stw %r3,0xc00(%r4) /* Hardwired 0xc0000000 kernel vaddr start */ + ldo 0x1000(%r3),%r3 + stw %r3,0xc04(%r4) + ldo _PAGE_KERNEL(%r0),%r3 /* Hardwired 0x0 phys addr start */ +$pgt_fill_loop: + stwm %r3,4(%r1) + ldo 0x1000(%r3),%r3 + bb,>= %r3,8,$pgt_fill_loop + nop + + /* Initialize the global data pointer */ + ldil L%$global$,%dp + ldo R%$global$(%dp),%dp + + /* And the stack pointer, physical too */ + ldil L%init_task_union+TASK_SZ_ALGN,%sp + ldo R%init_task_union+TASK_SZ_ALGN(%sp),%sp + + /* we need this to take interruptions directly after the rfi below */ + /* (which we need for PA2.0 boxes) */ + mtctl %r0, %cr30 + + /* + * Set up our interrupt table. HPMCs might not work after this! + * + * We need to install the correct iva for PA1.1 or PA2.0. The + * following short sequence of instructions can determine this + * (without being illegal on a PA1.1 machine). + */ + + ldi 32,%r10 + mtctl %r10,%cr11 + .level 2.0 + mfctl,w %cr11,%r10 + .level 1.1 + comib,<>,n 0,%r10,$is_pa20 + ldil L%PA(fault_vector_11),%r10 + b $install_iva + ldo R%PA(fault_vector_11)(%r10),%r10 + +$is_pa20: + ldil L%PA(fault_vector_20),%r10 + ldo R%PA(fault_vector_20)(%r10),%r10 + +$install_iva: + mtctl %r10,%cr14 + + /* Disable (most) interruptions */ + mtsm %r0 + + /* kernel PSW: + * - no interruptions except for HPMC and TOC (which are handled by PDC) + * - Q bit set (IODC / PDC interruptions) + * - big-endian + * - virtually mapped + */ + + ldil L%KERNEL_PSW,%r10 + ldo R%KERNEL_PSW(%r10),%r10 + mtctl %r10,%ipsw + + /* Set the space pointers for the post-RFI world */ + mtctl %r0,%cr17 /* Clear two-level IIA Space Queue */ + mtctl %r0,%cr17 /* effectively setting kernel space. */ + + /* And the return address(es) too */ + ldil L%start_parisc,%r10 + ldo R%start_parisc(%r10),%r10 + mtctl %r10,%cr18 + ldo 4(%r10),%r10 + mtctl %r10,%cr18 + + /* Jump to hyperspace */ + rfi + nop + + .procend + + .data + + .align 4 + .export $global$,data + + .type $global$,@object + .size $global$,4 +$global$: + .word 0 diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/hpmc.S linux/arch/parisc/kernel/hpmc.S --- v2.4.0-test11/linux/arch/parisc/kernel/hpmc.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/hpmc.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,319 @@ +/* + * HPMC (High Priority Machine Check) handler. + * + * Copyright (C) 1999 Philipp Rumpf + * Copyright (C) 1999 Hewlett-Packard (Frank Rowand) + * Copyright (C) 2000 Hewlett-Packard (John Marvin) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +/* + * This HPMC handler retrieves the HPMC pim data, resets IO and + * returns to the default trap handler with code set to 1 (HPMC). + * The default trap handler calls handle interruption, which + * does a stack and register dump. This at least allows kernel + * developers to get back to C code in virtual mode, where they + * have the option to examine and print values from memory that + * would help in debugging an HPMC caused by a software bug. + * + * There is more to do here: + * + * 1) On MP systems we need to synchronize processors + * before calling pdc/iodc. + * 2) We should be checking the system state and not + * returning to the fault handler if things are really + * bad. + * + */ + + .level 1.1 + .data + +#define __ASSEMBLY__ +#include +#include + + /* + * stack for os_hpmc, the HPMC handler. + * buffer for IODC procedures (for the HPMC handler). + * + * IODC requires 7K byte stack. That leaves 1K byte for os_hpmc. + */ + + .align 4096 +hpmc_stack: + .block 16384 + +#define HPMC_IODC_BUF_SIZE 0x8000 + + .align 4096 +hpmc_iodc_buf: + .block HPMC_IODC_BUF_SIZE + + .align 8 +hpmc_raddr: + .block 128 + +#define HPMC_PIM_DATA_SIZE 896 /* Enough to hold all architected 2.0 state */ + + .export hpmc_pim_data, data + .align 8 +hpmc_pim_data: + .block HPMC_PIM_DATA_SIZE + + .text + + .export os_hpmc, code + .import intr_save, code + +os_hpmc: + + /* + * registers modified: + * + * Using callee saves registers without saving them. The + * original values are in the pim dump if we need them. + * + * r2 (rp) return pointer + * r3 address of PDCE_PROC + * r4 scratch + * r5 scratch + * r23 (arg3) procedure arg + * r24 (arg2) procedure arg + * r25 (arg1) procedure arg + * r26 (arg0) procedure arg + * r30 (sp) stack pointer + * + * registers read: + * + * r26 contains address of PDCE_PROC on entry + * r28 (ret0) return value from procedure + */ + + copy arg0, %r3 /* save address of PDCE_PROC */ + + /* + * disable nested HPMCs + * + * Increment os_hpmc checksum to invalidate it. + * Do this before turning the PSW M bit off. + */ + + mfctl %cr14, %r4 + ldw 52(%r4),%r5 + addi 1,%r5,%r5 + stw %r5,52(%r4) + + /* MP_FIXME: synchronize all processors. */ + + /* Setup stack pointer. */ + + ldil L%PA(hpmc_stack),sp + ldo R%PA(hpmc_stack)(sp),sp + + ldo 128(sp),sp /* leave room for arguments */ + + /* + * Most PDC routines require that the M bit be off. + * So turn on the Q bit and turn off the M bit. + */ + + ldo 8(%r0),%r4 /* PSW Q on, PSW M off */ + mtctl %r4,ipsw + mtctl %r0,pcsq + mtctl %r0,pcsq + ldil L%PA(os_hpmc_1),%r4 + ldo R%PA(os_hpmc_1)(%r4),%r4 + mtctl %r4,pcoq + ldo 4(%r4),%r4 + mtctl %r4,pcoq + rfi + nop + +os_hpmc_1: + + /* Call PDC_PIM to get HPMC pim info */ + + /* + * Note that on some newer boxes, PDC_PIM must be called + * before PDC_IO if you want IO to be reset. PDC_PIM sets + * a flag that PDC_IO examines. + */ + + ldo PDC_PIM(%r0), arg0 + ldo PDC_PIM_HPMC(%r0),arg1 /* Transfer HPMC data */ + ldil L%PA(hpmc_raddr),arg2 + ldo R%PA(hpmc_raddr)(arg2),arg2 + ldil L%PA(hpmc_pim_data),arg3 + ldo R%PA(hpmc_pim_data)(arg3),arg3 + ldil L%HPMC_PIM_DATA_SIZE,%r4 + ldo R%HPMC_PIM_DATA_SIZE(%r4),%r4 + stw %r4,-52(sp) + + ldil L%PA(os_hpmc_2), rp + bv (r3) /* call pdce_proc */ + ldo R%PA(os_hpmc_2)(rp), rp + +os_hpmc_2: + comib,<> 0,ret0, os_hpmc_fail + + /* Reset IO by calling the hversion dependent PDC_IO routine */ + + ldo PDC_IO(%r0),arg0 + ldo 0(%r0),arg1 /* log IO errors */ + ldo 0(%r0),arg2 /* reserved */ + ldo 0(%r0),arg3 /* reserved */ + stw %r0,-52(sp) /* reserved */ + + ldil L%PA(os_hpmc_3),rp + bv (%r3) /* call pdce_proc */ + ldo R%PA(os_hpmc_3)(rp),rp + +os_hpmc_3: + + /* FIXME? Check for errors from PDC_IO (-1 might be OK) */ + + /* + * Initialize the IODC console device (HPA,SPA, path etc. + * are stored on page 0. + */ + + /* + * Load IODC into hpmc_iodc_buf by calling PDC_IODC. + * Note that PDC_IODC handles flushing the appropriate + * data and instruction cache lines. + */ + + ldo PDC_IODC(%r0),arg0 + ldo PDC_IODC_READ(%r0),arg1 + ldil L%PA(hpmc_raddr),arg2 + ldo R%PA(hpmc_raddr)(arg2),arg2 + ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */ + ldo PDC_IODC_RI_INIT(%r0),%r4 + stw %r4,-52(sp) + ldil L%PA(hpmc_iodc_buf),%r4 + ldo R%PA(hpmc_iodc_buf)(%r4),%r4 + stw %r4,-56(sp) + ldil L%HPMC_IODC_BUF_SIZE,%r4 + ldo R%HPMC_IODC_BUF_SIZE(%r4),%r4 + stw %r4,-60(sp) + + ldil L%PA(os_hpmc_4),rp + bv (%r3) /* call pdce_proc */ + ldo R%PA(os_hpmc_4)(rp),rp + +os_hpmc_4: + comib,<> 0,ret0,os_hpmc_fail + + /* Call the entry init (just loaded by PDC_IODC) */ + + ldw BOOT_CONSOLE_HPA_OFFSET(%r0),arg0 /* console hpa */ + ldo ENTRY_INIT_MOD_DEV(%r0), arg1 + ldw BOOT_CONSOLE_SPA_OFFSET(%r0),arg2 /* console spa */ + depi 0,31,11,arg2 /* clear bits 21-31 */ + ldo BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */ + ldil L%PA(hpmc_raddr),%r4 + ldo R%PA(hpmc_raddr)(%r4),%r4 + stw %r4, -52(sp) + stw %r0, -56(sp) /* HV */ + stw %r0, -60(sp) /* HV */ + stw %r0, -64(sp) /* HV */ + stw %r0, -68(sp) /* lang, must be zero */ + + ldil L%PA(hpmc_iodc_buf),%r5 + ldo R%PA(hpmc_iodc_buf)(%r5),%r5 + ldil L%PA(os_hpmc_5),rp + bv (%r5) + ldo R%PA(os_hpmc_5)(rp),rp + +os_hpmc_5: + comib,<> 0,ret0,os_hpmc_fail + + /* Prepare to call intr_save */ + + /* + * Load kernel page directory (load into user also, since + * we don't intend to ever return to user land anyway) + */ + + ldil L%PA(swapper_pg_dir),%r4 + ldo R%PA(swapper_pg_dir)(%r4),%r4 + mtctl %r4,%cr24 /* Initialize kernel root pointer */ + mtctl %r4,%cr25 /* Initialize user root pointer */ + + /* Clear sr4-sr7 */ + + mtsp %r0, %sr4 + mtsp %r0, %sr5 + mtsp %r0, %sr6 + mtsp %r0, %sr7 + + tovirt %r30 /* make sp virtual */ + + rsm 8,%r0 /* Clear Q bit */ + ldi 1,%r1 + mtctl %r1,%cr29 /* Set trap code to "1" for HPMC */ + mtctl %r0,%cr30 /* Force interruptions to use hpmc stack */ + ldil L%PA(intr_save), %r1 + ldo R%PA(intr_save)(%r1), %r1 + be 0(%sr7,%r1) + nop + +os_hpmc_fail: + + /* + * Reset the system + * + * Some systems may lockup from a broadcast reset, so try the + * hversion PDC_BROADCAST_RESET() first. + * MP_FIXME: reset all processors if more than one central bus. + */ + + /* PDC_BROADCAST_RESET() */ + + ldo PDC_BROADCAST_RESET(%r0),arg0 + ldo 0(%r0),arg1 /* do reset */ + + ldil L%PA(os_hpmc_6),rp + bv (%r3) /* call pdce_proc */ + ldo R%PA(os_hpmc_6)(rp),rp + +os_hpmc_6: + + /* + * possible return values: + * -1 non-existent procedure + * -2 non-existent option + * -16 unaligned stack + * + * If call returned, do a broadcast reset. + */ + + ldil L%0xfffc0000,%r4 /* IO_BROADCAST */ + ldo 5(%r0),%r5 + stw %r5,48(%r4) /* CMD_RESET to IO_COMMAND offset */ + + b . + nop + + /* this label used to compute os_hpmc checksum */ + + .export os_hpmc_end, code + +os_hpmc_end: + + nop diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/init_task.c linux/arch/parisc/kernel/init_task.c --- v2.4.0-test11/linux/arch/parisc/kernel/init_task.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/init_task.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,29 @@ +#include +#include +#include + +#include +#include +#include + +static struct vm_area_struct init_mmap = INIT_MMAP; +static struct fs_struct init_fs = INIT_FS; +static struct files_struct init_files = INIT_FILES; +static struct signal_struct init_signals = INIT_SIGNALS; +struct mm_struct init_mm = INIT_MM(init_mm); + +/* + * Initial task structure. + * + * We need to make sure that this is 16384-byte aligned due to the + * way process stacks are handled. This is done by having a special + * "init_task" linker map entry.. + */ +union task_union init_task_union + __attribute__((section("init_task"), aligned(4096))) = { INIT_TASK(init_task_union.task) }; + +unsigned long swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { 0, }; +#ifdef __LP64__ +unsigned long pmd0[PTRS_PER_PMD] __attribute__ ((aligned(4096))) = { 0, }; +#endif +unsigned long pg0[PT_INITIAL * PTRS_PER_PTE] __attribute__ ((aligned(4096))) = { 0, }; diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/inventory.c linux/arch/parisc/kernel/inventory.c --- v2.4.0-test11/linux/arch/parisc/kernel/inventory.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/inventory.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,397 @@ + +/* Copyright (c) 1999 The Puffin Group */ +/* Written by David Kennedy and Alex deVries */ + +#include +#include +#include +#include +#include + +/* +** Debug options +** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices. +*/ +#undef DEBUG_PAT + +extern char *parisc_getHWtype(unsigned short hw_type); + +extern struct hp_device * register_module(void *hpa); +extern void print_devices(char * buf); + + +int pdc_hpa_processor(void *address); + +#ifndef __LP64__ +static u8 iodc_data[32] __attribute__ ((aligned (64))); +static struct pdc_model model __attribute__ ((aligned (8))); +#endif +static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0}; +static struct pdc_hpa processor_hpa __attribute__ ((aligned (8))); +static struct pdc_system_map module_result __attribute__ ((aligned (8))); +static struct pdc_module_path module_path __attribute__ ((aligned (8))); + +#ifdef __LP64__ +#include + +int pdc_pat = 0; + +/* +** The module object is filled via PDC_PAT_CELL[Return Cell Module]. +** If a module is found, register module will get the IODC bytes via +** pdc_iodc_read() using the PA view of conf_base_addr for the hpa parameter. +** +** The IO view can be used by PDC_PAT_CELL[Return Cell Module] +** only for SBAs and LBAs. This view will cause an invalid +** argument error for all other cell module types. +** +*/ + +static int +pat_query_module( ulong pcell_loc, ulong mod_index) +{ + extern int num_devices; + extern struct hp_device devices[]; + + pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; + struct hp_device * dev = &devices[num_devices]; + uint64_t temp; /* 64-bit scratch value */ + long status; /* PDC return value status */ + + /* return cell module (PA or Processor view) */ + status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index, + PA_VIEW, & pa_pdc_cell); + + if (status != PDC_RET_OK) { + /* no more cell modules or error */ + return status; + } + + /* + ** save parameters in the hp_device + ** (The idea being the device driver will call pdc_pat_cell_module() + ** and store the results in it's own data structure.) + */ + dev->pcell_loc = pcell_loc; + dev->mod_index = mod_index; + + /* save generic info returned from the call */ + /* REVISIT: who is the consumer of this? not sure yet... */ + dev->mod_info = pa_pdc_cell.mod_info; /* pass to PAT_GET_ENTITY() */ + dev->pmod_loc = pa_pdc_cell.mod_location; + dev->mod_path = pa_pdc_cell.mod_path; + + temp = pa_pdc_cell.cba; + register_module((void *) PAT_GET_CBA(temp)); /* fills in dev->hpa */ + +#ifdef DEBUG_PAT + /* dump what we see so far... */ + switch (PAT_GET_ENTITY(dev->mod_info)) { + ulong i; + + case PAT_ENTITY_PROC: + printk ("PAT_ENTITY_PROC: id_eid 0x%lx\n", pa_pdc_cell.mod[0]); + break; + + case PAT_ENTITY_MEM: + printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n", + pa_pdc_cell.mod[0], + pa_pdc_cell.mod[1], + pa_pdc_cell.mod[2]); + break; + case PAT_ENTITY_CA: + printk ("PAT_ENTITY_CA: %ld\n",pcell_loc); + break; + + case PAT_ENTITY_PBC: + printk ("PAT_ENTITY_PBC: "); + goto print_ranges; + + case PAT_ENTITY_SBA: + printk ("PAT_ENTITY_SBA: "); + goto print_ranges; + + case PAT_ENTITY_LBA: + printk ("PAT_ENTITY_LBA: "); + +print_ranges: + printk ("ranges %ld\n", pa_pdc_cell.mod[1]); + for (i = 0; i < pa_pdc_cell.mod[1]; i++) { + printk (" %ld: 0x%016lx 0x%016lx 0x%016lx\n", i, + pa_pdc_cell.mod[2+i*3], /* type */ + pa_pdc_cell.mod[3+i*3], /* start */ + pa_pdc_cell.mod[4+i*3]); /* finish (ie end) */ + } + printk("\n"); + break; + } +#endif /* DEBUG_PAT */ + return PDC_RET_OK; +} + + +static int do_pat_inventory(void) +{ + ulong mod_index=0; + int status; + ulong cell_num; + ulong pcell_loc; + + pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK); + if (!pdc_pat) + { + return 0; + } + + cell_num = pdc_result[0]; /* Cell number call was made */ + + /* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */ + pcell_loc = pdc_result[1]; /* Physical location of the cell */ + +#ifdef DEBUG_PAT + printk("CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_num, pcell_loc); +#endif + + status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num); + if (status == PDC_BAD_OPTION) + { + /* Prelude (and it's successors: Lclass, A400/500) only + ** implement PDC_PAT_CELL sub-options 0 and 2. + ** "Home cook'n is best anyhow!" + */ + } else if (PDC_OK == status) { + /* so far only Halfdome supports this */ + pcell_loc = pdc_result[0]; + } else { + panic("WTF? CELL_GET_NUMBER give me invalid cell number?"); + } + + while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index)) + { + mod_index++; + } + + return mod_index; +} +#endif /* __LP64__ */ + +static int do_newer_workstation_inventory(void) +{ + long status; + int i, num = 0; + + /* So the idea here is to simply try one SYSTEM_MAP call. If + that one works, great, otherwise do it another way */ + + status = pdc_system_map_find_mods(&module_result,&module_path,0); + + if (status == PDC_RET_OK) { + /* This is for newer non-PDC-PAT boxes */ + + printk("a newer box...\n"); + for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC && + status != PDC_RET_NE_MOD ;i++) { + + status = pdc_system_map_find_mods(&module_result,&module_path,i); + if (status == PDC_RET_OK) { + num++; + register_module(module_result.mod_addr); + } + } + } + + return (num > 0); +} + +#ifndef __LP64__ +static struct pdc_memory_map r_addr __attribute__ ((aligned (8))); + +static int really_do_oldhw_inventory(void) +{ + int i, mod, num = 0; + int status; + unsigned int hw_type; + unsigned int func; + + /* This is undocumented at the time of writing, but basically + we're setting up mod_path so that bc[0..4]=0xff, and step + through mod to get the "Path Structure for GSC Modules". If + it works, use the returned HPA and determine the hardware type. */ + + for (i=0;i<6;i++) module_path.bc[i]=0xff; + + for (mod=0;mod<16;mod++) { + char *stype = NULL; + + module_path.mod=mod; + status = pdc_mem_map_hpa(&r_addr, &module_path); + if (status!=PDC_RET_OK) continue; + + status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa, + 0, &iodc_data,32 ); + if (status!=PDC_RET_OK) continue; + hw_type = iodc_data[3]&0x1f; + + switch (hw_type) + { + case HPHW_NPROC: /* 0 */ + stype="Processor"; break; + + case HPHW_MEMORY: /* 1 */ + stype="Memory"; break; + + case HPHW_B_DMA: /* 2 */ + stype="Type B DMA"; break; + + case HPHW_A_DMA: /* 4 */ + stype="Type A DMA"; break; + + case HPHW_A_DIRECT: /* 5 */ + stype="Type A Direct"; break; + + case HPHW_BCPORT: /* 7 */ + stype="Bus Converter Port"; break; + + case HPHW_CONSOLE: /* 9 */ + stype="Console"; break; + + case HPHW_FIO: /* 10 - Graphics */ + stype="Foreign I/O (Graphics)"; break; + + case HPHW_BA: /* 11 - Bus Adapter */ + stype="Bus Adapter"; break; + + case HPHW_IOA: /* 12 */ + stype="I/O Adapter"; break; + + case HPHW_BRIDGE: /* 13 */ + stype="Bridge"; break; + + case HPHW_FABRIC: /* 14 */ + stype="Fabric"; break; + + case HPHW_FAULTY: /* 31 */ + stype="Faulty HW"; break; + + case HPHW_OTHER: /* 42 */ + default: + printk("Don't know this hw_type: %d\n", hw_type); + break; + } + + // This is kluged. But don't want to replicate code for + // most of the above cases. + if (stype) { +#ifdef DBG_PDC_QUERY + // parisc/kernel/drivers.c + extern int num_devices; + extern struct hp_device devices[]; + struct hp_hardware *h; +#endif + + status = pdc_mem_map_hpa(&r_addr, &module_path); + if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL) + num++; + + + if (hw_type == HPHW_BA) { + /* Now, we're checking for devices for each + module. I seem to think that the + modules in question are Lasi (2), 2nd Lasi (6) + Wax (5). To do this, set bc[5]=0, and set + bc[4] to the module, and step through the + functions. */ + + for (i=0;i<4;i++) module_path.bc[i]=0xff; + module_path.bc[4]=mod; + for (func=0;func<16;func++) { + module_path.mod = func; + module_path.bc[5]=0; + status = pdc_mem_map_hpa(&r_addr, &module_path); + if (status!=PDC_RET_OK) continue; + if (register_module((void *) r_addr.hpa) != NULL) + num++; + } + } + // reset module_path.bc[] + for (i=0;i<6;i++) module_path.bc[i]=0xff; + + +#ifdef DBG_PDC_QUERY +// +// Let print_devices() dump everything which is registered. +// + h = devices[num_devices-1].reference; + + if (h) stype = h->name; + printk("Found %s at %d\n", stype, module_path.mod); +#endif + } + } + return num; +} + +static int +do_old_inventory(void) +{ + unsigned int bus_id; + long status; + int ok = 0; + + printk(" an older box...\n"); + + /* Here, we're going to check the model, and decide + if we should even bother trying. */ + + status = pdc_model_info(&model); + + bus_id = (model.hversion >> (4+7) ) &0x1f; + + /* Here, we're checking the HVERSION of the CPU. + We're only checking the 0th CPU, since it'll + be the same on an SMP box. */ + + switch (bus_id) { + case 0x4: /* 720, 730, 750, 735, 755 */ + case 0x6: /* 705, 710 */ + case 0x7: /* 715, 725 */ + case 0x8: /* 745, 747, 742 */ + case 0xA: /* 712 and similiar */ + case 0xC: /* 715/64, at least */ + + /* Do inventory using MEM_MAP */ + really_do_oldhw_inventory(); + ok = 1; + break; + default: /* Everything else */ + printk("This is a very very old machine, with a bus_id of 0x%x.\n",bus_id); + panic("This will probably never run Linux.\n"); + } + + return ok; +} + +#endif /* !__LP64__ */ + +void do_inventory(void){ + if((pdc_hpa_processor(&processor_hpa))<0){ + printk(KERN_INFO "Couldn't get the HPA of the processor.\n" ); + } + + printk("Searching for devices in PDC firmware... "); + printk("processor hpa 0x%lx\n", processor_hpa.hpa); + + if (!( + do_newer_workstation_inventory() +#ifdef __LP64__ + || do_pat_inventory() +#else /* __LP64__ */ + || do_old_inventory() +#endif /* __LP64__ */ + )) + { + panic("I can't get the hardware inventory on this machine"); + } + print_devices(NULL); +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/iosapic.c linux/arch/parisc/kernel/iosapic.c --- v2.4.0-test11/linux/arch/parisc/kernel/iosapic.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/iosapic.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,1100 @@ +/* +** I/O Sapic Driver - PCI interrupt line support +** +** (c) Copyright 1999 Grant Grundler +** (c) Copyright 1999 Hewlett-Packard Company +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** The I/O sapic driver manages the Interrupt Redirection Table which is +** the control logic to convert PCI line based interrupts into a Message +** Signaled Interrupt (aka Transaction Based Interrupt, TBI). +** +** Acronyms +** -------- +** HPA Hard Physical Address (aka MMIO address) +** IRQ Interrupt ReQuest. Implies Line based interrupt. +** IRT Interrupt Routing Table (provided by PAT firmware) +** IRdT Interrupt Redirection Table. IRQ line to TXN ADDR/DATA +** table which is implemented in I/O SAPIC. +** ISR Interrupt Service Routine. aka Interrupt handler. +** MSI Message Signaled Interrupt. PCI 2.2 functionality. +** aka Transaction Based Interrupt (or TBI). +** PA Precision Architecture. HP's RISC architecture. +** RISC Reduced Instruction Set Computer. +** +** +** What's a Message Signalled Interrupt? +** ------------------------------------- +** MSI is a write transaction which targets a processor and is similar +** to a processor write to memory or MMIO. MSIs can be generated by I/O +** devices as well as processors and require *architecture* to work. +** +** PA only supports MSI. So I/O subsystems must either natively generate +** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs +** (e.g. PCI and EISA). IA64 supports MSIs via a "local SAPIC" which +** acts on behalf of a processor. +** +** MSI allows any I/O device to interrupt any processor. This makes +** load balancing of the interrupt processing possible on an SMP platform. +** Interrupts are also ordered WRT to DMA data. It's possible on I/O +** coherent systems to completely eliminate PIO reads from the interrupt +** path. The device and driver must be designed and implemented to +** guarantee all DMA has been issued (issues about atomicity here) +** before the MSI is issued. I/O status can then safely be read from +** DMA'd data by the ISR. +** +** +** PA Firmware +** ----------- +** PA-RISC platforms have two fundementally different types of firmware. +** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register +** and BARs similar to a traditional PC BIOS. +** The newer "PAT" firmware supports PDC calls which return tables. +** PAT firmware only initializes PCI Console and Boot interface. +** With these tables, the OS can progam all other PCI devices. +** +** One such PAT PDC call returns the "Interrupt Routing Table" (IRT). +** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC +** input line. If the IRT is not available, this driver assumes +** INTERRUPT_LINE register has been programmed by firmware. The latter +** case also means online addition of PCI cards can NOT be supported +** even if HW support is present. +** +** All platforms with PAT firmware to date (Oct 1999) use one Interrupt +** Routing Table for the entire platform. +** +** Where's the iosapic? +** -------------------- +** I/O sapic is part of the "Core Electronics Complex". And on HP platforms +** it's integrated as part of the PCI bus adapter, "lba". So no bus walk +** will discover I/O Sapic. I/O Sapic driver learns about each device +** when lba driver advertises the presence of the I/O sapic by calling +** iosapic_register(). +** +** +** IRQ region notes +** ---------------- +** The data passed to iosapic_interrupt() is per IRQ line. +** Each IRQ line will get one txn_addr/data pair. Thus each IRQ region, +** will have several txn_addr/data pairs (up to 7 for current I/O SAPIC +** implementations). The IRQ region "sysdata" will NOT be directly passed +** to the interrupt handler like GSCtoPCI (dino.c). +** +** iosapic interrupt handler will NOT call do_irq_mask(). +** It doesn't need to read a bit mask to determine which IRQ line was pulled +** since it already knows based on vector_info passed to iosapic_interrupt(). +** +** One IRQ number represents both an IRQ line and a driver ISR. +** The I/O sapic driver can't manage shared IRQ lines because +** additional data besides the IRQ number must be passed via +** irq_region_ops. do_irq() and request_irq() must manage +** a sharing a bit in the mask. +** +** iosapic_interrupt() replaces do_irq_mask() and calls do_irq(). +** Which IRQ line was asserted is already known since each +** line has unique data associated with it. We could omit +** iosapic_interrupt() from the calling path if it did NOT need +** to write EOI. For unshared lines, it really doesn't. +** +** Unfortunately, can't optimize out EOI if IRQ line isn't "shared". +** N-class console "device" and some sort of heartbeat actually share +** one line though only one driver is registered......this was +** true for HP-UX at least. May not be true for parisc-linux. +** +** +** Overview of exported iosapic functions +** -------------------------------------- +** (caveat: code isn't finished yet - this is just the plan) +** +** iosapic_init: +** o initialize globals (lock, etc) +** o try to read IRT. Presence of IRT determines if this is +** a PAT platform or not. +** +** iosapic_register(): +** o create iosapic_info instance data structure +** o allocate vector_info array for this iosapic +** o initialize vector_info - read corresponding IRdT? +** +** iosapic_xlate_pin: (only called by fixup_irq for PAT platform) +** o intr_pin = read cfg (INTERRUPT_PIN); +** o if (device under PCI-PCI bridge) +** translate slot/pin +** +** iosapic_fixup_irq: +** o if PAT platform (IRT present) +** intr_pin = iosapic_xlate_pin(isi,pcidev): +** intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin) +** save IRT entry into vector_info later +** write cfg INTERRUPT_LINE (with intr_line)? +** else +** intr_line = pcidev->irq +** IRT pointer = NULL +** endif +** o locate vector_info (needs: isi, intr_line) +** o allocate processor "irq" and get txn_addr/data +** o request_irq(processor_irq, iosapic_interrupt, vector_info,...) +** o pcidev->irq = isi->isi_region...base + intr_line; +** +** iosapic_interrupt: +** o call do_irq(vector->isi->irq_region, vector->irq_line, regs) +** o assume level triggered and write EOI +** +** iosapic_enable_irq: +** o clear any pending IRQ on that line +** o enable IRdT - call enable_irq(vector[line]->processor_irq) +** o write EOI in case line is already asserted. +** +** iosapic_disable_irq: +** o disable IRdT - call disable_irq(vector[line]->processor_irq) +** +** FIXME: mask/unmask +*/ + + +/* FIXME: determine which include files are really needed */ +#include +#include +#include +#include /* pci cfg accessor functions */ +#include +#include +#include +#include /* irqaction */ +#include /* irq_region support */ + +#include /* get in-line asm for swab */ +#include +#include +#include +#include +#include +#include /* gsc_read/write functions */ + +#include +#include "./iosapic_private.h" + +#define MODULE_NAME "iosapic" + +/* "local" compile flags */ +#undef IOSAPIC_CALLBACK +#undef PCI_BRIDGE_FUNCS +#undef DEBUG_IOSAPIC +#undef DEBUG_IOSAPIC_IRT + + +#ifdef DEBUG_IOSAPIC +static char assert_buf[128]; + +static int +assert_failed (char *a, char *f, int l) +{ + sprintf(assert_buf, + "ASSERT(%s) failed!\nline %d in %s\n", + a, /* assertion text */ + l, /* line number */ + f); /* file name */ + panic(assert_buf); + return 0; +} + +#undef ASSERT +#define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); } + +#define DBG(x...) printk(x) + +#else /* DEBUG_IOSAPIC */ + +#define DBG(x...) +#define ASSERT(EX) + +#endif /* DEBUG_IOSAPIC */ + +#ifdef DEBUG_IOSAPIC_IRT +#define DBG_IRT(x...) printk(x) +#else +#define DBG_IRT(x...) +#endif + + +#define READ_U8(addr) gsc_readb(addr) +#define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr))) +#define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr))) +#define READ_REG16(addr) gsc_readw((u16 *) (addr)) +#define READ_REG32(addr) gsc_readl((u32 *) (addr)) +#define WRITE_U8(value, addr) gsc_writeb(value, addr) +#define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr)) +#define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr)) +#define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr)) +#define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr)) + + +#define IOSAPIC_REG_SELECT 0 +#define IOSAPIC_REG_WINDOW 0x10 +#define IOSAPIC_REG_EOI 0x40 + +#define IOSAPIC_REG_VERSION 0x1 + +#define IOSAPIC_IRDT_ENTRY(idx) (0x10+(idx)*2) +#define IOSAPIC_IRDT_ENTRY_HI(idx) (0x11+(idx)*2) + +/* +** FIXME: revisit which GFP flags we should really be using. +** GFP_KERNEL includes __GFP_WAIT flag and that may not +** be acceptable. Since this is boot time, we shouldn't have +** to wait ever and this code should (will?) never get called +** from the interrrupt context. +*/ +#define IOSAPIC_KALLOC(a_type, cnt) \ + (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL) +#define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr) + + +#define IOSAPIC_LOCK(lck) spin_lock_irqsave(lck, irqflags) +#define IOSAPIC_UNLOCK(lck) spin_unlock_irqrestore(lck, irqflags) + + +#define IOSAPIC_VERSION_MASK 0x000000ff +#define IOSAPIC_VERSION_SHIFT 0x0 +#define IOSAPIC_VERSION(ver) \ + (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT) + +#define IOSAPIC_MAX_ENTRY_MASK 0x00ff0000 + +#define IOSAPIC_MAX_ENTRY_SHIFT 0x10 +#define IOSAPIC_IRDT_MAX_ENTRY(ver) \ + (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT) + +/* bits in the "low" I/O Sapic IRdT entry */ +#define IOSAPIC_IRDT_ENABLE 0x10000 +#define IOSAPIC_IRDT_PO_LOW 0x02000 +#define IOSAPIC_IRDT_LEVEL_TRIG 0x08000 +#define IOSAPIC_IRDT_MODE_LPRI 0x00100 + +/* bits in the "high" I/O Sapic IRdT entry */ +#define IOSAPIC_IRDT_ID_EID_SHIFT 0x10 + + + +#define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr) + +#if IOSAPIC_CALLBACK +/* +** Shouldn't use callback since SAPIC doesn't have an officially assigned +** H or S version numbers. Slight long term risk the number chosen would +** collide with something else. +** But benefit is cleaner lba/sapic interface. +** Might be worth it but for just use direct calls for now. +** +** Entry below is copied from lba driver. +** Only thing different is hw_type. +*/ +static struct pa_iodc_driver iosapic_driver_for[] = { + {HPHW_OTHER, 0x782, 0, 0x0000A, 0, 0x00, + DRIVER_CHECK_HWTYPE + DRIVER_CHECK_HVERSION + DRIVER_CHECK_SVERSION, + "I/O Sapic", "",(void *) iosapic_callback}, + {0,0,0,0,0,0, + 0, + (char *) NULL,(char *) NULL,(void *) NULL} +}; +#endif /* IOSAPIO_CALLBACK */ + + +static struct iosapic_info *iosapic_list; +static spinlock_t iosapic_lock; +static int iosapic_count; + + +/* +** REVISIT: future platforms may have more than one IRT. +** If so, the following three fields form a structure which +** then be linked into a list. Names are chosen to make searching +** for them easy - not necessarily accurate (eg "cell"). +** +** Alternative: iosapic_info could point to the IRT it's in. +** iosapic_register() could search a list of IRT's. +*/ +static struct irt_entry *irt_cell; +static size_t irt_num_entry; + + + +/* +** iosapic_load_irt +** +** The "Get PCI INT Routing Table Size" option returns the number of +** entries in the PCI interrupt routing table for the cell specified +** in the cell_number argument. The cell number must be for a cell +** within the caller's protection domain. +** +** The "Get PCI INT Routing Table" option returns, for the cell +** specified in the cell_number argument, the PCI interrupt routing +** table in the caller allocated memory pointed to by mem_addr. +** We assume the IRT only contains entries for I/O SAPIC and +** calculate the size based on the size of I/O sapic entries. +** +** The PCI interrupt routing table entry format is derived from the +** IA64 SAL Specification 2.4. The PCI interrupt routing table defines +** the routing of PCI interrupt signals between the PCI device output +** "pins" and the IO SAPICs' input "lines" (including core I/O PCI +** devices). This table does NOT include information for devices/slots +** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec. +** for the architected method of routing of IRQ's behind PPB's. +*/ + + +static int __init /* return number of entries as success/fail flag */ +iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt) +{ + struct pdc_pat_io_num pdc_io_num; /* PAT PDC return block */ + long status; /* PDC return value status */ + struct irt_entry *table = NULL; /* start of interrupt routing tbl */ + unsigned long num_entries = 0UL; + + ASSERT(NULL != irt); + /* FIXME ASSERT(((&pdc_io_num) & (0x3f)) == 0); enforce 32-byte alignment */ + + /* Try PAT_PDC to get interrupt routing table size */ + DBG(KERN_DEBUG "calling get_irt_size\n"); + status = pdc_pat_get_irt_size( &pdc_io_num, cell_num); + DBG(KERN_DEBUG "get_irt_size: %ld\n", status); + + switch(status) { + + case PDC_RET_OK: /* PAT box. Proceed to get the IRT */ + + /* save the number of entries in the table */ + num_entries = pdc_io_num.num; + ASSERT(0UL != num_entries); + + /* + ** allocate memory for interrupt routing table + ** This interface isn't really right. We are assuming + ** the contents of the table are exclusively + ** for I/O sapic devices. + */ + table = IOSAPIC_KALLOC(struct irt_entry, num_entries); + if (table == NULL) { + printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n"); + return 0; + } + + /* get PCI INT routing table */ + status = pdc_pat_get_irt( (void *) table, cell_num); + DBG(KERN_DEBUG "pdc_pat_get_irt: %ld\n", status); + ASSERT(status == PDC_RET_OK); + break; + + case PDC_RET_NE_PROC: /* Not a PAT platform. Try PDC_PCI extensions */ + /* + ** C3000/J5000 (and similar) platforms with "legacy" PDC + ** will return exactly one IRT. + ** So if we have one, don't need to get it again. + */ + if (NULL != irt_cell) + break; + + status = pdc_pci_irt_size( (void *)&pdc_io_num, + /* elroy HPA (really a NOP) */ 0); + DBG(KERN_WARNING "pdc_pci_irt_size: %ld\n", status); + + if (PDC_RET_OK != status) { + /* Not a "legacy" system with I/O SAPIC either */ + return 0; + } + + num_entries = pdc_io_num.num; + ASSERT(0UL != num_entries); + + table = IOSAPIC_KALLOC(struct irt_entry, num_entries); + if (table == NULL) { + printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n"); + return 0; + } + + status = pdc_pci_irt( (void *) &pdc_io_num, + (void *) NULL, /* Elroy HPA - not used */ + (void *) table); + + ASSERT(PDC_RET_OK == status); + break; + + default: + printk(KERN_WARNING MODULE_NAME ": PDC_PAT_IO call failed with %ld\n", status); + break; + } + + /* return interrupt table address */ + *irt = table; + + +#ifdef DEBUG_IOSAPIC_IRT + { + struct irt_entry *p = table; + int i; + + printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num); + printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n", + table, + num_entries, + (int) sizeof(struct irt_entry)); + + for (i = 0 ; i < num_entries ; i++, p++) + { + printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n", + p->entry_type, p->entry_length, p->interrupt_type, + p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id, + p->src_seg_id, p->dest_iosapic_intin, + ((u32 *) p)[2], + ((u32 *) p)[3] + ); + } + } +#endif /* DEBUG_IOSAPIC_IRT */ + + return num_entries; +} + + + +void __init +iosapic_init(void) +{ + /* init global data */ + iosapic_lock = SPIN_LOCK_UNLOCKED; + iosapic_list = (struct iosapic_info *) NULL; + iosapic_count = 0; + + DBG("iosapic_init()\n"); + + /* + ** get IRT for this cell. + */ + irt_num_entry = iosapic_load_irt(0L, &irt_cell); + if (0 == irt_num_entry) + irt_cell = NULL; /* old PDC w/o iosapic */ + +#ifdef IOSAPIC_CALLBACK + /* + ** When new I/O SAPICs are discovered, this callback + ** will get invoked. Implies lba driver will register + ** I/O Sapic as a device it "discovered" with faked + ** IODC data. + */ + register_driver(iosapic_driver_for); +#endif /* IOSAPIC_CALLBACK */ +} + + +/* +** Return the IRT entry in case we need to look something else up. +*/ +static struct irt_entry * +irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin) +{ + struct irt_entry *i = irt_cell; + int cnt; /* track how many entries we've looked at */ + u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1); + + DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin); + + for (cnt=0; cnt < irt_num_entry; cnt++, i++) { + + /* + ** Validate: entry_type, entry_length, interrupt_type + ** + ** Difference between validate vs compare is the former + ** should print debug info and is not expected to "fail" + ** on current platforms. + */ + if (i->entry_type != IRT_IOSAPIC_TYPE) { + DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type); + continue; + } + + if (i->entry_length != IRT_IOSAPIC_LENGTH) { + DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d length %d\n", i, cnt, i->entry_length); + continue; + } + + if (i->interrupt_type != IRT_VECTORED_INTR) { + DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d interrupt_type %d\n", i, cnt, i->interrupt_type); + continue; + } + + /* + ** Compare: dest_iosapic_addr, src_bus_irq_devno + */ + if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa)) + continue; + + if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno) + continue; + + /* + ** Ignore: src_bus_id and rc_seg_id correlate with + ** iosapic_info->isi_hpa on HP platforms. + ** If needed, pass in "PFA" (aka config space addr) + ** instead of slot. + */ + + /* Found it! */ + return i; + } + + printk(KERN_WARNING MODULE_NAME ": 0x%p : no IRT entry for slot %d, pin %d\n", + isi->isi_hpa, slot, intr_pin); + return NULL; +} + + +/* +** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges. +** Legacy PDC already does this translation for us and stores it in INTR_LINE. +** +** PAT PDC needs to basically do what legacy PDC does: +** o read PIN +** o adjust PIN in case device is "behind" a PPB +** (eg 4-port 100BT and SCSI/LAN "Combo Card") +** o convert slot/pin to I/O SAPIC input line. +** +** HP platforms only support: +** o one level of skewing for any number of PPBs +** o only support PCI-PCI Bridges. +*/ +static struct irt_entry * +iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) +{ + u8 intr_pin, intr_slot; + + (void) pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin); + + DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n", PCI_SLOT(pcidev->devfn), intr_pin); + + if (0 == intr_pin) + { + /* + ** The device does NOT support/use IRQ lines. + */ + return NULL; + } + + /* Check if pcidev behind a PPB */ + if (NULL != pcidev->bus->self) + { + /* Convert pcidev INTR_PIN into something we + ** can lookup in the IRT. + */ +#ifdef PCI_BRIDGE_FUNCS + /* + ** Proposal #1: + ** + ** call implementation specific translation function + ** This is architecturally "cleaner". HP-UX doesn't + ** support other secondary bus types (eg. E/ISA) directly. + ** May be needed for other processor (eg IA64) architectures + ** or by some ambitous soul who wants to watch TV. + */ + if (pci_bridge_funcs->xlate_intr_line) { + intr_pin = (*pci_bridge_funcs->xlate_intr_line)(pcidev); + } +#else /* PCI_BRIDGE_FUNCS */ + struct pci_bus *p = pcidev->bus; + /* + ** Proposal #2: + ** The "pin" is skewed ((pin + dev - 1) % 4). + ** + ** This isn't very clean since I/O SAPIC must assume: + ** - all platforms only have PCI busses. + ** - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA) + ** - IRQ routing is only skewed once regardless of + ** the number of PPB's between iosapic and device. + ** (Bit3 expansion chassis follows this rule) + ** + ** Advantage is it's really easy to implement. + */ + intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4; + intr_pin++; /* convert back to INTA-D (1-4) */ +#endif /* PCI_BRIDGE_FUNCS */ + + /* + ** Locate the host slot the PPB nearest the Host bus + ** adapter. + */ + while (NULL != p->parent->self) + p = p->parent; + + intr_slot = PCI_SLOT(p->self->devfn); + } else { + intr_slot = PCI_SLOT(pcidev->devfn); + } + DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n", + pcidev->bus->secondary, intr_slot, intr_pin); + + return irt_find_irqline(isi, intr_slot, intr_pin); +} + + +static void +iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs) +{ + struct vector_info *vi = (struct vector_info *)dev_id; + extern void do_irq(struct irqaction *a, int i, struct pt_regs *p); + int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline; + + DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", irq, vi->vi_irqline, + vi->vi_eoi_addr); + +/* FIXME: Need to mask/unmask? processor IRQ is already masked... */ + do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs); + + /* + ** PCI only supports level triggered in order to share IRQ lines. + ** I/O SAPIC must always issue EOI. + */ + IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data); +} + + +int +iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev) +{ + struct iosapic_info *isi = (struct iosapic_info *)isi_obj; + struct irt_entry *irte = NULL; /* only used if PAT PDC */ + struct vector_info *vi; + int isi_line; /* line used by device */ + int tmp; + + if (NULL == isi) { + printk(KERN_WARNING MODULE_NAME ": 0x%p hpa not registered\n", isi->isi_hpa); + return(-1); + } + + /* lookup IRT entry for isi/slot/pin set */ + irte = iosapic_xlate_pin(isi, pcidev); + if (NULL == irte) { + return(-1); + } + DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n", + irte, + irte->entry_type, + irte->entry_length, + irte->polarity_trigger, + irte->src_bus_irq_devno, + irte->src_bus_id, + irte->src_seg_id, + irte->dest_iosapic_intin, + (u32) irte->dest_iosapic_addr); + isi_line = irte->dest_iosapic_intin; + + /* get vector info for this input line */ + ASSERT(NULL != isi->isi_vector); + vi = &(isi->isi_vector[isi_line]); + DBG_IRT("iosapic_fixup_irq: line %d vi 0x%p\n", isi_line, vi); + vi->vi_irte = irte; + + /* Allocate processor IRQ */ + vi->vi_txn_irq = txn_alloc_irq(); + +/* XXX/FIXME The txn_alloc_irq() code and related code should be moved +** to enable_irq(). That way we only allocate processor IRQ bits +** for devices that actually have drivers claiming them. +** Right now we assign an IRQ to every PCI device present regardless +** of whether it's used or not. +*/ + if (vi->vi_txn_irq < 0) + panic("I/O sapic: couldn't get TXN IRQ\n"); + + /* enable_irq() will use txn_* to program IRdT */ + vi->vi_txn_addr = txn_alloc_addr(vi->vi_txn_irq); + vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8); + ASSERT(vi->vi_txn_data < 256); /* matches 8 above */ + + tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, "iosapic", vi); + ASSERT(tmp == 0); + + vi->vi_eoi_addr = ((void *) isi->isi_hpa) + IOSAPIC_REG_EOI; + vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline); + + ASSERT(NULL != isi->isi_region); + /* + ** pcidev->irq still needs to be virtualized. + */ + pcidev->irq = isi->isi_region->data.irqbase + isi_line; + + DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", PCI_SLOT(pcidev->devfn), + PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, pcidev->irq); + + return(pcidev->irq); +} + + +static void +iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1) +{ + struct iosapic_info *isp = vi->vi_ios; + u8 idx = vi->vi_irqline; + + /* point the window register to the lower word */ + WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT); + *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW); + + /* point the window register to the higher word */ + WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT); + *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW); +} + + +static void +iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1) +{ + struct iosapic_info *isp = vi->vi_ios; + + ASSERT(NULL != isp); + ASSERT(NULL != isp->isi_hpa); + DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p 0x%x 0x%x\n", + vi->vi_irqline, + isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW, + dp0, dp1); + + /* point the window register to the lower word */ + WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT); + WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW); + + /* Read the window register to flush the writes down to HW */ + dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW); + + /* point the window register to the higher word */ + WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->vi_irqline), isp->isi_hpa+IOSAPIC_REG_SELECT); + WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW); + + /* Read the window register to flush the writes down to HW */ + dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW); +} + + +/* +** set_irt prepares the data (dp0, dp1) according to the vector_info +** and target cpu (id_eid). dp0/dp1 are then used to program I/O SAPIC +** IRdT for the given "vector" (aka IRQ line). +*/ +static void +iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1) +{ + u32 mode = 0; + struct irt_entry *p = vi->vi_irte; + ASSERT(NULL != vi->vi_irte); + + if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO) + mode |= IOSAPIC_IRDT_PO_LOW; + + if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG) + mode |= IOSAPIC_IRDT_LEVEL_TRIG; + + /* + ** IA64 REVISIT + ** PA doesn't support EXTINT or LPRIO bits. + */ + + ASSERT(vi->vi_txn_data); + *dp0 = mode | (u32) vi->vi_txn_data; + + /* + ** Extracting id_eid isn't a real clean way of getting it. + ** But the encoding is the same for both PA and IA64 platforms. + */ +#ifdef __LP64__ + if (pdc_pat) { + /* + ** PAT PDC just hands it to us "right". + ** vi_txn_addr comes from cpu_data[x].txn_addr. + */ + *dp1 = (u32) (vi->vi_txn_addr); + } else +#endif + { + /* + ** eg if base_addr == 0xfffa0000), + ** we want to get 0xa0ff0000. + ** + ** eid 0x0ff00000 -> 0x00ff0000 + ** id 0x000ff000 -> 0xff000000 + */ + *dp1 = (((u32)vi->vi_txn_addr & 0x0ff00000) >> 4) | + (((u32)vi->vi_txn_addr & 0x000ff000) << 12); + } + DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1); +} + + +static void +iosapic_disable_irq(void *irq_dev, int irq) +{ + ulong irqflags; + struct vector_info *vi = &(((struct vector_info *) irq_dev)[irq]); + u32 d0, d1; + + ASSERT(NULL != vi); + + IOSAPIC_LOCK(&iosapic_lock); + +#ifdef REVISIT_DESIGN_ISSUE +/* +** XXX/FIXME + +disable_irq()/enable_irq(): drawback of using IRQ as a "handle" + +Current disable_irq interface only allows the irq_region support routines +to manage sharing of "irq" objects. The problem is the disable_irq() +interface specifies which IRQ line needs to be disabled but does not +identify the particular ISR which needs to be disabled. IO sapic +(and similar code in Dino) can only support one handler per IRQ +since they don't further encode the meaning of the IRQ number. +irq_region support has to hide it's implementation of "shared IRQ" +behind a function call. + +Encoding the IRQ would be possible by I/O SAPIC but makes life really +complicated for the IRQ handler and not help performance. + +Need more info on how Linux supports shared IRQ lines on a PC. +*/ +#endif /* REVISIT_DESIGN_ISSUE */ + + iosapic_rd_irt_entry(vi, &d0, &d1); + d0 |= IOSAPIC_IRDT_ENABLE; + iosapic_wr_irt_entry(vi, d0, d1); + + IOSAPIC_UNLOCK(&iosapic_lock); + + /* disable ISR for parent */ + disable_irq(vi->vi_txn_irq); +} + + +static void +iosapic_enable_irq(void *dev, int irq) +{ + struct vector_info *vi = &(((struct vector_info *) dev)[irq]); + u32 d0, d1; + + ASSERT(NULL != vi); + ASSERT(NULL != vi->vi_irte); + + /* data is initialized by fixup_irq */ + ASSERT(0 < vi->vi_txn_irq); + ASSERT(0UL != vi->vi_txn_addr); + ASSERT(0UL != vi->vi_txn_data); + + iosapic_set_irt_data(vi, &d0, &d1); + iosapic_wr_irt_entry(vi, d0, d1); + + +#ifdef DEBUG_IOSAPIC_IRT +{ +u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL); +printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr); +while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++)); +printk("\n"); +} + +printk("iosapic_enable_irq(): sel "); +{ + struct iosapic_info *isp = vi->vi_ios; + + for (d0=0x10; d0<0x1e; d0++) { + /* point the window register to the lower word */ + WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT); + + /* read the word */ + d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW); + printk(" %x", d1); + } +} +printk("\n"); +#endif + + /* + ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ. + ** PCI supports level triggered in order to share IRQ lines. + ** + ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is + ** asserted. + */ + IOSAPIC_EOI(vi->vi_eoi_addr, vi->vi_eoi_data); +} + + +static void +iosapic_mask_irq(void *dev, int irq) +{ + BUG(); +} + + +static void +iosapic_unmask_irq(void *dev, int irq) +{ + BUG(); +} + + +static struct irq_region_ops iosapic_irq_ops = { + iosapic_disable_irq, + iosapic_enable_irq, + iosapic_mask_irq, + iosapic_unmask_irq +}; + + +/* +** squirrel away the I/O Sapic Version +*/ +static unsigned int +iosapic_rd_version(struct iosapic_info *isi) +{ + ASSERT(isi); + ASSERT(isi->isi_hpa); + + /* point window to the version register */ + WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT); + + /* now read the version register */ + return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW)); +} + + +#ifndef IOSAPIC_CALLBACK +/* +** iosapic_register() is the alternative to iosapic_driver_for(). +** (Only one or the other should be implemented.) +*/ + +/* +** iosapic_register() is called by "drivers" with an integrated I/O SAPIC. +** Caller must be certain they have an I/O SAPIC and know it's MMIO address. +** +** o allocate iosapic_info and add it to the list +** o read iosapic version and squirrel that away +** o read size of IRdT. +** o allocate and initialize isi_vector[] +** o allocate isi_region (registers region handlers) +*/ +void * +iosapic_register(void *hpa) +{ + struct iosapic_info *isi = NULL; + struct irt_entry *irte = irt_cell; + struct vector_info *vip; + int cnt; /* track how many entries we've looked at */ + + /* + ** Astro based platforms can't support PCI OLARD if they + ** implement the legacy PDC (not PAT). Though Legacy PDC + ** supports an IRT, LBA's with no device under them + ** are *not* listed in the IRT. + ** Search the IRT and ignore iosapic's which aren't + ** in the IRT. + */ + ASSERT(NULL != irte); /* always have built-in devices */ + for (cnt=0; cnt < irt_num_entry; cnt++, irte++) { + ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type); + /* + ** We need sign extension of the hpa on 32-bit kernels. + ** The address in the IRT is *always* 64 bit and really + ** is an unsigned quantity (like all physical addresses). + */ + if (irte->dest_iosapic_addr == (s64) ((long) hpa)) + break; + } + + if (cnt >= irt_num_entry) + return (NULL); + + if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) { + BUG(); + return (NULL); + } + + memset(isi, 0, sizeof(struct iosapic_info)); + + isi->isi_hpa = (unsigned char *) hpa; + isi->isi_version = iosapic_rd_version(isi); + isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1; + + vip = isi->isi_vector = + IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors); + + if (vip == NULL) { + IOSAPIC_FREE(isi, struct iosapic_info, 1); + return (NULL); + } + + memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors); + + /* + ** Initialize vector array + */ + for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) { + vip->vi_irqline = (unsigned char) cnt; + vip->vi_ios = isi; + } + + isi->isi_region = alloc_irq_region(isi->isi_num_vectors, + &iosapic_irq_ops, IRQ_REG_DIS|IRQ_REG_MASK, + "I/O Sapic", (void *) isi->isi_vector); + + ASSERT(NULL != isi->isi_region); + return ((void *) isi); +} +#endif /* !IOSAPIC_CALLBACK */ + + + +#ifdef DEBUG_IOSAPIC + +static void +iosapic_prt_irt(void *irt, long num_entry) +{ + unsigned int i, *irp = (unsigned int *) irt; + + ASSERT(NULL != irt); + + printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry); + + for (i=0; ivi_irqline, vi); + printk(KERN_DEBUG "\t\tvi_status: %.4x\n", vi->vi_status); + printk(KERN_DEBUG "\t\tvi_txn_irq: %d\n", vi->vi_txn_irq); + printk(KERN_DEBUG "\t\tvi_txn_addr: %lx\n", vi->vi_txn_addr); + printk(KERN_DEBUG "\t\tvi_txn_data: %lx\n", vi->vi_txn_data); + printk(KERN_DEBUG "\t\tvi_eoi_addr: %p\n", vi->vi_eoi_addr); + printk(KERN_DEBUG "\t\tvi_eoi_data: %x\n", vi->vi_eoi_data); +} + + +static void +iosapic_prt_isi(struct iosapic_info *isi) +{ + ASSERT(NULL != isi); + printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi); + printk(KERN_DEBUG "\t\tisi_hpa: %p\n", isi->isi_hpa); + printk(KERN_DEBUG "\t\tisi_satus: %x\n", isi->isi_status); + printk(KERN_DEBUG "\t\tisi_version: %x\n", isi->isi_version); + printk(KERN_DEBUG "\t\tisi_vector: %p\n", isi->isi_vector); +} +#endif /* DEBUG_IOSAPIC */ diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/iosapic_private.h linux/arch/parisc/kernel/iosapic_private.h --- v2.4.0-test11/linux/arch/parisc/kernel/iosapic_private.h Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/iosapic_private.h Tue Dec 5 12:29:39 2000 @@ -0,0 +1,165 @@ +/* +** This file is private to iosapic driver. +** If stuff needs to be used by another driver, move it to a common file. +** +** WARNING: fields most data structures here are ordered to make sure +** they pack nicely for 64-bit compilation. (ie sizeof(long) == 8) +*/ + + +/* +** Interrupt Routing Stuff +** ----------------------- +** The interrupt routing table consists of entries derived from +** MP Specification Draft 1.5. There is one interrupt routing +** table per cell. N- and L-class consist of a single cell. +*/ +struct irt_entry { + + /* Entry Type 139 identifies an I/O SAPIC interrupt entry */ + u8 entry_type; + + /* Entry Length 16 indicates entry is 16 bytes long */ + u8 entry_length; + + /* + ** Interrupt Type of 0 indicates a vectored interrupt, + ** all other values are reserved + */ + u8 interrupt_type; + + /* + ** PO and EL + ** Polarity of SAPIC I/O input signals: + ** 00 = Reserved + ** 01 = Active high + ** 10 = Reserved + ** 11 = Active low + ** Trigger mode of SAPIC I/O input signals: + ** 00 = Reserved + ** 01 = Edge-triggered + ** 10 = Reserved + ** 11 = Level-triggered + */ + u8 polarity_trigger; + + /* + ** IRQ and DEVNO + ** irq identifies PCI interrupt signal where + ** 0x0 corresponds to INT_A#, + ** 0x1 corresponds to INT_B#, + ** 0x2 corresponds to INT_C# + ** 0x3 corresponds to INT_D# + ** PCI device number where interrupt originates + */ + u8 src_bus_irq_devno; + + /* Source Bus ID identifies the bus where interrupt signal comes from */ + u8 src_bus_id; + + /* + ** Segment ID is unique across a protection domain and + ** identifies a segment of PCI buses (reserved in + ** MP Specification Draft 1.5) + */ + u8 src_seg_id; + + /* + ** Destination I/O SAPIC INTIN# identifies the INTIN n pin + ** to which the signal is connected + */ + u8 dest_iosapic_intin; + + /* + ** Destination I/O SAPIC Address identifies the I/O SAPIC + ** to which the signal is connected + */ + u64 dest_iosapic_addr; +}; + +#define IRT_IOSAPIC_TYPE 139 +#define IRT_IOSAPIC_LENGTH 16 + +#define IRT_VECTORED_INTR 0 + +#define IRT_PO_MASK 0x3 +#define IRT_ACTIVE_HI 1 +#define IRT_ACTIVE_LO 3 + +#define IRT_EL_MASK 0x3 +#define IRT_EL_SHIFT 2 +#define IRT_EDGE_TRIG 1 +#define IRT_LEVEL_TRIG 3 + +#define IRT_IRQ_MASK 0x3 +#define IRT_DEV_MASK 0x1f +#define IRT_DEV_SHIFT 2 + +#define IRT_IRQ_DEVNO_MASK ((IRT_DEV_MASK << IRT_DEV_SHIFT) | IRT_IRQ_MASK) + +#ifdef SUPPORT_MULTI_CELL +struct iosapic_irt { + struct iosapic_irt *irt_next; /* next routing table */ + struct irt_entry *irt_base; /* intr routing table address */ + size_t irte_count; /* number of entries in the table */ + size_t irte_size; /* size (bytes) of each entry */ +}; +#endif + +struct vector_info { + struct iosapic_info *vi_ios; /* I/O SAPIC this vector is on */ + struct irt_entry *vi_irte; /* IRT entry */ + u32 *vi_eoi_addr; /* precalculate EOI reg address */ + u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */ + u8 vi_status; /* status/flags */ + u8 vi_irqline; /* INTINn(IRQ) */ + int vi_txn_irq; /* virtual IRQ number for processor */ + ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */ + ulong vi_txn_data; /* IA64: vector PA: EIR bit */ +}; + + +struct iosapic_info { + struct iosapic_info *isi_next; /* list of I/O SAPIC */ + volatile void *isi_hpa; /* physical base address */ + struct irq_region *isi_region; /* each I/O SAPIC is one region */ + struct vector_info *isi_vector; /* IRdT (IRQ line) array */ + int isi_num_vectors; /* size of IRdT array */ + int isi_status; /* status/flags */ + unsigned int isi_version; /* DEBUG: data fr version reg */ +}; + + + +#ifdef __IA64__ +/* +** PA risc does NOT have any local sapics. IA64 does. +** PIB (Processor Interrupt Block) is handled by Astro or Dew (Stretch CEC). +** +** PA: Get id_eid from IRT and hardcode PIB to 0xfeeNNNN0 +** Emulate the data on PAT platforms. +*/ +struct local_sapic_info { + struct local_sapic_info *lsi_next; /* point to next CPU info */ + int *lsi_cpu_id; /* point to logical CPU id */ + unsigned long *lsi_id_eid; /* point to IA-64 CPU id */ + int *lsi_status; /* point to CPU status */ + void *lsi_private; /* point to special info */ +}; + +/* +** "root" data structure which ties everything together. +** Should always be able to start with sapic_root and locate +** the desired information. +*/ +struct sapic_info { + struct sapic_info *si_next; /* info is per cell */ + int si_cellid; /* cell id */ + unsigned int si_status; /* status */ + char *si_pib_base; /* intr blk base address */ + local_sapic_info_t *si_local_info; + io_sapic_info_t *si_io_info; + extint_info_t *si_extint_info;/* External Intr info */ +}; +#endif + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/irq.c linux/arch/parisc/kernel/irq.c --- v2.4.0-test11/linux/arch/parisc/kernel/irq.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/irq.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,538 @@ +/* $Id: irq.c,v 1.8 2000/02/08 02:01:17 grundler Exp $ + * + * Code to handle x86 style IRQs plus some generic interrupt stuff. + * + * This is not in any way SMP-clean. + * + * Copyright (C) 1992 Linus Torvalds + * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle + * Copyright (C) 1999 SuSE GmbH (Author: Philipp Rumpf, prumpf@tux.org) + * Copyright (C) 2000 Hewlett Packard Corp (Co-Author: Grant Grundler, grundler@cup.hp.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef DEBUG_IRQ + +extern void timer_interrupt(int, void *, struct pt_regs *); +extern void ipi_interrupt(int, void *, struct pt_regs *); + +#ifdef DEBUG_IRQ +#define DBG_IRQ(x...) printk(x) +#else /* DEBUG_IRQ */ +#define DBG_IRQ(x...) +#endif /* DEBUG_IRQ */ + +#define EIEM_MASK(irq) (1L<<(MAX_CPU_IRQ-IRQ_OFFSET(irq))) +#define CLEAR_EIEM_BIT(irq) set_eiem(get_eiem() & ~EIEM_MASK(irq)) +#define SET_EIEM_BIT(irq) set_eiem(get_eiem() | EIEM_MASK(irq)) + +static void disable_cpu_irq(void *unused, int irq) +{ + CLEAR_EIEM_BIT(irq); +} + +static void enable_cpu_irq(void *unused, int irq) +{ + unsigned long mask = EIEM_MASK(irq); + + mtctl(mask, 23); + SET_EIEM_BIT(irq); +} + +static struct irqaction cpu_irq_actions[IRQ_PER_REGION] = { + [IRQ_OFFSET(TIMER_IRQ)] { timer_interrupt, 0, 0, "timer", NULL, NULL }, + [IRQ_OFFSET(IPI_IRQ)] { ipi_interrupt, 0, 0, "IPI", NULL, NULL }, +}; + +struct irq_region cpu_irq_region = { + { disable_cpu_irq, enable_cpu_irq, NULL, NULL }, + { &cpu_data[0], "PA-PIC", IRQ_REG_MASK|IRQ_REG_DIS, IRQ_FROM_REGION(CPU_IRQ_REGION)}, + cpu_irq_actions +}; + +struct irq_region *irq_region[NR_IRQ_REGS] = { + [ 0 ] NULL, /* abuse will data page fault (aka code 15) */ + [ CPU_IRQ_REGION ] &cpu_irq_region, +}; + + + +/* we special-case the real IRQs here, which feels right given the relatively + * high cost of indirect calls. If anyone is bored enough to benchmark this + * and find out whether I am right, feel free to. prumpf */ + +static inline void mask_irq(int irq) +{ + struct irq_region *region; + +#ifdef DEBUG_IRQ + if (irq != TIMER_IRQ) +#endif + DBG_IRQ("mask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + + if(IRQ_REGION(irq) != CPU_IRQ_REGION) { + region = irq_region[IRQ_REGION(irq)]; + if(region->data.flags & IRQ_REG_MASK) + region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq)); + } else { + CLEAR_EIEM_BIT(irq); + } +} + +static inline void unmask_irq(int irq) +{ + struct irq_region *region; + +#ifdef DEBUG_IRQ + if (irq != TIMER_IRQ) +#endif + DBG_IRQ("unmask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + + if(IRQ_REGION(irq) != CPU_IRQ_REGION) { + region = irq_region[IRQ_REGION(irq)]; + if(region->data.flags & IRQ_REG_MASK) + region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq)); + } else { + SET_EIEM_BIT(irq); + } +} + +void disable_irq(int irq) +{ + struct irq_region *region; + +#ifdef DEBUG_IRQ + if (irq != TIMER_IRQ) +#endif + DBG_IRQ("disable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + region = irq_region[IRQ_REGION(irq)]; + + if(region->data.flags & IRQ_REG_DIS) + region->ops.disable_irq(region->data.dev, IRQ_OFFSET(irq)); + else + BUG(); +} + +void enable_irq(int irq) +{ + struct irq_region *region; + +#ifdef DEBUG_IRQ + if (irq != TIMER_IRQ) +#endif + DBG_IRQ("enable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + region = irq_region[IRQ_REGION(irq)]; + + if(region->data.flags & IRQ_REG_DIS) + region->ops.enable_irq(region->data.dev, IRQ_OFFSET(irq)); + else + BUG(); +} + +int get_irq_list(char *buf) +{ +#ifdef CONFIG_PROC_FS + char *p = buf; + int i, j; + int regnr, irq_no; + struct irq_region *region; + struct irqaction *action, *mainaction; + + p += sprintf(p, " "); + for (j=0; jaction) + continue; + + mainaction = region->action; + + for (i = 0; i <= MAX_CPU_IRQ; i++) { + action = mainaction++; + if (!action || !action->name) + continue; + + irq_no = IRQ_FROM_REGION(regnr) + i; + + p += sprintf(p, "%3d: ", irq_no); +#ifndef CONFIG_SMP + p += sprintf(p, "%10u ", kstat_irqs(irq_no)); +#else + for (j = 0; j < smp_num_cpus; j++) + p += sprintf(p, "%10u ", + kstat.irqs[cpu_logical_map(j)][irq_no]); +#endif + p += sprintf(p, " %14s", + region->data.name ? region->data.name : "N/A"); + p += sprintf(p, " %s", action->name); + + for (action=action->next; action; action = action->next) + p += sprintf(p, ", %s", action->name); + *p++ = '\n'; + } + } + + p += sprintf(p, "\n"); +#if CONFIG_SMP + p += sprintf(p, "LOC: "); + for (j = 0; j < smp_num_cpus; j++) + p += sprintf(p, "%10u ", + apic_timer_irqs[cpu_logical_map(j)]); + p += sprintf(p, "\n"); +#endif + + return p - buf; + +#else /* CONFIG_PROC_FS */ + + return 0; + +#endif /* CONFIG_PROC_FS */ +} + + + +/* +** The following form a "set": Virtual IRQ, Transaction Address, Trans Data. +** Respectively, these map to IRQ region+EIRR, Processor HPA, EIRR bit. +** +** To use txn_XXX() interfaces, get a Virtual IRQ first. +** Then use that to get the Transaction address and data. +*/ + +int +txn_alloc_irq(void) +{ + int irq; + + /* never return irq 0 cause that's the interval timer */ + for(irq=1; irq<=MAX_CPU_IRQ; irq++) { + if(cpu_irq_region.action[irq].handler == NULL) { + return (IRQ_FROM_REGION(CPU_IRQ_REGION) + irq); + } + } + + /* unlikely, but be prepared */ + return -1; +} + +int +txn_claim_irq(int irq) +{ + if (irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)].handler ==NULL) + { + return irq; + } + + /* unlikely, but be prepared */ + return -1; +} + +unsigned long +txn_alloc_addr(int virt_irq) +{ + struct cpuinfo_parisc *dev = (struct cpuinfo_parisc *) (irq_region[IRQ_REGION(virt_irq)]->data.dev); + + if (0==dev) { + printk(KERN_ERR "txn_alloc_addr(0x%x): CPU IRQ region? dev %p\n", + virt_irq,dev); + return(0UL); + } + return (dev->txn_addr); +} + + +/* +** The alloc process needs to accept a parameter to accomodate limitations +** of the HW/SW which use these bits: +** Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register) +** V-class (EPIC): 6 bits +** N/L-class/A500: 8 bits (iosapic) +** PCI 2.2 MSI: 16 bits (I think) +** Existing PCI devices: 32-bits (NCR c720/ATM/GigE/HyperFabric) +** +** On the service provider side: +** o PA 1.1 (and PA2.0 narrow mode) 5-bits (width of EIR register) +** o PA 2.0 wide mode 6-bits (per processor) +** o IA64 8-bits (0-256 total) +** +** So a Legacy PA I/O device on a PA 2.0 box can't use all +** the bits supported by the processor...and the N/L-class +** I/O subsystem supports more bits than PA2.0 has. The first +** case is the problem. +*/ +unsigned int +txn_alloc_data(int virt_irq, unsigned int bits_wide) +{ + /* XXX FIXME : bits_wide indicates how wide the transaction + ** data is allowed to be...we may need a different virt_irq + ** if this one won't work. Another reason to index virtual + ** irq's into a table which can manage CPU/IRQ bit seperately. + */ + if (IRQ_OFFSET(virt_irq) > (1 << (bits_wide -1))) + { + panic("Sorry -- didn't allocate valid IRQ for this device\n"); + } + + return(IRQ_OFFSET(virt_irq)); +} + + +/* FIXME: SMP, flags, bottom halves, rest */ +void do_irq(struct irqaction *action, int irq, struct pt_regs * regs) +{ + int cpu = smp_processor_id(); + + irq_enter(cpu, irq); + +#ifdef DEBUG_IRQ + if (irq != TIMER_IRQ) +#endif + DBG_IRQ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)); + if (action->handler == NULL) + printk(KERN_ERR "No handler for interrupt %d !\n", irq); + + for(; action && action->handler; action = action->next) { + action->handler(irq, action->dev_id, regs); + } + + irq_exit(cpu, irq); + + /* don't need to care about unmasking and stuff */ + do_softirq(); +} + +void do_irq_mask(unsigned long mask, struct irq_region *region, struct pt_regs *regs) +{ + unsigned long bit; + int irq; + int cpu = smp_processor_id(); + +#ifdef DEBUG_IRQ + if (mask != (1L << MAX_CPU_IRQ)) + printk("do_irq_mask %08lx %p %p\n", mask, region, regs); +#endif + + for(bit=(1L<>=1, irq++) { + int irq_num; + if(!(bit&mask)) + continue; + + irq_num = region->data.irqbase + irq; + + ++kstat.irqs[cpu][IRQ_FROM_REGION(CPU_IRQ_REGION) | irq]; + if (IRQ_REGION(irq_num) != CPU_IRQ_REGION) + ++kstat.irqs[cpu][irq_num]; + + mask_irq(irq_num); + do_irq(®ion->action[irq], irq_num, regs); + unmask_irq(irq_num); + } +} + +static inline int alloc_irqregion(void) +{ + int irqreg; + + for(irqreg=1; irqreg<=(NR_IRQ_REGS); irqreg++) { + if(irq_region[irqreg] == NULL) + return irqreg; + } + + return 0; +} + +struct irq_region *alloc_irq_region( + int count, struct irq_region_ops *ops, unsigned long flags, + const char *name, void *dev) +{ + struct irq_region *region; + int index; + + index = alloc_irqregion(); + + if((IRQ_REGION(count-1))) + return NULL; + + if (count < IRQ_PER_REGION) { + DBG_IRQ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n", + IRQ_PER_REGION, name, count); + count = IRQ_PER_REGION; + } + + if(flags & IRQ_REG_MASK) + if(!(ops->mask_irq && ops->unmask_irq)) + return NULL; + + if(flags & IRQ_REG_DIS) + if(!(ops->disable_irq && ops->enable_irq)) + return NULL; + + if((irq_region[index])) + return NULL; + + region = kmalloc(sizeof *region, GFP_ATOMIC); + if(!region) + return NULL; + + region->action = kmalloc(sizeof *region->action * count, GFP_ATOMIC); + if(!region->action) { + kfree(region); + return NULL; + } + memset(region->action, 0, sizeof *region->action * count); + + region->ops = *ops; + region->data.irqbase = IRQ_FROM_REGION(index); + region->data.flags = flags; + region->data.name = name; + region->data.dev = dev; + + irq_region[index] = region; + + return irq_region[index]; +} + + + +/* FIXME: SMP, flags, bottom halves, rest */ + +int request_irq(unsigned int irq, + void (*handler)(int, void *, struct pt_regs *), + unsigned long irqflags, + const char * devname, + void *dev_id) +{ + struct irqaction * action; + +#if 0 + printk(KERN_INFO "request_irq(%d, %p, 0x%lx, %s, %p)\n",irq, handler, irqflags, devname, dev_id); +#endif + if(!handler) { + printk(KERN_ERR "request_irq(%d,...): Augh! No handler for irq!\n", + irq); + return -EINVAL; + } + + if ((IRQ_REGION(irq) == 0) || irq_region[IRQ_REGION(irq)] == NULL) { + /* + ** Bug catcher for drivers which use "char" or u8 for + ** the IRQ number. They lose the region number which + ** is in pcidev->irq (an int). + */ + printk(KERN_ERR "%p (%s?) called request_irq with an invalid irq %d\n", + __builtin_return_address(0), devname, irq); + return -EINVAL; + } + + action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)]; + + if(action->handler) { + while(action->next) + action = action->next; + + action->next = kmalloc(sizeof *action, GFP_ATOMIC); + + action = action->next; + } + + if(!action) { + printk(KERN_ERR "request_irq():Augh! No action!\n") ; + return -ENOMEM; + } + + action->handler = handler; + action->flags = irqflags; + action->mask = 0; + action->name = devname; + action->next = NULL; + action->dev_id = dev_id; + + enable_irq(irq); + return 0; +} + +void free_irq(unsigned int irq, void *dev_id) +{ + struct irqaction *action, **p; + + action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)]; + + if(action->dev_id == dev_id) { + if(action->next == NULL) + action->handler = NULL; + else + memcpy(action, action->next, sizeof *action); + + return; + } + + p = &action->next; + action = action->next; + + for (; (action = *p) != NULL; p = &action->next) { + if (action->dev_id != dev_id) + continue; + + /* Found it - now free it */ + *p = action->next; + kfree(action); + + return; + } + + printk(KERN_ERR "Trying to free free IRQ%d\n",irq); +} + +unsigned long probe_irq_on (void) +{ + return 0; +} + +int probe_irq_off (unsigned long irqs) +{ + return 0; +} + + +void __init init_IRQ(void) +{ +} + +void init_irq_proc(void) +{ +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/keyboard.c linux/arch/parisc/kernel/keyboard.c --- v2.4.0-test11/linux/arch/parisc/kernel/keyboard.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/keyboard.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,82 @@ +/* + * linux/arch/parisc/kernel/keyboard.c + * + * Alex deVries + * Copyright (1999) The Puffin Group + * Mostly rewritten by Philipp Rumpf + * Copyright 2000 Philipp Rumpf + */ + +#include +#include + +static int def_setkeycode(unsigned int x, unsigned int y) +{ + return 0; +} + +static int def_getkeycode(unsigned int x) +{ + return 0; +} + +static int def_translate(unsigned char scancode, unsigned char *keycode, + char raw) +{ + *keycode = scancode; + + return 1; +} + +static char def_unexpected_up(unsigned char c) +{ + return 128; +} + +static void def_leds(unsigned char leds) +{ +} + +static void def_init_hw(void) +{ +} + +static char def_sysrq_xlate[NR_KEYS]; + +static struct kbd_ops def_kbd_ops = { + setkeycode: def_setkeycode, + getkeycode: def_getkeycode, + translate: def_translate, + unexpected_up: def_unexpected_up, + leds: def_leds, + init_hw: def_init_hw, + + sysrq_key: 0xff, + sysrq_xlate: def_sysrq_xlate, +}; + +struct kbd_ops *kbd_ops = &def_kbd_ops; + +void register_kbd_ops(struct kbd_ops *ops) +{ + if(ops->setkeycode) + kbd_ops->setkeycode = ops->setkeycode; + + if(ops->getkeycode) + kbd_ops->getkeycode = ops->getkeycode; + + if(ops->translate) + kbd_ops->translate = ops->translate; + + if(ops->unexpected_up) + kbd_ops->unexpected_up = ops->unexpected_up; + + if(ops->leds) + kbd_ops->leds = ops->leds; + + if(ops->init_hw) + kbd_ops->init_hw = ops->init_hw; + + kbd_ops->sysrq_key = ops->sysrq_key; + kbd_ops->sysrq_xlate = ops->sysrq_xlate; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/lasimap.map linux/arch/parisc/kernel/lasimap.map --- v2.4.0-test11/linux/arch/parisc/kernel/lasimap.map Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/lasimap.map Tue Dec 5 12:29:39 2000 @@ -0,0 +1,322 @@ +# HP 712 kernel keymap. This uses 7 modifier combinations. + +keymaps 0-2,4-5,8,12 +# ie, plain, Shift, AltGr, Control, Control+Shift, Alt and Control+Alt + + +# Change the above line into +# keymaps 0-2,4-6,8,12 +# in case you want the entries +# altgr control keycode 83 = Boot +# altgr control keycode 111 = Boot +# below. +# +# In fact AltGr is used very little, and one more keymap can +# be saved by mapping AltGr to Alt (and adapting a few entries): +# keycode 100 = Alt +# +keycode 1 = F9 F19 Console_21 + control keycode 1 = F9 + alt keycode 1 = Console_9 + control alt keycode 1 = Console_9 +keycode 2 = +keycode 3 = F5 F15 Console_17 + control keycode 3 = F5 + alt keycode 3 = Console_5 + control alt keycode 3 = Console_5 +keycode 4 = F3 F13 Console_15 + control keycode 4 = F3 + alt keycode 4 = Console_3 + control alt keycode 4 = Console_3 +keycode 5 = F1 F11 Console_13 + control keycode 5 = F1 + alt keycode 5 = Console_1 + control alt keycode 5 = Console_1 +keycode 6 = F2 F12 Console_14 + control keycode 6 = F2 + alt keycode 6 = Console_2 + control alt keycode 6 = Console_2 +keycode 7 = F12 F12 Console_24 + control keycode 7 = F12 + alt keycode 7 = Console_12 + control alt keycode 7 = Console_12 +keycode 8 = +keycode 9 = F10 F20 Console_22 + control keycode 9 = F10 + alt keycode 9 = Console_10 + control alt keycode 9 = Console_10 +keycode 10 = F8 F18 Console_20 + control keycode 10 = F8 + alt keycode 10 = Console_8 + control alt keycode 10 = Console_8 +keycode 11 = F6 F16 Console_18 + control keycode 11 = F6 + alt keycode 11 = Console_6 + control alt keycode 11 = Console_6 +keycode 12 = F4 F14 Console_16 + control keycode 12 = F4 + alt keycode 12 = Console_4 + control alt keycode 12 = Console_4 +keycode 13 = Tab Tab + alt keycode 13 = Meta_Tab +keycode 14 = grave asciitilde + control keycode 14 = nul + alt keycode 14 = Meta_grave +keycode 15 = +keycode 16 = +keycode 17 = Alt +keycode 18 = Shift +keycode 19 = +keycode 20 = Control +keycode 21 = q +keycode 22 = one exclam exclam +keycode 23 = +keycode 24 = +keycode 25 = +keycode 26 = z +keycode 27 = s +keycode 28 = a + altgr keycode 28 = Hex_A +keycode 29 = w +keycode 30 = two at at +keycode 31 = +keycode 32 = +keycode 33 = c + altgr keycode 46 = Hex_C +keycode 34 = x +keycode 35 = d + altgr keycode 35 = Hex_D +keycode 36 = e + altgr keycode 36 = Hex_E +keycode 37 = four dollar +keycode 38 = three numbersign +keycode 39 = +keycode 40 = +keycode 41 = +keycode 42 = v +keycode 43 = f + altgr keycode 43 = Hex_F +keycode 44 = t +keycode 45 = r +keycode 46 = five percent +keycode 47 = +keycode 48 = +keycode 49 = n +keycode 50 = b + altgr keycode 50 = Hex_B +keycode 51 = h +keycode 52 = g +keycode 53 = y +keycode 54 = six asciicircum +keycode 55 = +keycode 56 = +keycode 57 = +keycode 58 = m +keycode 59 = j +keycode 60 = u +keycode 61 = seven ampersand +keycode 62 = eight asterisk asterisk +keycode 63 = +keycode 64 = +keycode 65 = comma less + alt keycode 65 = Meta_comma +keycode 66 = k +keycode 67 = i +keycode 68 = o +keycode 69 = zero parenright bracketright +keycode 70 = nine parenleft bracketleft +keycode 71 = +keycode 72 = +keycode 73 = period greater + control keycode 73 = Compose + alt keycode 73 = Meta_period +keycode 74 = slash question + control keycode 74 = Delete + alt keycode 53 = Meta_slash +keycode 75 = l +keycode 76 = semicolon colon + alt keycode 39 = Meta_semicolon +keycode 77 = p +keycode 78 = minus underscore +keycode 79 = +keycode 80 = +keycode 81 = +keycode 82 = apostrophe quotedbl + control keycode 82 = Control_g + alt keycode 40 = Meta_apostrophe +keycode 83 = +keycode 84 = bracketleft braceleft + control keycode 84 = Escape + alt keycode 26 = Meta_bracketleft +keycode 85 = equal plus +keycode 86 = +keycode 87 = +keycode 88 = Caps_Lock +keycode 88 = +keycode 89 = +keycode 89 = +keycode 89 = +keycode 90 = Return + alt keycode 90 = Meta_Control_m +keycode 91 = bracketright braceright asciitilde + control keycode 91 = Control_bracketright + alt keycode 91 = Meta_bracketright +keycode 92 = +keycode 93 = backslash bar + control keycode 43 = Control_backslash + alt keycode 43 = Meta_backslash +keycode 94 = +keycode 95 = +keycode 96 = +keycode 97 = +keycode 98 = +keycode 99 = +keycode 100 = +keycode 101 = +keycode 102 = BackSpace +keycode 103 = +keycode 104 = +keycode 105 = KP_1 + alt keycode 105 = Ascii_1 + altgr keycode 105 = Hex_1 +keycode 106 = +keycode 107 = KP_4 + alt keycode 107 = Ascii_4 + altgr keycode 107 = Hex_4 +keycode 108 = KP_7 + alt keycode 108 = Ascii_7 + altgr keycode 108 = Hex_7 +keycode 109 = +keycode 110 = +keycode 111 = +keycode 112 = KP_0 + alt keycode 82 = Ascii_0 + altgr keycode 82 = Hex_0 +keycode 113 = KP_Period +keycode 114 = KP_2 + alt keycode 114 = Ascii_2 + altgr keycode 114 = Hex_2 +keycode 115 = KP_5 + alt keycode 115 = Ascii_5 + altgr keycode 115 = Hex_5 +keycode 116 = KP_6 + alt keycode 116 = Ascii_6 + altgr keycode 116 = Hex_6 +keycode 117 = KP_8 + alt keycode 117 = Ascii_8 + altgr keycode 117 = Hex_8 +keycode 118 = Escape +keycode 119 = +keycode 120 = F11 +keycode 121 = KP_Add +keycode 122 = KP_3 + alt keycode 122 = Ascii_3 + altgr keycode 122 = Hex_3 +keycode 123 = KP_Subtract +keycode 124 = KP_Multiply +keycode 125 = KP_9 + alt keycode 125 = Ascii_9 + altgr keycode 125 = Hex_9 +keycode 126 = +# 131!! +keycode 127 = F7 F17 Console_19 + control keycode 127 = F7 + alt keycode 127 = Console_7 + control alt keycode 127 = Console_7 + +string F1 = "\033[[A" +string F2 = "\033[[B" +string F3 = "\033[[C" +string F4 = "\033[[D" +string F5 = "\033[[E" +string F6 = "\033[17~" +string F7 = "\033[18~" +string F8 = "\033[19~" +string F9 = "\033[20~" +string F10 = "\033[21~" +string F11 = "\033[23~" +string F12 = "\033[24~" +string F13 = "\033[25~" +string F14 = "\033[26~" +string F15 = "\033[28~" +string F16 = "\033[29~" +string F17 = "\033[31~" +string F18 = "\033[32~" +string F19 = "\033[33~" +string F20 = "\033[34~" +string Find = "\033[1~" +string Insert = "\033[2~" +string Remove = "\033[3~" +string Select = "\033[4~" +string Prior = "\033[5~" +string Next = "\033[6~" +string Macro = "\033[M" +string Pause = "\033[P" +compose '`' 'A' to 'À' +compose '`' 'a' to 'à' +compose '\'' 'A' to 'Á' +compose '\'' 'a' to 'á' +compose '^' 'A' to 'Â' +compose '^' 'a' to 'â' +compose '~' 'A' to 'Ã' +compose '~' 'a' to 'ã' +compose '"' 'A' to 'Ä' +compose '"' 'a' to 'ä' +compose 'O' 'A' to 'Å' +compose 'o' 'a' to 'å' +compose '0' 'A' to 'Å' +compose '0' 'a' to 'å' +compose 'A' 'A' to 'Å' +compose 'a' 'a' to 'å' +compose 'A' 'E' to 'Æ' +compose 'a' 'e' to 'æ' +compose ',' 'C' to 'Ç' +compose ',' 'c' to 'ç' +compose '`' 'E' to 'È' +compose '`' 'e' to 'è' +compose '\'' 'E' to 'É' +compose '\'' 'e' to 'é' +compose '^' 'E' to 'Ê' +compose '^' 'e' to 'ê' +compose '"' 'E' to 'Ë' +compose '"' 'e' to 'ë' +compose '`' 'I' to 'Ì' +compose '`' 'i' to 'ì' +compose '\'' 'I' to 'Í' +compose '\'' 'i' to 'í' +compose '^' 'I' to 'Î' +compose '^' 'i' to 'î' +compose '"' 'I' to 'Ï' +compose '"' 'i' to 'ï' +compose '-' 'D' to 'Ð' +compose '-' 'd' to 'ð' +compose '~' 'N' to 'Ñ' +compose '~' 'n' to 'ñ' +compose '`' 'O' to 'Ò' +compose '`' 'o' to 'ò' +compose '\'' 'O' to 'Ó' +compose '\'' 'o' to 'ó' +compose '^' 'O' to 'Ô' +compose '^' 'o' to 'ô' +compose '~' 'O' to 'Õ' +compose '~' 'o' to 'õ' +compose '"' 'O' to 'Ö' +compose '"' 'o' to 'ö' +compose '/' 'O' to 'Ø' +compose '/' 'o' to 'ø' +compose '`' 'U' to 'Ù' +compose '`' 'u' to 'ù' +compose '\'' 'U' to 'Ú' +compose '\'' 'u' to 'ú' +compose '^' 'U' to 'Û' +compose '^' 'u' to 'û' +compose '"' 'U' to 'Ü' +compose '"' 'u' to 'ü' +compose '\'' 'Y' to 'Ý' +compose '\'' 'y' to 'ý' +compose 'T' 'H' to 'Þ' +compose 't' 'h' to 'þ' +compose 's' 's' to 'ß' +compose '"' 'y' to 'ÿ' +compose 's' 'z' to 'ß' +compose 'i' 'j' to 'ÿ' diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/lba_pci.c linux/arch/parisc/kernel/lba_pci.c --- v2.4.0-test11/linux/arch/parisc/kernel/lba_pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/lba_pci.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,1346 @@ +/* +** PCI Lower Bus Adapter (LBA) manager +** +** (c) Copyright 1999,2000 Grant Grundler +** (c) Copyright 1999,2000 Hewlett-Packard Company +** +** 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 module primarily provides access to PCI bus (config/IOport +** spaces) on platforms with an SBA/LBA chipset. A/B/C/J/L/N-class +** with 4 digit model numbers - eg C3000 (and A400...sigh). +** +** LBA driver isn't as simple as the Dino driver because: +** (a) this chip has substantial bug fixes between revisions +** (Only one Dino bug has a software workaround :^( ) +** (b) has more options which we don't (yet) support (DMA hints, OLARD) +** (c) IRQ support lives in the I/O SAPIC driver (not with PCI driver) +** (d) play nicely with both PAT and "Legacy" PA-RISC firmware (PDC). +** (dino only deals with "Legacy" PDC) +** +** LBA driver passes the I/O SAPIC HPA to the I/O SAPIC driver. +** (I/O SAPIC is integratd in the LBA chip). +** +** FIXME: Add support to SBA and LBA drivers for DMA hint sets +** FIXME: Add support for PCI card hot-plug (OLARD). +*/ + +#include +#include +#include +#include +#include /* for __init and __devinit */ +#include +#include +#include +#include + +#include +#include /* for struct irq_region support */ +#include +#include +#include +#include +#include + +#include /* for register_driver() stuff */ +#include /* for iosapic_register() */ +#include /* gsc_read/write stuff */ + + +#ifndef TRUE +#define TRUE (1 == 1) +#define FALSE (1 == 0) +#endif + +#undef DEBUG_LBA /* general stuff */ +#undef DEBUG_LBA_PORT /* debug I/O Port access */ +#undef DEBUG_LBA_CFG /* debug Config Space Access (ie PCI Bus walk) */ +#undef DEBUG_LBA_PAT /* debug PCI Resource Mgt code - PDC PAT only */ + +#ifdef DEBUG_LBA +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#ifdef DEBUG_LBA_PORT +#define DBG_PORT(x...) printk(x) +#else +#define DBG_PORT(x...) +#endif + +#ifdef DEBUG_LBA_CFG +#define DBG_CFG(x...) printk(x) +#else +#define DBG_CFG(x...) +#endif + +#ifdef DEBUG_LBA_PAT +#define DBG_PAT(x...) printk(x) +#else +#define DBG_PAT(x...) +#endif + +/* +** Config accessor functions only pass in the 8-bit bus number and not +** the 8-bit "PCI Segment" number. Each LBA will be assigned a PCI bus +** number based on what firmware wrote into the scratch register. +** +** The "secondary" bus number is set to this before calling +** pci_register_ops(). If any PPB's are present, the scan will +** discover them and update the "secondary" and "subordinate" +** fields in the pci_bus structure. +** +** Changes in the configuration *may* result in a different +** bus number for each LBA depending on what firmware does. +*/ + +#define MODULE_NAME "lba" + +static int lba_driver_callback(struct hp_device *, struct pa_iodc_driver *); + + +static struct pa_iodc_driver lba_drivers_for[]= { + + {HPHW_BRIDGE, 0x782, 0x0, 0xa, 0,0, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "tbd", (void *) lba_driver_callback}, + + {0,0,0,0,0,0, + 0, + (char *) NULL, (char *) NULL, (void *) NULL} +}; + + +#define LBA_FUNC_ID 0x0000 /* function id */ +#define LBA_FCLASS 0x0008 /* function class, bist, header, rev... */ +#define LBA_CAPABLE 0x0030 /* capabilities register */ + +#define LBA_PCI_CFG_ADDR 0x0040 /* poke CFG address here */ +#define LBA_PCI_CFG_DATA 0x0048 /* read or write data here */ + +#define LBA_PMC_MTLT 0x0050 /* Firmware sets this - read only. */ +#define LBA_FW_SCRATCH 0x0058 /* Firmware writes the PCI bus number here. */ +#define LBA_ERROR_ADDR 0x0070 /* On error, address gets logged here */ + +#define LBA_ARB_MASK 0x0080 /* bit 0 enable arbitration. PAT/PDC enables */ +#define LBA_ARB_PRI 0x0088 /* firmware sets this. */ +#define LBA_ARB_MODE 0x0090 /* firmware sets this. */ +#define LBA_ARB_MTLT 0x0098 /* firmware sets this. */ + +#define LBA_MOD_ID 0x0100 /* Module ID. PDC_PAT_CELL reports 4 */ + +#define LBA_STAT_CTL 0x0108 /* Status & Control */ +#define HF_ENABLE 0x40 /* enable HF mode (default is -1 mode) */ + +#define LBA_LMMIO_BASE 0x0200 /* < 4GB I/O address range */ +#define LBA_LMMIO_MASK 0x0208 + +#define LBA_GMMIO_BASE 0x0210 /* > 4GB I/O address range */ +#define LBA_GMMIO_MASK 0x0218 + +#define LBA_WLMMIO_BASE 0x0220 /* All < 4GB ranges under the same *SBA* */ +#define LBA_WLMMIO_MASK 0x0228 + +#define LBA_WGMMIO_BASE 0x0230 /* All > 4GB ranges under the same *SBA* */ +#define LBA_WGMMIO_MASK 0x0238 + +#define LBA_IOS_BASE 0x0240 /* I/O port space for this LBA */ +#define LBA_IOS_MASK 0x0248 + +#define LBA_ELMMIO_BASE 0x0250 /* Extra LMMIO range */ +#define LBA_ELMMIO_MASK 0x0258 + +#define LBA_EIOS_BASE 0x0260 /* Extra I/O port space */ +#define LBA_EIOS_MASK 0x0268 + +#define LBA_DMA_CTL 0x0278 /* firmware sets this */ + +/* RESET: ignore DMA stuff until we can measure performance */ +#define LBA_IBASE 0x0300 /* DMA support */ +#define LBA_IMASK 0x0308 +#define LBA_HINT_CFG 0x0310 +#define LBA_HINT_BASE 0x0380 /* 14 registers at every 8 bytes. */ + +/* ERROR regs are needed for config cycle kluges */ +#define LBA_ERROR_CONFIG 0x0680 +#define LBA_ERROR_STATUS 0x0688 + +#define LBA_IOSAPIC_BASE 0x800 /* Offset of IRQ logic */ + +/* non-postable I/O port space, densely packed */ +#ifdef __LP64__ +#define LBA_ASTRO_PORT_BASE (0xfffffffffee00000UL) +#else +#define LBA_ASTRO_PORT_BASE (0xfee00000UL) +#endif + + +/* +** lba_device: Per instance Elroy data structure +*/ +struct lba_device { + struct pci_hba_data hba; + + spinlock_t lba_lock; + void *iosapic_obj; + +#ifdef __LP64__ + unsigned long lmmio_base; /* PA_VIEW - fixup MEM addresses */ + unsigned long gmmio_base; /* PA_VIEW - Not used (yet) */ + unsigned long iop_base; /* PA_VIEW - for IO port accessor funcs */ +#endif + + int flags; /* state/functionality enabled */ + int hw_rev; /* HW revision of chip */ +}; + + +static u32 lba_t32; + +/* +** lba "flags" +*/ +#define LBA_FLAG_NO_DMA_DURING_CFG 0x01 +#define LBA_FLAG_SKIP_PROBE 0x10 + +/* Tape Release 4 == hw_rev 5 */ +#define LBA_TR4PLUS(d) ((d)->hw_rev > 0x4) +#define LBA_DMA_DURING_CFG_DISABLED(d) ((d)->flags & LBA_FLAG_NO_DMA_DURING_CFG) +#define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE) + + +/* Looks nice and keeps the compiler happy */ +#define LBA_DEV(d) ((struct lba_device *) (d)) + + +/* +** Only allow 8 subsidiary busses per LBA +** Problem is the PCI bus numbering is globally shared. +*/ +#define LBA_MAX_NUM_BUSES 8 + +/************************************ + * LBA register read and write support + * + * BE WARNED: register writes are posted. + * (ie follow writes which must reach HW with a read) + */ +#define READ_U8(addr) gsc_readb(addr) +#define READ_U16(addr) gsc_readw((u16 *) (addr)) +#define READ_U32(addr) gsc_readl((u32 *) (addr)) +#define WRITE_U8(value, addr) gsc_writeb(value, addr) +#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr)) +#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr)) + +#define READ_REG8(addr) gsc_readb(addr) +#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr))) +#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr))) +#define WRITE_REG8(value, addr) gsc_writeb(value, addr) +#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr)) +#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr)) + + +#define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8)) +#define LBA_CFG_BUS(tok) ((u8) ((tok)>>16)) +#define LBA_CFG_DEV(tok) ((u8) ((tok)>>11) & 0x1f) +#define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7) + + +#ifdef DEBUG_LBA +/* Extract LBA (Rope) number from HPA */ +#define LBA_NUM(x) ((((uintptr_t) x) >> 13) & 0xf) +#endif /* DEBUG_LBA */ + +#ifdef __LP64__ +/* PDC_PAT */ +static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0}; +#endif + +/* +** One time initialization to let the world know the LBA was found. +** This is the only routine which is NOT static. +** Must be called exactly once before pci_init(). +*/ +void __init lba_init(void) +{ + register_driver(lba_drivers_for); +} + + +static void +lba_dump_res(struct resource *r, int d) +{ + int i; + + if (NULL == r) + return; + + printk("(%p)", r->parent); + for (i = d; i ; --i) printk(" "); + printk("%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags); + lba_dump_res(r->child, d+2); + lba_dump_res(r->sibling, d); +} + + +/* +** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex +** workaround for cfg cycles: +** -- preserve LBA state +** -- LBA_FLAG_NO_DMA_DURING_CFG workaround +** -- turn on smart mode +** -- probe with config writes before doing config reads +** -- check ERROR_STATUS +** -- clear ERROR_STATUS +** -- restore LBA state +** +** The workaround is only used for device discovery. +*/ + +static int +lba_device_present( u8 bus, u8 dfn, struct lba_device *d) +{ + u8 first_bus = d->hba.hba_bus->secondary; + u8 last_sub_bus = d->hba.hba_bus->subordinate; +#if 0 +/* FIXME - see below in this function */ + u8 dev = PCI_SLOT(dfn); + u8 func = PCI_FUNC(dfn); +#endif + + ASSERT(bus >= first_bus); + ASSERT(bus <= last_sub_bus); + ASSERT((bus - first_bus) < LBA_MAX_NUM_BUSES); + + if ((bus < first_bus) || + (bus > last_sub_bus) || + ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) + { + /* devices that fall into any of these cases won't get claimed */ + return(FALSE); + } + +#if 0 +/* +** FIXME: Need to implement code to fill the devices bitmap based +** on contents of the local pci_bus tree "data base". +** pci_register_ops() walks the bus for us and builds the tree. +** For now, always do the config cycle. +*/ + bus -= first_bus; + + return (((d->devices[bus][dev]) >> func) & 0x1); +#else + return TRUE; +#endif +} + + + +#define LBA_CFG_SETUP(d, tok) { \ + /* Save contents of error config register. */ \ + error_config = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG); \ +\ + /* Save contents of status control register. */ \ + status_control = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); \ +\ + /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA \ + ** arbitration for full bus walks. \ + */ \ + if (LBA_DMA_DURING_CFG_DISABLED(d)) { \ + /* Save contents of arb mask register. */ \ + arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK); \ +\ + /* \ + * Turn off all device arbitration bits (i.e. everything \ + * except arbitration enable bit). \ + */ \ + WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK); \ + } \ +\ + /* \ + * Set the smart mode bit so that master aborts don't cause \ + * LBA to go into PCI fatal mode (required). \ + */ \ + WRITE_REG32(error_config | 0x20, d->hba.base_addr + LBA_ERROR_CONFIG); \ +} + + +#define LBA_CFG_PROBE(d, tok) { \ + /* \ + * Setup Vendor ID write and read back the address register \ + * to make sure that LBA is the bus master. \ + */ \ + WRITE_REG32(tok | PCI_VENDOR_ID, (d)->hba.base_addr + LBA_PCI_CFG_ADDR);\ + /* \ + * Read address register to ensure that LBA is the bus master, \ + * which implies that DMA traffic has stopped when DMA arb is off. \ + */ \ + lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ + /* \ + * Generate a cfg write cycle (will have no affect on \ + * Vendor ID register since read-only). \ + */ \ + WRITE_REG32(~0, (d)->hba.base_addr + LBA_PCI_CFG_DATA); \ + /* \ + * Make sure write has completed before proceeding further, \ + * i.e. before setting clear enable. \ + */ \ + lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ +} + + +/* + * HPREVISIT: + * -- Can't tell if config cycle got the error. + * + * OV bit is broken until rev 4.0, so can't use OV bit and + * LBA_ERROR_LOG_ADDR to tell if error belongs to config cycle. + * + * As of rev 4.0, no longer need the error check. + * + * -- Even if we could tell, we still want to return -1 + * for **ANY** error (not just master abort). + * + * -- Only clear non-fatal errors (we don't want to bring + * LBA out of pci-fatal mode). + * + * Actually, there is still a race in which + * we could be clearing a fatal error. We will + * live with this during our real mode bus walk + * until rev 4.0 (no driver activity during + * real mode bus walk). The real mode bus walk + * has race conditions concerning the use of + * smart mode as well. + */ + +#define LBA_MASTER_ABORT_ERROR 0xc +#define LBA_FATAL_ERROR 0x10 + +#define LBA_CFG_MASTER_ABORT_CHECK(d, base, tok, error) { \ + u32 error_status = 0; \ + /* \ + * Set clear enable (CE) bit. Unset by HW when new \ + * errors are logged -- LBA HW ERS section 14.3.3). \ + */ \ + WRITE_REG32(status_control | 0x20, base + LBA_STAT_CTL); \ + error_status = READ_REG32(base + LBA_ERROR_STATUS); \ + if ((error_status & 0x1f) != 0) { \ + /* \ + * Fail the config read request. \ + */ \ + error = 1; \ + if ((error_status & LBA_FATAL_ERROR) == 0) { \ + /* \ + * Clear error status (if fatal bit not set) by setting \ + * clear error log bit (CL). \ + */ \ + WRITE_REG32(status_control | 0x10, base + LBA_STAT_CTL); \ + } \ + } \ +} + +#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \ + WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR) + +#define LBA_CFG_ADDR_SETUP(d, addr) { \ + WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ + /* \ + * HPREVISIT: \ + * -- Potentially could skip this once DMA bug fixed. \ + * \ + * Read address register to ensure that LBA is the bus master, \ + * which implies that DMA traffic has stopped when DMA arb is off. \ + */ \ + lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR); \ +} + + +#define LBA_CFG_RESTORE(d, base) { \ + /* \ + * Restore status control register (turn off clear enable). \ + */ \ + WRITE_REG32(status_control, base + LBA_STAT_CTL); \ + /* \ + * Restore error config register (turn off smart mode). \ + */ \ + WRITE_REG32(error_config, base + LBA_ERROR_CONFIG); \ + if (LBA_DMA_DURING_CFG_DISABLED(d)) { \ + /* \ + * Restore arb mask register (reenables DMA arbitration). \ + */ \ + WRITE_REG32(arb_mask, base + LBA_ARB_MASK); \ + } \ +} + + + +static unsigned int +lba_rd_cfg( struct lba_device *d, u32 tok, u8 reg, u32 size) +{ + u32 data = ~0; + int error = 0; + u32 arb_mask = 0; /* used by LBA_CFG_SETUP/RESTORE */ + u32 error_config = 0; /* used by LBA_CFG_SETUP/RESTORE */ + u32 status_control = 0; /* used by LBA_CFG_SETUP/RESTORE */ + + ASSERT((size == sizeof(u8)) || + (size == sizeof(u16)) || + (size == sizeof(u32))); + + if ((size != sizeof(u8)) && + (size != sizeof(u16)) && + (size != sizeof(u32))) { + return(data); + } + + LBA_CFG_SETUP(d, tok); + LBA_CFG_PROBE(d, tok); + LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error); + if (!error) { + LBA_CFG_ADDR_SETUP(d, tok | reg); + switch (size) { + case sizeof(u8): + data = (u32) READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 3)); + break; + case sizeof(u16): + data = (u32) READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 2)); + break; + case sizeof(u32): + data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA); + break; + default: + break; /* leave data as -1 */ + } + } + LBA_CFG_RESTORE(d, d->hba.base_addr); + return(data); +} + + + +#define LBA_CFG_RD(size, mask) \ +static int lba_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \ +{ \ + struct lba_device *d = LBA_DEV(dev->bus->sysdata); \ + u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ + u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \ + \ + if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \ + /* original - Generate config cycle on broken elroy \ + with risk we will miss PCI bus errors. */ \ + *data = (u##size) lba_rd_cfg(d, tok, pos, sizeof(u##size)); \ + DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \ + return(*data == (u##size) -1); \ + } \ + \ + if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) \ + { \ + DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos, *data); \ + /* either don't want to look or know device isn't present. */ \ + *data = (u##size) -1; \ + return(0); \ + } \ + \ + /* Basic Algorithm \ + ** Should only get here on fully working LBA rev. \ + ** This is how simple the code should have been. \ + */ \ + LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \ + *data = READ_REG##size(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask));\ + DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\ + return(*data == (u##size) -1); \ +} + +LBA_CFG_RD( 8, 3) +LBA_CFG_RD(16, 2) +LBA_CFG_RD(32, 0) + + + +static void +lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) +{ + int error = 0; + u32 arb_mask = 0; + u32 error_config = 0; + u32 status_control = 0; + + ASSERT((size == sizeof(u8)) || + (size == sizeof(u16)) || + (size == sizeof(u32))); + + if ((size != sizeof(u8)) && + (size != sizeof(u16)) && + (size != sizeof(u32))) { + return; + } + + LBA_CFG_SETUP(d, tok); + LBA_CFG_ADDR_SETUP(d, tok | reg); + switch (size) { + case sizeof(u8): + WRITE_REG8((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA + (reg&3)); + break; + case sizeof(u16): + WRITE_REG16((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA +(reg&2)); + break; + case sizeof(u32): + WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA); + break; + default: + break; + } + LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error); + LBA_CFG_RESTORE(d, d->hba.base_addr); +} + + +/* + * LBA 4.0 config write code implements non-postable semantics + * by doing a read of CONFIG ADDR after the write. + */ + +#define LBA_CFG_WR(size, mask) \ +static int lba_cfg_write##size (struct pci_dev *dev, int pos, u##size data) \ +{ \ + struct lba_device *d = LBA_DEV(dev->bus->sysdata); \ + u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \ + u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \ + \ + ASSERT((tok & 0xff) == 0); \ + ASSERT(pos < 0x100); \ + \ + if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \ + /* Original Workaround */ \ + lba_wr_cfg(d, tok, pos, (u32) data, sizeof(u##size)); \ + DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \ + return 0; \ + } \ + \ + if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) { \ + DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \ + return 1; /* New Workaround */ \ + } \ + \ + DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \ + /* Basic Algorithm */ \ + LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \ + WRITE_REG##size(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask)); \ + lba_t32 = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_ADDR); \ + return 0; \ +} + + +LBA_CFG_WR( 8, 3) +LBA_CFG_WR(16, 2) +LBA_CFG_WR(32, 0) + +static struct pci_ops lba_cfg_ops = { + lba_cfg_read8, lba_cfg_read16, lba_cfg_read32, + lba_cfg_write8, lba_cfg_write16, lba_cfg_write32 + +}; + + + +static void +lba_bios_init(void) +{ + DBG(KERN_DEBUG MODULE_NAME ": lba_bios_init\n"); +} + + +#ifdef __LP64__ + +/* +** Determine if a device is already configured. +** If so, reserve it resources. +** +** Read PCI cfg command register and see if I/O or MMIO is enabled. +** PAT has to enable the devices it's using. +** +** Note: resources are fixed up before we try to claim them. +*/ +static void +lba_claim_dev_resources(struct pci_dev *dev) +{ + u16 cmd; + int i, srch_flags; + + (void) lba_cfg_read16(dev, PCI_COMMAND, &cmd); + + srch_flags = (cmd & PCI_COMMAND_IO) ? IORESOURCE_IO : 0; + if (cmd & PCI_COMMAND_MEMORY) + srch_flags |= IORESOURCE_MEM; + + if (!srch_flags) + return; + + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + if (dev->resource[i].flags & srch_flags) { + pci_claim_resource(dev, i); + DBG(" claimed %s %d [%lx,%lx]/%x\n", + dev->slot_name, i, + dev->resource[i].start, + dev->resource[i].end, + (int) dev->resource[i].flags + ); + } + } +} +#endif + + +/* +** The algorithm is generic code. +** But it needs to access local data structures to get the IRQ base. +** Could make this a "pci_fixup_irq(bus, region)" but not sure +** it's worth it. +** +** Called by do_pci_scan_bus() immediately after each PCI bus is walked. +** Resources aren't allocated until recursive buswalk below HBA is completed. +*/ +static void +lba_fixup_bus(struct pci_bus *bus) +{ + struct list_head *ln; + struct pci_dev *dev; + u16 fbb_enable = PCI_STATUS_FAST_BACK; + u16 status; + struct lba_device *ldev = LBA_DEV(bus->sysdata); +#ifdef __LP64__ + int i; +#endif + DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n", + bus, bus->secondary, bus->sysdata); + + /* + ** Properly Setup MMIO resources for this bus. + ** pci_alloc_primary_bus() mangles this. + */ + if (NULL == bus->self) { + int err; + + DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", + ldev->hba.io_space.name, + ldev->hba.io_space.start, + ldev->hba.io_space.end, + (int) ldev->hba.io_space.flags); + DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n", + ldev->hba.mem_space.name, + ldev->hba.mem_space.start, + ldev->hba.mem_space.end, + (int) ldev->hba.mem_space.flags); + + err = request_resource(&ioport_resource, &(ldev->hba.io_space)); + if (err < 0) { + BUG(); + lba_dump_res(&ioport_resource, 2); + } + err = request_resource(&iomem_resource, &(ldev->hba.mem_space)); + if (err < 0) { + BUG(); + lba_dump_res(&iomem_resource, 2); + } + + bus->resource[0] = &(ldev->hba.io_space); + bus->resource[1] = &(ldev->hba.mem_space); + } + + list_for_each(ln, &bus->devices) { + + dev = pci_dev_b(ln); + +#ifdef __LP64__ + /* + ** 0-5 are the "standard PCI regions" + ** (see comments near PCI_NUM_RESOURCES in include/linux/pci.h) + */ + for (i = 0; i <= PCI_ROM_RESOURCE; i++) { + struct resource *res = &(dev->resource[i]); + + if (res->flags & IORESOURCE_MEM) { + /* "Globalize" PCI address */ + res->start |= ldev->lmmio_base; + res->end |= ldev->lmmio_base; + } + } +#endif + + /* + ** If one device does not support FBB transfers, + ** No one on the bus can be allowed to use them. + */ + (void) lba_cfg_read16(dev, PCI_STATUS, &status); + fbb_enable &= status; + +#ifdef __LP64__ + if (pdc_pat) { + /* Claim resources for PDC's devices */ + lba_claim_dev_resources(dev); + } +#endif /* __LP64__ */ + + /* + ** P2PB's have no IRQs. ignore them. + */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) + continue; + + /* Adjust INTERRUPT_LINE for this dev */ + iosapic_fixup_irq(LBA_DEV(bus->sysdata)->iosapic_obj, dev); + } + +#if 0 +/* FIXME/REVISIT - finish figuring out to set FBB on both +** pbus_set_ranges() clobbers PCI_BRIDGE_CONTROL. +** Can't fixup here anyway....garr... +*/ + if (fbb_enable) { + if (bus->self) { + u8 control; + /* enable on PPB */ + (void) lba_cfg_read8(bus->self, PCI_BRIDGE_CONTROL, &control); + (void) lba_cfg_write8(bus->self, PCI_BRIDGE_CONTROL, control | PCI_STATUS_FAST_BACK); + + } else { + /* enable on LBA */ + } + fbb_enable = PCI_COMMAND_FAST_BACK; + } + + /* Lastly enable FBB/PERR/SERR on all devices too */ + list_for_each(ln, &bus->devices) { + (void) lba_cfg_read16(dev, PCI_COMMAND, &status); + status |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR | fbb_enable; + (void) lba_cfg_write16(dev, PCI_COMMAND, status); + } +#endif +} + + +struct pci_bios_ops lba_bios_ops = { + lba_bios_init, + lba_fixup_bus /* void lba_fixup_bus(struct pci_bus *bus) */ +}; + + + + +/******************************************************* +** +** LBA Sprockets "I/O Port" Space Accessor Functions +** +** This set of accessor functions is intended for use with +** "legacy firmware" (ie Sprockets on Allegro/Forte boxes). +** +** Many PCI devices don't require use of I/O port space (eg Tulip, +** NCR720) since they export the same registers to both MMIO and +** I/O port space. In general I/O port space is slower than +** MMIO since drivers are designed so PIO writes can be posted. +** +********************************************************/ + +#define LBA_PORT_IN(size, mask) \ +static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \ +{ \ + u##size t; \ + ASSERT(bus != NULL); \ + DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, bus, addr); \ + t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \ + DBG_PORT(" 0x%x\n", t); \ + return (t); \ +} + +LBA_PORT_IN( 8, 3) +LBA_PORT_IN(16, 2) +LBA_PORT_IN(32, 0) + + + +/* +** BUG X4107: Ordering broken - DMA RD return can bypass PIO WR +** +** Fixed in Elroy 2.2. The READ_U32(..., LBA_FUNC_ID) below is +** guarantee non-postable completion semantics - not avoid X4107. +** The READ_U32 only guarantees the write data gets to elroy but +** out to the PCI bus. We can't read stuff from I/O port space +** since we don't know what has side-effects. Attempting to read +** from configuration space would be suicidal given the number of +** bugs in that elroy functionality. +** +** Description: +** DMA read results can improperly pass PIO writes (X4107). The +** result of this bug is that if a processor modifies a location in +** memory after having issued PIO writes, the PIO writes are not +** guaranteed to be completed before a PCI device is allowed to see +** the modified data in a DMA read. +** +** Note that IKE bug X3719 in TR1 IKEs will result in the same +** symptom. +** +** Workaround: +** The workaround for this bug is to always follow a PIO write with +** a PIO read to the same bus before starting DMA on that PCI bus. +** +*/ +#define LBA_PORT_OUT(size, mask) \ +static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \ +{ \ + ASSERT(bus != NULL); \ + DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \ + WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \ + if (LBA_DEV(d)->hw_rev < 3) \ + lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \ +} + +LBA_PORT_OUT( 8, 3) +LBA_PORT_OUT(16, 2) +LBA_PORT_OUT(32, 0) + + +static struct pci_port_ops lba_astro_port_ops = { + lba_astro_in8, lba_astro_in16, lba_astro_in32, + lba_astro_out8, lba_astro_out16, lba_astro_out32 +}; + + +#ifdef __LP64__ + +#define PIOP_TO_GMMIO(lba, addr) \ + ((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3)) + +/******************************************************* +** +** LBA PAT "I/O Port" Space Accessor Functions +** +** This set of accessor functions is intended for use with +** "PAT PDC" firmware (ie Prelude/Rhapsody/Piranha boxes). +** +** This uses the PIOP space located in the first 64MB of GMMIO. +** Each rope gets a full 64*KB* (ie 4 bytes per page) this way. +** bits 1:0 stay the same. bits 15:2 become 25:12. +** Then add the base and we can generate an I/O Port cycle. +********************************************************/ +#undef LBA_PORT_IN +#define LBA_PORT_IN(size, mask) \ +static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \ +{ \ + u##size t; \ + ASSERT(bus != NULL); \ + DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \ + t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \ + DBG_PORT(" 0x%x\n", t); \ + return (t); \ +} + +LBA_PORT_IN( 8, 3) +LBA_PORT_IN(16, 2) +LBA_PORT_IN(32, 0) + + +#undef LBA_PORT_OUT +#define LBA_PORT_OUT(size, mask) \ +static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ +{ \ + void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \ + ASSERT(bus != NULL); \ + DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ + WRITE_REG##size(val, where); \ + /* flush the I/O down to the elroy at least */ \ + lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \ +} + +LBA_PORT_OUT( 8, 3) +LBA_PORT_OUT(16, 2) +LBA_PORT_OUT(32, 0) + + +static struct pci_port_ops lba_pat_port_ops = { + lba_pat_in8, lba_pat_in16, lba_pat_in32, + lba_pat_out8, lba_pat_out16, lba_pat_out32 +}; + + + +/* +** make range information from PDC available to PCI subsystem. +** We make the PDC call here in order to get the PCI bus range +** numbers. The rest will get forwarded in pcibios_fixup_bus(). +** We don't have a struct pci_bus assigned to us yet. +*/ +static void +lba_pat_resources( struct hp_device *d, struct lba_device *lba_dev) +{ + pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; /* PA_VIEW */ +#ifdef DONT_NEED_THIS_FOR_ASTRO + pdc_pat_cell_mod_maddr_block_t io_pdc_cell; /* IO_VIEW */ + long io_count; +#endif + long status; /* PDC return status */ + long pa_count; + int i; + + /* return cell module (IO view) */ + status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index, + PA_VIEW, & pa_pdc_cell); + pa_count = pa_pdc_cell.mod[1]; + +#ifdef DONT_NEED_THIS_FOR_ASTRO + status |= pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index, + IO_VIEW, & io_pdc_cell); + io_count = io_pdc_cell.mod[1]; +#endif + + /* We've already done this once for device discovery...*/ + if (status != PDC_RET_OK) { + panic("pdc_pat_cell_module() call failed for LBA!\n"); + } + + if (PAT_GET_ENTITY(pa_pdc_cell.mod_info) != PAT_ENTITY_LBA) { + panic("pdc_pat_cell_module() entity returned != PAT_ENTITY_LBA!\n"); + } + + /* + ** Inspect the resources PAT tells us about + */ + for (i = 0; i < pa_count; i++) { + struct { + unsigned long type; + unsigned long start; + unsigned long end; /* aka finish */ + } *p; + struct resource *r; + + p = (void *) &(pa_pdc_cell.mod[2+i*3]); + + /* Convert the PAT range data to PCI "struct resource" */ + switch(p->type & 0xff) { + case PAT_PBNUM: + lba_dev->hba.bus_num.start = p->start; + lba_dev->hba.bus_num.end = p->end; + break; + case PAT_LMMIO: + /* used to fix up pre-initialized MEM BARs */ + lba_dev->lmmio_base = p->start; + + r = &(lba_dev->hba.mem_space); + r->name = "LBA LMMIO"; + r->start = p->start; + r->end = p->end; + r->flags = IORESOURCE_MEM; + r->parent = r->sibling = r->child = NULL; + break; + case PAT_GMMIO: + printk(KERN_WARNING MODULE_NAME + " range[%d] : ignoring GMMIO (0x%lx)\n", + i, p->start); + lba_dev->gmmio_base = p->start; + break; + case PAT_NPIOP: + printk(KERN_WARNING MODULE_NAME + " range[%d] : ignoring NPIOP (0x%lx)\n", + i, p->start); + break; + case PAT_PIOP: + /* + ** Postable I/O port space is per PCI host adapter. + */ + + /* save base of 64MB PIOP region */ + lba_dev->iop_base = p->start; + + r = &(lba_dev->hba.io_space); + r->name = "LBA I/O Port"; + r->start = lba_dev->hba.hba_num << 16; + r->end = r->start + 0xffffUL; + r->flags = IORESOURCE_IO; + r->parent = r->sibling = r->child = NULL; + break; + default: + printk(KERN_WARNING MODULE_NAME + " range[%d] : unknown pat range type (0x%lx)\n", + i, p->type & 0xff); + break; + } + } +} +#endif /* __LP64__ */ + + +static void +lba_legacy_resources( struct hp_device *d, struct lba_device *lba_dev) +{ + int lba_num; + struct resource *r; +#ifdef __LP64__ + /* + ** Used to sign extend instead BAR values are only 32-bit. + ** 64-bit BARs have the upper 32-bit's zero'd by firmware. + ** "Sprockets" PDC initializes for 32-bit OS. + */ + lba_dev->lmmio_base = 0xffffffff00000000UL; +#endif + + /* + ** With "legacy" firmware, the lowest byte of FW_SCRATCH + ** represents bus->secondary and the second byte represents + ** bus->subsidiary (i.e. highest PPB programmed by firmware). + ** PCI bus walk *should* end up with the same result. + ** FIXME: But we don't have sanity checks in PCI or LBA. + */ + lba_num = READ_REG32(d->hpa + LBA_FW_SCRATCH); + r = &(lba_dev->hba.bus_num); + r->name = "LBA PCI Busses"; + r->start = lba_num & 0xff; + r->end = (lba_num>>8) & 0xff; + + /* Set up local PCI Bus resources - we don't really need + ** them for Legacy boxes but it's nice to see in /proc. + */ + r = &(lba_dev->hba.mem_space); + r->name = "LBA PCI LMMIO"; + r->flags = IORESOURCE_MEM; + r->start = READ_REG32(d->hpa + LBA_LMMIO_BASE); + r->end = r->start + ~ (READ_REG32(d->hpa + LBA_LMMIO_MASK)); + + r = &(lba_dev->hba.io_space); + r->name = "LBA PCI I/O Ports"; + r->flags = IORESOURCE_IO; + r->start = READ_REG32(d->hpa + LBA_IOS_BASE); + r->end = r->start + (READ_REG32(d->hpa + LBA_IOS_MASK) ^ 0xffff); + + lba_num = lba_dev->hba.hba_num << 16; + r->start |= lba_num; + r->end |= lba_num; +} + + +/************************************************************************** +** +** LBA initialization code (HW and SW) +** +** o identify LBA chip itself +** o initialize LBA chip modes (HardFail) +** o FIXME: initialize DMA hints for reasonable defaults +** o enable configuration functions +** o call pci_register_ops() to discover devs (fixup/fixup_bus get invoked) +** +**************************************************************************/ + +static void +lba_hw_init(struct lba_device *d) +{ + u32 stat; + + /* Set HF mode as the default (vs. -1 mode). */ + stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL); + WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL); + + /* + ** FIXME: Hint registers are programmed with default hint + ** values by firmware. Hints should be sane even if we + ** can't reprogram them the way drivers want. + */ +} + + + +static void +lba_common_init(struct lba_device *lba_dev) +{ + pci_bios = &lba_bios_ops; + pcibios_register_hba((struct pci_hba_data *)lba_dev); + lba_dev->lba_lock = SPIN_LOCK_UNLOCKED; + + /* + ** Set flags which depend on hw_rev + */ + if (!LBA_TR4PLUS(lba_dev)) { + lba_dev->flags |= LBA_FLAG_NO_DMA_DURING_CFG; + } +} + + + +/* +** Determine if lba should claim this chip (return 0) or not (return 1). +** If so, initialize the chip and tell other partners in crime they +** have work to do. +*/ +static __init int +lba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +{ + struct lba_device *lba_dev; + struct pci_bus *lba_bus; + u32 func_class; + void *tmp_obj; + + /* from drivers/pci/setup-bus.c */ + extern void __init pbus_set_ranges(struct pci_bus *, struct pbus_set_ranges_data *); + + /* Read HW Rev First */ + func_class = READ_REG32(d->hpa + LBA_FCLASS); + func_class &= 0xf; + + switch (func_class) { + case 0: dri->version = "TR1.0"; break; + case 1: dri->version = "TR2.0"; break; + case 2: dri->version = "TR2.1"; break; + case 3: dri->version = "TR2.2"; break; + case 4: dri->version = "TR3.0"; break; + case 5: dri->version = "TR4.0"; break; + default: dri->version = "TR4+"; + } + + printk("%s version %s (0x%x) found at 0x%p\n", dri->name, dri->version, func_class & 0xf, d->hpa); + + /* Just in case we find some prototypes... */ + if (func_class < 2) { + printk(KERN_WARNING "Can't support LBA older than TR2.1 " + "- continuing under adversity.\n"); + } + + /* + ** Tell I/O SAPIC driver we have a IRQ handler/region. + */ + tmp_obj = iosapic_register(d->hpa+LBA_IOSAPIC_BASE); + if (NULL == tmp_obj) { + /* iosapic may have failed. But more likely the + ** slot isn't occupied and thus has no IRT entries. + ** iosapic_register looks for this iosapic in the IRT + ** before bothering to allocating data structures + ** we don't need. + */ + DBG(KERN_WARNING MODULE_NAME ": iosapic_register says not used\n"); + return (1); + } + + lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL); + if (NULL == lba_dev) + { + printk("lba_init_chip - couldn't alloc lba_device\n"); + return(1); + } + + memset(lba_dev, 0, sizeof(struct lba_device)); + + + /* ---------- First : initialize data we already have --------- */ + + /* + ** Need hw_rev to adjust configuration space behavior. + ** LBA_TR4PLUS macro uses hw_rev field. + */ + lba_dev->hw_rev = func_class; + + lba_dev->hba.base_addr = d->hpa; /* faster access */ + lba_dev->iosapic_obj = tmp_obj; /* save interrupt handle */ + + /* ------------ Second : initialize common stuff ---------- */ + lba_common_init(lba_dev); + lba_hw_init(lba_dev); + + /* ---------- Third : setup I/O Port and MMIO resources --------- */ +#ifdef __LP64__ + + if (pdc_pat) { + /* PDC PAT firmware uses PIOP region of GMMIO space. */ + pci_port = &lba_pat_port_ops; + + /* Go ask PDC PAT what resources this LBA has */ + lba_pat_resources(d, lba_dev); + + } else { +#endif + /* Sprockets PDC uses NPIOP region */ + pci_port = &lba_astro_port_ops; + + /* Poke the chip a bit for /proc output */ + lba_legacy_resources(d, lba_dev); +#ifdef __LP64__ + } +#endif + + /* + ** Tell PCI support another PCI bus was found. + ** Walks PCI bus for us too. + */ + lba_bus = lba_dev->hba.hba_bus = + pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev); + +#ifdef __LP64__ + if (pdc_pat) { + + /* determine window sizes needed by PCI-PCI bridges */ + DBG_PAT("LBA pcibios_size_bridge()\n"); + pcibios_size_bridge(lba_bus, NULL); + + /* assign resources to un-initialized devices */ + DBG_PAT("LBA pcibios_assign_unassigned_resources()\n"); + pcibios_assign_unassigned_resources(lba_bus); + +#ifdef DEBUG_LBA_PAT + DBG_PAT("\nLBA PIOP resource tree\n"); + lba_dump_res(&lba_dev->hba.io_space, 2); + DBG_PAT("\nLBA LMMIO resource tree\n"); + lba_dump_res(&lba_dev->hba.mem_space, 2); +#endif + + /* program *all* PCI-PCI bridge range registers */ + DBG_PAT("LBA pbus_set_ranges()\n"); + pbus_set_ranges(lba_bus, NULL); + } +#endif /* __LP64__ */ + + /* + ** Once PCI register ops has walked the bus, access to config + ** space is restricted. Avoids master aborts on config cycles. + ** Early LBA revs go fatal on *any* master abort. + */ + if (!LBA_TR4PLUS(lba_dev)) { + lba_dev->flags |= LBA_FLAG_SKIP_PROBE; + } + + /* Whew! Finally done! Tell services we got this one covered. */ + return 0; +} + + +/* +** Initialize the IBASE/IMASK registers for LBA (Elroy). +** Only called from sba_iommu.c initialization sequence. +*/ +void lba_init_iregs(void *sba_hpa, u32 ibase, u32 imask) +{ + extern struct pci_hba_data *hba_list; /* arch/parisc/kernel/pci.c */ + struct pci_hba_data *lba; + + imask <<= 2; /* adjust for hints - 2 more bits */ + + ASSERT((ibase & 0x003fffff) == 0); + ASSERT((imask & 0x003fffff) == 0); + + /* FIXME: sba_hpa is intended to search some table to + ** determine which LBA's belong to the caller's SBA. + ** IS_ASTRO: just assume only one SBA for now. + */ + ASSERT(NULL != hba_list); + DBG(KERN_DEBUG "%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask); + + for (lba = hba_list; NULL != lba; lba = lba->next) { + DBG(KERN_DEBUG "%s() base_addr %p\n", __FUNCTION__, lba->base_addr); + WRITE_REG32( imask, lba->base_addr + LBA_IMASK); + WRITE_REG32( ibase, lba->base_addr + LBA_IBASE); + } + DBG(KERN_DEBUG "%s() done\n", __FUNCTION__); +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/led.c linux/arch/parisc/kernel/led.c --- v2.4.0-test11/linux/arch/parisc/kernel/led.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/led.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,451 @@ +/* + * Chassis LCD/LED driver for HP-PARISC workstations + * + * (c) Copyright 2000 Red Hat Software + * (c) Copyright 2000 Helge Deller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* HZ */ +#include + + +/* define to disable all LED functions */ +#undef DISABLE_LEDS + + +#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF) + + +struct lcd_block { + unsigned char command; /* stores the command byte */ + unsigned char on; /* value for turning LED on */ + unsigned char off; /* value for turning LED off */ +}; + +/* Structure returned by PDC_RETURN_CHASSIS_INFO */ +struct pdc_chassis_lcd_info_ret_block { + unsigned long model:16; /* DISPLAY_MODEL_XXXX (see below) */ + unsigned long lcd_width:16; /* width of the LCD in chars (DISPLAY_MODEL_LCD only) */ + char *lcd_cmd_reg_addr; /* ptr to LCD cmd-register & data ptr for LED */ + char *lcd_data_reg_addr; /* ptr to LCD data-register (LCD only) */ + unsigned int min_cmd_delay; /* delay in uS after cmd-write (LCD only) */ + unsigned char reset_cmd1; /* command #1 for writing LCD string (LCD only) */ + unsigned char reset_cmd2; /* command #2 for writing LCD string (LCD only) */ + unsigned char act_enable; /* 0 = no activity (LCD only) */ + struct lcd_block heartbeat; + struct lcd_block disk_io; + struct lcd_block lan_rcv; + struct lcd_block lan_tx; + char _pad; +}; + +/* values for pdc_chassis_lcd_info_ret_block.model: */ +#define DISPLAY_MODEL_LCD 0 /* KittyHawk LED or LCD */ +#define DISPLAY_MODEL_NONE 1 /* no LED or LCD */ +#define DISPLAY_MODEL_LASI 2 /* LASI style 8 bit LED */ +#define DISPLAY_MODEL_OLD_ASP 0x7F /* faked: ASP style 8 x 1 bit LED (only very old ASP versions) */ + + +/* LCD_CMD and LCD_DATA for KittyHawk machines */ +#ifdef __LP64__ +#define KITTYHAWK_LCD_CMD 0xfffffffff0190000L +#else +#define KITTYHAWK_LCD_CMD 0xf0190000 +#endif +#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD + 1) + + +/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's */ +static struct pdc_chassis_lcd_info_ret_block +lcd_info __attribute__((aligned(8))) = +{ + model:DISPLAY_MODEL_LCD, + lcd_width:16, + lcd_cmd_reg_addr:(char *) KITTYHAWK_LCD_CMD, + lcd_data_reg_addr:(char *) KITTYHAWK_LCD_DATA, + min_cmd_delay:40, + reset_cmd1:0x80, + reset_cmd2:0xc0, +}; + + +/* direct access to some of the lcd_info variables */ +#define LCD_CMD_REG lcd_info.lcd_cmd_reg_addr +#define LCD_DATA_REG lcd_info.lcd_data_reg_addr +#define LED_DATA_REG lcd_info.lcd_cmd_reg_addr /* LASI & ASP only */ + + + + +/* + ** + ** led_ASP_driver() + ** + */ +#define LED_DATA 0x01 /* data to shift (0:on 1:off) */ +#define LED_STROBE 0x02 /* strobe to clock data */ +static void led_ASP_driver(unsigned char leds) +{ + int i; + + leds = ~leds; + for (i = 0; i < 8; i++) { + unsigned char value; + value = (leds & 0x80) >> 7; + gsc_writeb( value, LED_DATA_REG ); + gsc_writeb( value | LED_STROBE, LED_DATA_REG ); + leds <<= 1; + } +} + + +/* + ** + ** led_LASI_driver() + ** + */ +static void led_LASI_driver(unsigned char leds) +{ + leds = ~leds; + gsc_writeb( leds, LED_DATA_REG ); +} + + +/* + ** + ** led_LCD_driver() + ** + ** The logic of the LCD driver is, that we write at every interrupt + ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers. + ** That way we don't need to let this interrupt routine busywait + ** the "min_cmd_delay", since idlewaiting in an interrupt-routine is + ** allways a BAD IDEA ! + ** + ** TODO: check the value of "min_cmd_delay" against the value of HZ. + ** + */ + +static void led_LCD_driver(unsigned char leds) +{ + static int last_index; /* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */ + static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */ + struct lcd_block *block_ptr; + int value; + + // leds = ~leds; /* needed ? */ + + switch (last_index) { + case 0: block_ptr = &lcd_info.heartbeat; + value = leds & LED_HEARTBEAT; + break; + case 1: block_ptr = &lcd_info.disk_io; + value = leds & LED_DISK_IO; + break; + case 2: block_ptr = &lcd_info.lan_rcv; + value = leds & LED_LAN_RCV; + break; + case 3: block_ptr = &lcd_info.lan_tx; + value = leds & LED_LAN_TX; + break; + default: /* should never happen: */ + BUG(); + return; + } + + if (last_was_cmd) { + /* write the value to the LCD data port */ + gsc_writeb( value ? block_ptr->on : block_ptr->off, LCD_DATA_REG ); + } else { + /* write the command-byte to the LCD command register */ + gsc_writeb( block_ptr->command, LCD_CMD_REG ); + } + + /* now update the vars for the next interrupt iteration */ + if (++last_was_cmd == 2) { + last_was_cmd = 0; + if (++last_index == 4) + last_index = 0; + } +} + + + +static char currentleds; /* stores current value of the LEDs */ + +static void (*led_func_ptr) (unsigned char); /* ptr to LCD/LED-specific function */ + +/* + ** led_interrupt_func() + ** + ** is called at every timer interrupt from time.c, + ** updates the chassis LCD/LED + */ + +#define HEARTBEAT_LEN (HZ/16) + +void led_interrupt_func(void) +{ +#ifndef DISABLE_LEDS + static int count; + static int lastleds = -1; + static int nr; + + /* exit, if not initialized */ + if (!led_func_ptr) + return; + + /* increment the local counter */ + if (count == (HZ-1)) + count = 0; + else + count++; + + /* calculate the Heartbeat */ + if ((count % (HZ/2)) < HEARTBEAT_LEN) + currentleds |= LED_HEARTBEAT; + else + currentleds &= ~LED_HEARTBEAT; + + /* roll LEDs 0..2 */ + if (count == 0) { + if (nr++ >= 2) + nr = 0; + currentleds &= ~7; + currentleds |= (1 << nr); + } + + /* now update the LEDs */ + if (currentleds != lastleds) { + led_func_ptr(currentleds); + lastleds = currentleds; + } +#endif +} + + +/* + ** register_led_driver() + ** + ** All information in lcd_info needs to be set up prior + ** calling this function. + */ + +static void __init register_led_driver(void) +{ +#ifndef DISABLE_LEDS + switch (lcd_info.model) { + case DISPLAY_MODEL_LCD: + printk(KERN_INFO "LCD display at (%p,%p)\n", + LCD_CMD_REG , LCD_DATA_REG); + led_func_ptr = led_LCD_driver; + break; + + case DISPLAY_MODEL_LASI: + printk(KERN_INFO "LED display at %p\n", + LED_DATA_REG); + led_func_ptr = led_LASI_driver; + break; + + case DISPLAY_MODEL_OLD_ASP: + printk(KERN_INFO "LED (ASP-style) display at %p\n", + LED_DATA_REG); + led_func_ptr = led_ASP_driver; + break; + + default: + printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n", + __FUNCTION__, lcd_info.model); + return; + } +#endif +} + +/* + * XXX - could this move to lasi.c ?? + */ + +/* + ** lasi_led_init() + ** + ** lasi_led_init() is called from lasi.c with the base hpa + ** of the lasi controller chip. + ** Since Mirage and Electra machines use a different LED + ** address register, we need to check for these machines + ** explicitly. + */ + +#ifdef CONFIG_GSC_LASI +void __init lasi_led_init(unsigned long lasi_hpa) +{ + if (lcd_info.model != DISPLAY_MODEL_NONE || + lasi_hpa == 0) + return; + + printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION); + + /* Mirage and Electra machines need special offsets */ + switch (CPU_HVERSION) { + case 0x60A: /* Mirage Jr (715/64) */ + case 0x60B: /* Mirage 100 */ + case 0x60C: /* Mirage 100+ */ + case 0x60D: /* Electra 100 */ + case 0x60E: /* Electra 120 */ + LED_DATA_REG = (char *) (lasi_hpa - 0x00020000); + break; + default: + LED_DATA_REG = (char *) (lasi_hpa + 0x0000C000); + break; + } /* switch() */ + + lcd_info.model = DISPLAY_MODEL_LASI; + register_led_driver(); +} +#endif + + +/* + ** asp_led_init() + ** + ** asp_led_init() is called from asp.c with the ptr + ** to the LED display. + */ + +#ifdef CONFIG_GSC_LASI +void __init asp_led_init(unsigned long led_ptr) +{ + if (lcd_info.model != DISPLAY_MODEL_NONE || + led_ptr == 0) + return; + + lcd_info.model = DISPLAY_MODEL_OLD_ASP; + LED_DATA_REG = (char *) led_ptr; + + register_led_driver(); +} + +#endif + + + +/* + ** register_led_regions() + ** + ** Simple function, which registers the LCD/LED regions for /procfs. + ** At bootup - where the initialisation of the LCD/LED normally happens - + ** not all internal structures of request_region() are properly set up, + ** so that we delay the registration until busdevice.c is executed. + ** + */ + +void __init register_led_regions(void) +{ + switch (lcd_info.model) { + case DISPLAY_MODEL_LCD: + request_region((unsigned long)LCD_CMD_REG, 1, "lcd_cmd"); + request_region((unsigned long)LCD_DATA_REG, 1, "lcd_data"); + break; + case DISPLAY_MODEL_LASI: + case DISPLAY_MODEL_OLD_ASP: + request_region((unsigned long)LED_DATA_REG, 1, "led_data"); + break; + } +} + + + +/* + ** led_init() + ** + ** led_init() is called very early in the bootup-process from setup.c + ** and asks the PDC for an usable chassis LCD or LED. + ** If the PDC doesn't return any info, then the LED + ** is detected by lasi.c or asp.c and registered with the + ** above functions lasi_led_init() or asp_led_init(). + ** KittyHawk machines have often a buggy PDC, so that + ** we explicitly check for those machines here. + */ + +int __init led_init(void) +{ +#ifndef DISABLE_LEDS + long pdc_result[32]; + + printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION); + + /* Work around the buggy PDC of KittyHawk-machines */ + switch (CPU_HVERSION) { + case 0x580: /* KittyHawk DC2-100 (K100) */ + case 0x581: /* KittyHawk DC3-120 (K210) */ + case 0x582: /* KittyHawk DC3 100 (K400) */ + case 0x583: /* KittyHawk DC3 120 (K410) */ + case 0x58B: /* KittyHawk DC2 100 (K200) */ + printk("%s: KittyHawk-Machine found !!\n", __FUNCTION__); + goto found; /* use the preinitialized values of lcd_info */ + + default: + break; + } + + /* initialize pdc_result, so we can check the return values of pdc_chassis_info() */ + pdc_result[0] = pdc_result[1] = 0; + + if (pdc_chassis_info(&pdc_result, &lcd_info, sizeof(lcd_info)) == PDC_OK) { + printk("%s: chassis info: model %d, ret0=%d, ret1=%d\n", + __FUNCTION__, lcd_info.model, pdc_result[0], pdc_result[1]); + + /* check the results. Some machines have a buggy PDC */ + if (pdc_result[0] <= 0 || pdc_result[0] != pdc_result[1]) + goto not_found; + + switch (lcd_info.model) { + case DISPLAY_MODEL_LCD: /* LCD display */ + if (pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) + && pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) - 1) + goto not_found; + printk("%s: min_cmd_delay = %d uS\n", + __FUNCTION__, lcd_info.min_cmd_delay); + break; + + case DISPLAY_MODEL_NONE: /* no LED or LCD available */ + goto not_found; + + case DISPLAY_MODEL_LASI: /* Lasi style 8 bit LED display */ + if (pdc_result[0] != 8 && pdc_result[0] != 32) + goto not_found; + break; + + default: + printk(KERN_WARNING "Unknown LCD/LED model %d\n", + lcd_info.model); + goto not_found; + } /* switch() */ + +found: + /* register the LCD/LED driver */ + register_led_driver(); + return 0; + + } /* if() */ + +not_found: + lcd_info.model = DISPLAY_MODEL_NONE; + return 1; +#endif +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/pa7300lc.c linux/arch/parisc/kernel/pa7300lc.c --- v2.4.0-test11/linux/arch/parisc/kernel/pa7300lc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/pa7300lc.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,54 @@ +/* + * linux/arch/parisc/kernel/pa7300lc.c + * - PA7300LC-specific functions + * + * Copyright (C) 2000 Philipp Rumpf */ + +#include +#include +#include +#include +#include + +/* CPU register indices */ + +#define MIOC_STATUS 0xf040 +#define MIOC_CONTROL 0xf080 +#define MDERRADD 0xf0e0 +#define DMAERR 0xf0e8 +#define DIOERR 0xf0ec +#define HIDMAMEM 0xf0f4 + +/* read CPU Diagnose register index */ +static u32 diag_read(int index) +{ + return 0; +} + +/* this returns the HPA of the CPU it was called on */ +static u32 cpu_hpa(void) +{ + return 0xfffb0000; +} + +static void pa7300lc_lpmc(int code, struct pt_regs *regs) +{ + u32 hpa; + printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id()); + + show_regs(regs); + + hpa = cpu_hpa(); + printk(KERN_WARNING + "MIOC_CONTROL %08x\n" "MIOC_STATUS %08x\n" + "MDERRADD %08x\n" "DMAERR %08x\n" + "DIOERR %08x\n" "HIDMAMEM %08x\n", + gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS), + gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR), + gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM)); +} + +void pa7300lc_init(void) +{ + cpu_lpmc = pa7300lc_lpmc; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/parisc_ksyms.c linux/arch/parisc/kernel/parisc_ksyms.c --- v2.4.0-test11/linux/arch/parisc/kernel/parisc_ksyms.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/parisc_ksyms.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,138 @@ +/* + * Architecture-specific kernel symbols + */ + +#include +#include +#include + +#include +EXPORT_SYMBOL_NOVERS(memscan); +EXPORT_SYMBOL_NOVERS(memset); +EXPORT_SYMBOL(memcmp); +EXPORT_SYMBOL_NOVERS(memcpy); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(strcat); +EXPORT_SYMBOL(strchr); +EXPORT_SYMBOL(strcmp); +EXPORT_SYMBOL(strcpy); +EXPORT_SYMBOL(strlen); +EXPORT_SYMBOL(strncat); +EXPORT_SYMBOL(strncmp); +EXPORT_SYMBOL(strncpy); +EXPORT_SYMBOL(strtok); + +#include +EXPORT_SYMBOL(hppa_dma_ops); + +#include +EXPORT_SYMBOL(enable_irq); +EXPORT_SYMBOL(disable_irq); + +#include +EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(boot_cpu_data); + +#ifdef CONFIG_SMP +EXPORT_SYMBOL(synchronize_irq); + +#include +EXPORT_SYMBOL(kernel_flag); + +#include +EXPORT_SYMBOL(__global_sti); +EXPORT_SYMBOL(__global_cli); +EXPORT_SYMBOL(__global_save_flags); +EXPORT_SYMBOL(__global_restore_flags); + +#endif + +#include +EXPORT_SYMBOL(lcopy_to_user); +EXPORT_SYMBOL(lcopy_from_user); + +/* Needed so insmod can set dp value */ + +extern int data_start; + +EXPORT_SYMBOL_NOVERS(data_start); + +#include +EXPORT_SYMBOL(_gsc_writeb); +EXPORT_SYMBOL(_gsc_writew); +EXPORT_SYMBOL(_gsc_writel); +EXPORT_SYMBOL(_gsc_readb); +EXPORT_SYMBOL(_gsc_readw); +EXPORT_SYMBOL(_gsc_readl); +EXPORT_SYMBOL(busdevice_alloc_irq); +EXPORT_SYMBOL(register_driver); +EXPORT_SYMBOL(gsc_alloc_irq); +EXPORT_SYMBOL(pdc_iodc_read); + +extern void $$divI(void); +extern void $$divU(void); +extern void $$remI(void); +extern void $$remU(void); +extern void $$mulI(void); +extern void $$mulU(void); +extern void $$divU_3(void); +extern void $$divU_5(void); +extern void $$divU_6(void); +extern void $$divU_9(void); +extern void $$divU_10(void); +extern void $$divU_12(void); +extern void $$divU_7(void); +extern void $$divU_14(void); +extern void $$divU_15(void); +extern void $$divI_3(void); +extern void $$divI_5(void); +extern void $$divI_6(void); +extern void $$divI_7(void); +extern void $$divI_9(void); +extern void $$divI_10(void); +extern void $$divI_12(void); +extern void $$divI_14(void); +extern void $$divI_15(void); + +EXPORT_SYMBOL_NOVERS($$divI); +EXPORT_SYMBOL_NOVERS($$divU); +EXPORT_SYMBOL_NOVERS($$remI); +EXPORT_SYMBOL_NOVERS($$remU); +EXPORT_SYMBOL_NOVERS($$mulI); +EXPORT_SYMBOL_NOVERS($$mulU); +EXPORT_SYMBOL_NOVERS($$divU_3); +EXPORT_SYMBOL_NOVERS($$divU_5); +EXPORT_SYMBOL_NOVERS($$divU_6); +EXPORT_SYMBOL_NOVERS($$divU_9); +EXPORT_SYMBOL_NOVERS($$divU_10); +EXPORT_SYMBOL_NOVERS($$divU_12); +EXPORT_SYMBOL_NOVERS($$divU_7); +EXPORT_SYMBOL_NOVERS($$divU_14); +EXPORT_SYMBOL_NOVERS($$divU_15); +EXPORT_SYMBOL_NOVERS($$divI_3); +EXPORT_SYMBOL_NOVERS($$divI_5); +EXPORT_SYMBOL_NOVERS($$divI_6); +EXPORT_SYMBOL_NOVERS($$divI_7); +EXPORT_SYMBOL_NOVERS($$divI_9); +EXPORT_SYMBOL_NOVERS($$divI_10); +EXPORT_SYMBOL_NOVERS($$divI_12); +EXPORT_SYMBOL_NOVERS($$divI_14); +EXPORT_SYMBOL_NOVERS($$divI_15); + +extern void __ashrdi3(void); + +EXPORT_SYMBOL_NOVERS(__ashrdi3); + +#ifdef __LP64__ +extern void __divdi3(void); +extern void __udivdi3(void); + +EXPORT_SYMBOL_NOVERS(__divdi3); +EXPORT_SYMBOL_NOVERS(__udivdi3); +#endif + +#ifndef __LP64__ +extern void $$dyncall(void); +EXPORT_SYMBOL_NOVERS($$dyncall); +#endif + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/pci-dma.c linux/arch/parisc/kernel/pci-dma.c --- v2.4.0-test11/linux/arch/parisc/kernel/pci-dma.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/pci-dma.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,547 @@ +/* +** Dynamic DMA mapping support. +** See Documentation/DMA-mapping.txt for interface definitions. +** +** (c) Copyright 1999,2000 Hewlett-Packard Company +** (c) Copyright 2000 Grant Grundler +** (c) Copyright 2000 Philipp Rumpf +** (c) Copyright 2000 John Marvin +** +** This implementation is for PA-RISC platforms that do not support +** I/O TLBs (aka DMA address translation hardware). +** +** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c. +** (I assume it's from David Mosberger-Tang but there was no Copyright) +** +** AFAIK, all PA7100LC and PA7300LC platforms can use this code. +** All PA2.0 machines but V-class can alias xxx_alloc_consistent() +** to use regular cacheable memory. +** +** - ggg +*/ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include /* get_order */ +#include /* for DMA_CHUNK_SIZE */ + +#include + +static struct proc_dir_entry * proc_gsc_root = NULL; +static int pcxl_proc_info(char *buffer, char **start, off_t offset, int length); +static unsigned long pcxl_used_bytes = 0; +static unsigned long pcxl_used_pages = 0; + +extern unsigned long pcxl_dma_start; /* Start of pcxl dma mapping area */ +static spinlock_t pcxl_res_lock; +static char *pcxl_res_map; +static int pcxl_res_hint; +static int pcxl_res_size; + +#ifdef DEBUG_PCXL_RESOURCE +#define DBG_RES(x...) printk(x) +#else +#define DBG_RES(x...) +#endif + + +/* +** Dump a hex representation of the resource map. +*/ + +#ifdef DUMP_RESMAP +static +void dump_resmap(void) +{ + u_long *res_ptr = (unsigned long *)pcxl_res_map; + u_long i = 0; + + printk("res_map: "); + for(; i < (pcxl_res_size / sizeof(unsigned long)); ++i, ++res_ptr) + printk("%08lx ", *res_ptr); + + printk("\n"); +} +#else +static inline void dump_resmap(void) {;} +#endif + +static int pa11_dma_supported( struct pci_dev *dev, dma_addr_t mask) +{ + return 1; +} + +static inline int map_pte_uncached(pte_t * pte, + unsigned long vaddr, + unsigned long size, unsigned long *paddr_ptr) +{ + unsigned long end; + unsigned long orig_vaddr = vaddr; + + vaddr &= ~PMD_MASK; + end = vaddr + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + if (!pte_none(*pte)) + printk(KERN_ERR "map_pte_uncached: page already exists\n"); + set_pte(pte, __mk_pte(*paddr_ptr, PAGE_KERNEL_UNC)); + pdtlb_kernel(orig_vaddr); + vaddr += PAGE_SIZE; + orig_vaddr += PAGE_SIZE; + (*paddr_ptr) += PAGE_SIZE; + pte++; + } while (vaddr < end); + return 0; +} + +static inline int map_pmd_uncached(pmd_t * pmd, unsigned long vaddr, + unsigned long size, unsigned long *paddr_ptr) +{ + unsigned long end; + unsigned long orig_vaddr = vaddr; + + vaddr &= ~PGDIR_MASK; + end = vaddr + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + pte_t * pte = pte_alloc_kernel(pmd, vaddr); + if (!pte) + return -ENOMEM; + if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr)) + return -ENOMEM; + vaddr = (vaddr + PMD_SIZE) & PMD_MASK; + orig_vaddr += PMD_SIZE; + pmd++; + } while (vaddr < end); + return 0; +} + +static inline int map_uncached_pages(unsigned long vaddr, unsigned long size, + unsigned long paddr) +{ + pgd_t * dir; + unsigned long end = vaddr + size; + + dir = pgd_offset_k(vaddr); + do { + pmd_t *pmd; + + pmd = pmd_alloc_kernel(dir, vaddr); + if (!pmd) + return -ENOMEM; + if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr)) + return -ENOMEM; + vaddr = vaddr + PGDIR_SIZE; + dir++; + } while (vaddr && (vaddr < end)); + return 0; +} + +static inline void unmap_uncached_pte(pmd_t * pmd, unsigned long vaddr, + unsigned long size) +{ + pte_t * pte; + unsigned long end; + unsigned long orig_vaddr = vaddr; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, vaddr); + vaddr &= ~PMD_MASK; + end = vaddr + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + pte_t page = *pte; + pte_clear(pte); + pdtlb_kernel(orig_vaddr); + vaddr += PAGE_SIZE; + orig_vaddr += PAGE_SIZE; + pte++; + if (pte_none(page) || pte_present(page)) + continue; + printk(KERN_CRIT "Whee.. Swapped out page in kernel page table\n"); + } while (vaddr < end); +} + +static inline void unmap_uncached_pmd(pgd_t * dir, unsigned long vaddr, + unsigned long size) +{ + pmd_t * pmd; + unsigned long end; + unsigned long orig_vaddr = vaddr; + + if (pgd_none(*dir)) + return; + if (pgd_bad(*dir)) { + pgd_ERROR(*dir); + pgd_clear(dir); + return; + } + pmd = pmd_offset(dir, vaddr); + vaddr &= ~PGDIR_MASK; + end = vaddr + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + unmap_uncached_pte(pmd, orig_vaddr, end - vaddr); + vaddr = (vaddr + PMD_SIZE) & PMD_MASK; + orig_vaddr += PMD_SIZE; + pmd++; + } while (vaddr < end); +} + +static void unmap_uncached_pages(unsigned long vaddr, unsigned long size) +{ + pgd_t * dir; + unsigned long end = vaddr + size; + + dir = pgd_offset_k(vaddr); + do { + unmap_uncached_pmd(dir, vaddr, end - vaddr); + vaddr = vaddr + PGDIR_SIZE; + dir++; + } while (vaddr && (vaddr < end)); +} + +#define PCXL_SEARCH_LOOP(idx, mask, size) \ + for(; res_ptr < res_end; ++res_ptr) \ + { \ + if(0 == ((*res_ptr) & mask)) { \ + *res_ptr |= mask; \ + idx = (int)((u_long)res_ptr - (u_long)pcxl_res_map); \ + pcxl_res_hint = idx + (size >> 3); \ + goto resource_found; \ + } \ + } + +#define PCXL_FIND_FREE_MAPPING(idx, mask, size) { \ + u##size *res_ptr = (u##size *)&(pcxl_res_map[pcxl_res_hint & ~((size >> 3) - 1)]); \ + u##size *res_end = (u##size *)&pcxl_res_map[pcxl_res_size]; \ + PCXL_SEARCH_LOOP(idx, mask, size); \ + res_ptr = (u##size *)&pcxl_res_map[0]; \ + PCXL_SEARCH_LOOP(idx, mask, size); \ +} + +unsigned long +pcxl_alloc_range(size_t size) +{ + int res_idx; + u_long mask, flags; + unsigned int pages_needed = size >> PAGE_SHIFT; + + ASSERT(pages_needed); + ASSERT((pages_needed * PAGE_SIZE) < DMA_CHUNK_SIZE); + ASSERT(pages_needed < (BITS_PER_LONG - PAGE_SHIFT)); + + mask = (u_long) -1L; + mask >>= BITS_PER_LONG - pages_needed; + + DBG_RES("pcxl_alloc_range() size: %d pages_needed %d pages_mask 0x%08lx\n", + size, pages_needed, mask); + + spin_lock_irqsave(&pcxl_res_lock, flags); + + if(pages_needed <= 8) { + PCXL_FIND_FREE_MAPPING(res_idx, mask, 8); + } else if(pages_needed <= 16) { + PCXL_FIND_FREE_MAPPING(res_idx, mask, 16); + } else if(pages_needed <= 32) { + PCXL_FIND_FREE_MAPPING(res_idx, mask, 32); + } else { + panic(__FILE__ ": pcxl_alloc_range() Too many pages to map.\n"); + } + + dump_resmap(); + panic(__FILE__ ": pcxl_alloc_range() out of dma mapping resources\n"); + +resource_found: + + DBG_RES("pcxl_alloc_range() res_idx %d mask 0x%08lx res_hint: %d\n", + res_idx, mask, pcxl_res_hint); + + pcxl_used_pages += pages_needed; + pcxl_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1); + + spin_unlock_irqrestore(&pcxl_res_lock, flags); + + dump_resmap(); + + /* + ** return the corresponding vaddr in the pcxl dma map + */ + return (pcxl_dma_start + (res_idx << (PAGE_SHIFT + 3))); +} + +#define PCXL_FREE_MAPPINGS(idx, m, size) \ + u##size *res_ptr = (u##size *)&(pcxl_res_map[(idx) + (((size >> 3) - 1) & (~((size >> 3) - 1)))]); \ + ASSERT((*res_ptr & m) == m); \ + *res_ptr &= ~m; + +/* +** clear bits in the pcxl resource map +*/ +static void +pcxl_free_range(unsigned long vaddr, size_t size) +{ + u_long mask, flags; + unsigned int res_idx = (vaddr - pcxl_dma_start) >> (PAGE_SHIFT + 3); + unsigned int pages_mapped = size >> PAGE_SHIFT; + + ASSERT(pages_mapped); + ASSERT((pages_mapped * PAGE_SIZE) < DMA_CHUNK_SIZE); + ASSERT(pages_mapped < (BITS_PER_LONG - PAGE_SHIFT)); + + mask = (u_long) -1L; + mask >>= BITS_PER_LONG - pages_mapped; + + DBG_RES("pcxl_free_range() res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n", + res_idx, size, pages_mapped, mask); + + spin_lock_irqsave(&pcxl_res_lock, flags); + + if(pages_mapped <= 8) { + PCXL_FREE_MAPPINGS(res_idx, mask, 8); + } else if(pages_mapped <= 16) { + PCXL_FREE_MAPPINGS(res_idx, mask, 16); + } else if(pages_mapped <= 32) { + PCXL_FREE_MAPPINGS(res_idx, mask, 32); + } else { + panic(__FILE__ ": pcxl_free_range() Too many pages to unmap.\n"); + } + + pcxl_used_pages -= (pages_mapped ? pages_mapped : 1); + pcxl_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1); + + spin_unlock_irqrestore(&pcxl_res_lock, flags); + + dump_resmap(); +} + +static int __init +pcxl_dma_init(void) +{ + if (pcxl_dma_start == 0) + return 0; + + spin_lock_init(&pcxl_res_lock); + pcxl_res_size = PCXL_DMA_MAP_SIZE >> (PAGE_SHIFT + 3); + pcxl_res_hint = 0; + pcxl_res_map = (char *)__get_free_pages(GFP_KERNEL, + get_order(pcxl_res_size)); + + proc_gsc_root = proc_mkdir("gsc", 0); + create_proc_info_entry("dino", 0, proc_gsc_root, pcxl_proc_info); + return 0; +} + +__initcall(pcxl_dma_init); + +static void * pa11_dma_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +{ + unsigned long vaddr; + unsigned long paddr; + int order; + + order = get_order(size); + size = 1 << (order + PAGE_SHIFT); + vaddr = pcxl_alloc_range(size); + paddr = __get_free_pages(GFP_ATOMIC, order); + flush_kernel_dcache_range(paddr, size); + paddr = __pa(paddr); + map_uncached_pages(vaddr, size, paddr); + *dma_handle = (dma_addr_t) paddr; + +#if 0 +/* This probably isn't needed to support EISA cards. +** ISA cards will certainly only support 24-bit DMA addressing. +** Not clear if we can, want, or need to support ISA. +*/ + if (!hwdev || hwdev->dma_mask != 0xffffffff) + gfp |= GFP_DMA; +#endif + return (void *)vaddr; +} + +static void pa11_dma_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +{ + int order; + + order = get_order(size); + size = 1 << (order + PAGE_SHIFT); + unmap_uncached_pages((unsigned long)vaddr, size); + pcxl_free_range((unsigned long)vaddr, size); + free_pages((unsigned long)__va(dma_handle), order); +} + +static dma_addr_t pa11_dma_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) { + printk(KERN_ERR "pa11_dma_map_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0)); + BUG(); + } + + flush_kernel_dcache_range((unsigned long) addr, size); + return virt_to_phys(addr); +} + +static void pa11_dma_unmap_single(struct pci_dev *dev, dma_addr_t dma_handle, size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) { + printk(KERN_ERR "pa11_dma_unmap_single(PCI_DMA_NONE) called by %p\n", __builtin_return_address(0)); + BUG(); + } + + if (direction == PCI_DMA_TODEVICE) + return; + + /* + * For PCI_DMA_FROMDEVICE this flush is not necessary for the + * simple map/unmap case. However, it IS necessary if if + * pci_dma_sync_single has been called and the buffer reused. + */ + + flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size); + return; +} + +static int pa11_dma_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + int i; + + if (direction == PCI_DMA_NONE) + BUG(); + + for (i = 0; i < nents; i++, sglist++ ) { + sg_dma_address(sglist) = (dma_addr_t) virt_to_phys(sglist->address); + sg_dma_len(sglist) = sglist->length; + flush_kernel_dcache_range((unsigned long)sglist->address, + sglist->length); + } + return nents; +} + +static void pa11_dma_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + int i; + + if (direction == PCI_DMA_NONE) + BUG(); + + if (direction == PCI_DMA_TODEVICE) + return; + + /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */ + + for (i = 0; i < nents; i++, sglist++ ) + flush_kernel_dcache_range((unsigned long) sglist->address, sglist->length); + return; +} + +static void pa11_dma_sync_single(struct pci_dev *dev, dma_addr_t dma_handle, size_t size, int direction) +{ + if (direction == PCI_DMA_NONE) + BUG(); + + flush_kernel_dcache_range((unsigned long) phys_to_virt(dma_handle), size); +} + +static void pa11_dma_sync_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + int i; + + /* once we do combining we'll need to use phys_to_virt(sg_dma_address(sglist)) */ + + for (i = 0; i < nents; i++, sglist++ ) + flush_kernel_dcache_range((unsigned long) sglist->address, sglist->length); +} + +struct pci_dma_ops pcxl_dma_ops = { + pa11_dma_supported, /* dma_support */ + pa11_dma_alloc_consistent, + pa11_dma_free_consistent, + pa11_dma_map_single, /* map_single */ + pa11_dma_unmap_single, /* unmap_single */ + pa11_dma_map_sg, /* map_sg */ + pa11_dma_unmap_sg, /* unmap_sg */ + pa11_dma_sync_single, /* dma_sync_single */ + pa11_dma_sync_sg /* dma_sync_sg */ +}; + +static void *fail_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + return NULL; +} + +static void fail_free_consistent(struct pci_dev *dev, size_t size, + void *vaddr, dma_addr_t iova) +{ + return; +} + +struct pci_dma_ops pcx_dma_ops = { + pa11_dma_supported, /* dma_support */ + fail_alloc_consistent, + fail_free_consistent, + pa11_dma_map_single, /* map_single */ + pa11_dma_unmap_single, /* unmap_single */ + pa11_dma_map_sg, /* map_sg */ + pa11_dma_unmap_sg, /* unmap_sg */ + pa11_dma_sync_single, /* dma_sync_single */ + pa11_dma_sync_sg /* dma_sync_sg */ +}; + +struct pci_dma_ops *hppa_dma_ops; + +static int pcxl_proc_info(char *buf, char **start, off_t offset, int len) +{ + u_long i = 0; + unsigned long *res_ptr = (u_long *)pcxl_res_map; + unsigned long total_pages = pcxl_res_size << 3; /* 8 bits per byte */ + + sprintf(buf, "\nDMA Mapping Area size : %d bytes (%d pages)\n", + PCXL_DMA_MAP_SIZE, + (pcxl_res_size << 3) ); /* 1 bit per page */ + + sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", + buf, pcxl_res_size, pcxl_res_size << 3); /* 8 bits per byte */ + + strcat(buf, " total: free: used: % used:\n"); + sprintf(buf, "%sblocks %8d %8ld %8ld %8ld%%\n", buf, pcxl_res_size, + pcxl_res_size - pcxl_used_bytes, pcxl_used_bytes, + (pcxl_used_bytes * 100) / pcxl_res_size); + + sprintf(buf, "%spages %8ld %8ld %8ld %8ld%%\n", buf, total_pages, + total_pages - pcxl_used_pages, pcxl_used_pages, + (pcxl_used_pages * 100 / total_pages)); + + strcat(buf, "\nResource bitmap:"); + + for(; i < (pcxl_res_size / sizeof(u_long)); ++i, ++res_ptr) { + if ((i & 7) == 0) + strcat(buf,"\n "); + sprintf(buf, "%s %08lx", buf, *res_ptr); + } + strcat(buf, "\n"); + return strlen(buf); +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/pci.c linux/arch/parisc/kernel/pci.c --- v2.4.0-test11/linux/arch/parisc/kernel/pci.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/pci.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,535 @@ +/* $Id: pci.c,v 1.6 2000/01/29 00:12:05 grundler Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1997, 1998 Ralf Baechle + * Copyright (C) 1999 SuSE GmbH + * Copyright (C) 1999 Hewlett-Packard Company + * Copyright (C) 1999, 2000 Grant Grundler + */ +#include +#include +#include +#include /* for __init and __devinit */ +#include +#include +#include /* for memcpy() */ + +#include + +#ifdef CONFIG_PCI + +#undef DEBUG_RESOURCES + +#ifdef DEBUG_RESOURCES +#define DBG_RES(x...) printk(x) +#else +#define DBG_RES(x...) +#endif + +/* To be used as: mdelay(pci_post_reset_delay); +** +** post_reset is the time the kernel should stall to prevent anyone from +** accessing the PCI bus once #RESET is de-asserted. +** PCI spec somewhere says 1 second but with multi-PCI bus systems, +** this makes the boot time much longer than necessary. +** 20ms seems to work for all the HP PCI implementations to date. +*/ +int pci_post_reset_delay = 50; + +struct pci_port_ops *pci_port; +struct pci_bios_ops *pci_bios; + +struct pci_hba_data *hba_list = NULL; +int hba_count = 0; + +/* +** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data. +*/ +#define PCI_HBA_MAX 32 +static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX]; + + +/******************************************************************** +** +** I/O port space support +** +*********************************************************************/ + +#define PCI_PORT_HBA(a) ((a)>>16) +#define PCI_PORT_ADDR(a) ((a) & 0xffffUL) + +/* KLUGE : inb needs to be defined differently for PCI devices than +** for other bus interfaces. Doing this at runtime sucks but is the +** only way one driver binary can support devices on different bus types. +** +*/ + +#define PCI_PORT_IN(type, size) \ +u##size in##type (int addr) \ +{ \ + int b = PCI_PORT_HBA(addr); \ + u##size d = (u##size) -1; \ + ASSERT(pci_port); /* make sure services are defined */ \ + ASSERT(parisc_pci_hba[b]); /* make sure ioaddr are "fixed up" */ \ + if (parisc_pci_hba[b] == NULL) { \ + printk(KERN_WARNING "\nPCI Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \ + } else { \ + d = pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \ + } \ + return d; \ +} + +PCI_PORT_IN(b, 8) +PCI_PORT_IN(w, 16) +PCI_PORT_IN(l, 32) + + +#define PCI_PORT_OUT(type, size) \ +void out##type (u##size d, int addr) \ +{ \ + int b = PCI_PORT_HBA(addr); \ + ASSERT(pci_port); \ + pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \ +} + +PCI_PORT_OUT(b, 8) +PCI_PORT_OUT(w, 16) +PCI_PORT_OUT(l, 32) + + + +/* + * BIOS32 replacement. + */ +void pcibios_init(void) +{ + ASSERT(pci_bios != NULL); + + if (pci_bios) + { + if (pci_bios->init) { + (*pci_bios->init)(); + } else { + printk(KERN_WARNING "pci_bios != NULL but init() is!\n"); + } + } +} + + +/* Called from pci_do_scan_bus() *after* walking a bus but before walking PPBs. */ +void pcibios_fixup_bus(struct pci_bus *bus) +{ + ASSERT(pci_bios != NULL); + + /* If this is a bridge, get the current bases */ + if (bus->self) { + pci_read_bridge_bases(bus); + } + + if (pci_bios) { + if (pci_bios->fixup_bus) { + (*pci_bios->fixup_bus)(bus); + } else { + printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n"); + } + } +} + + +char *pcibios_setup(char *str) +{ + return str; +} + +#endif /* defined(CONFIG_PCI) */ + + + +/* ------------------------------------------------------------------- +** linux-2.4: NEW STUFF +** -------------------- +*/ + +/* +** Used in drivers/pci/quirks.c +*/ +struct pci_fixup pcibios_fixups[] = { {0} }; + + +/* +** called by drivers/pci/setup.c:pdev_fixup_irq() +*/ +void __devinit pcibios_update_irq(struct pci_dev *dev, int irq) +{ +/* +** updates IRQ_LINE cfg register to reflect PCI-PCI bridge skewing. +** +** Calling path for Alpha is: +** alpha/kernel/pci.c:common_init_pci(swizzle_func, pci_map_irq_func ) +** drivers/pci/setup.c:pci_fixup_irqs() +** drivers/pci/setup.c:pci_fixup_irq() (for each PCI device) +** invoke swizzle and map functions +** alpha/kernel/pci.c:pcibios_update_irq() +** +** Don't need this for PA legacy PDC systems. +** +** On PAT PDC systems, We only support one "swizzle" for any number +** of PCI-PCI bridges deep. That's how bit3 PCI expansion chassis +** are implemented. The IRQ lines are "skewed" for all devices but +** *NOT* routed through the PCI-PCI bridge. Ie any device "0" will +** share an IRQ line. Legacy PDC is expecting this IRQ line routing +** as well. +** +** Unfortunately, PCI spec allows the IRQ lines to be routed +** around the PCI bridge as long as the IRQ lines are skewed +** based on the device number...... +** +** Lastly, dino.c might be able to use pci_fixup_irq() to +** support RS-232 and PS/2 children. Not sure how but it's +** something to think about. +*/ +} + + +/* ------------------------------------ +** +** Program one BAR in PCI config space. +** +** ------------------------------------ +** PAT PDC systems need this routine. PA legacy PDC does not. +** +** Used by alpha/arm: +** alpha/kernel/pci.c:common_init_pci() +** (or arm/kernel/pci.c:pcibios_init()) +** drivers/pci/setup.c:pci_assign_unassigned_resources() +** drivers/pci/setup.c:pdev_assign_unassigned_resources() +** arch//kernel/pci.c:pcibios_update_resource() +** +** When BAR's are configured by linux, this routine +** will update configuration space with the "normalized" +** address. "root" indicates where the range starts and res +** is some portion of that range. +** +** For all PA-RISC systems except V-class, root->start would be zero. +** +** PAT PDC can tell us which MMIO ranges are available or already in use. +** I/O port space and such are not memory mapped anyway for PA-Risc. +*/ +void __devinit +pcibios_update_resource( + struct pci_dev *dev, + struct resource *root, + struct resource *res, + int barnum + ) +{ + int where; + u32 barval = 0; + + DBG_RES("pcibios_update_resource(%s, ..., %d) [%lx,%lx]/%x\n", + dev->slot_name, + barnum, res->start, res->end, (int) res->flags); + + if (barnum >= PCI_BRIDGE_RESOURCES) { + /* handled in pbus_set_ranges_data() */ + return; + } + + if (barnum == PCI_ROM_RESOURCE) { + where = PCI_ROM_ADDRESS; + } else { + /* 0-5 standard PCI "regions" */ + where = PCI_BASE_ADDRESS_0 + (barnum * 4); + } + + if (res->flags & IORESOURCE_IO) { + barval = PCI_PORT_ADDR(res->start); + } else if (res->flags & IORESOURCE_MEM) { + /* This should work for VCLASS too */ + barval = res->start & 0xffffffffUL; + } else { + panic("pcibios_update_resource() WTF? flags not IO or MEM"); + } + + pci_write_config_dword(dev, where, barval); + +/* XXX FIXME - Elroy does support 64-bit (dual cycle) addressing. +** But at least one device (Symbios 53c896) which has 64-bit BAR +** doesn't actually work right with dual cycle addresses. +** So ignore the whole mess for now. +*/ + + if ((res->flags & (PCI_BASE_ADDRESS_SPACE + | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) + == (PCI_BASE_ADDRESS_SPACE_MEMORY + | PCI_BASE_ADDRESS_MEM_TYPE_64)) { + pci_write_config_dword(dev, where+4, 0); + printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name); + } +} + +/* +** Called by pci_set_master() - a driver interface. +** +** Legacy PDC guarantees to set: +** Map Memory BAR's into PA IO space. +** Map Expansion ROM BAR into one common PA IO space per bus. +** Map IO BAR's into PCI IO space. +** Command (see below) +** Cache Line Size +** Latency Timer +** Interrupt Line +** PPB: secondary latency timer, io/mmio base/limit, +** bus numbers, bridge control +** +*/ +void +pcibios_set_master(struct pci_dev *dev) +{ + u8 lat; + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + if (lat >= 16) return; + + /* + ** HP generally has fewer devices on the bus than other architectures. + */ + printk("PCIBIOS: Setting latency timer of %s to 128\n", dev->slot_name); + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80); +} + + +/* +** called by drivers/pci/setup-res.c:pbus_set_ranges(). +*/ +void pcibios_fixup_pbus_ranges( + struct pci_bus *bus, + struct pbus_set_ranges_data *ranges + ) +{ + /* + ** I/O space may see busnumbers here. Something + ** in the form of 0xbbxxxx where bb is the bus num + ** and xxxx is the I/O port space address. + ** Remaining address translation are done in the + ** PCI Host adapter specific code - ie dino_out8. + */ + ranges->io_start = PCI_PORT_ADDR(ranges->io_start); + ranges->io_end = PCI_PORT_ADDR(ranges->io_end); + + DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number, + ranges->io_start, ranges->io_end, + ranges->mem_start, ranges->mem_end); +} + +#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2)) + + +/* +** pcibios align resources() is called everytime generic PCI code +** wants to generate a new address. The process of looking for +** an available address, each candidate is first "aligned" and +** then checked if the resource is available until a match is found. +** +** Since we are just checking candidates, don't use any fields other +** than res->start. +*/ +void __devinit +pcibios_align_resource(void *data, struct resource *res, unsigned long size) +{ + unsigned long mask, align; + + DBG_RES("pcibios_align_resource(%s, (%p) [%lx,%lx]/%x, 0x%lx)\n", + ((struct pci_dev *) data)->slot_name, + res->parent, res->start, res->end, (int) res->flags, size); + + /* has resource already been aligned/assigned? */ + if (res->parent) + return; + + /* If it's not IO, then it's gotta be MEM */ + align = (res->flags & IORESOURCE_IO) ? PCIBIOS_MIN_IO : PCIBIOS_MIN_MEM; + + /* Align to largest of MIN or input size */ + mask = MAX(size, align) - 1; + res->start += mask; + res->start &= ~mask; + + /* + ** WARNING : caller is expected to update "end" field. + ** We can't since it might really represent the *size*. + ** The difference is "end = start + size" vs "end += size". + */ +} + + +#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +void __devinit +pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer) +{ + struct pbus_set_ranges_data inner; + struct pci_dev *dev; + struct pci_dev *bridge = bus->self; + struct list_head *ln; + + /* set reasonable default "window" for pcibios_align_resource */ + inner.io_start = inner.io_end = 0; + inner.mem_start = inner.mem_end = 0; + + /* Collect information about how our direct children are layed out. */ + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { + int i; + dev = pci_dev_b(ln); + + /* Skip bridges here - we'll catch them below */ + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) + continue; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource res; + unsigned long size; + + if (dev->resource[i].flags == 0) + continue; + + memcpy(&res, &dev->resource[i], sizeof(res)); + size = res.end - res.start + 1; + + if (res.flags & IORESOURCE_IO) { + res.start = inner.io_end; + pcibios_align_resource(dev, &res, size); + inner.io_end += res.start + size; + } else if (res.flags & IORESOURCE_MEM) { + res.start = inner.mem_end; + pcibios_align_resource(dev, &res, size); + inner.mem_end = res.start + size; + } + + DBG_RES(" %s inner size %lx/%x IO %lx MEM %lx\n", + dev->slot_name, + size, res.flags, inner.io_end, inner.mem_end); + } + } + + /* And for all of the subordinate busses. */ + for (ln=bus->children.next; ln != &bus->children; ln=ln->next) + pcibios_size_bridge(pci_bus_b(ln), &inner); + + /* turn the ending locations into sizes (subtract start) */ + inner.io_end -= inner.io_start - 1; + inner.mem_end -= inner.mem_start - 1; + + /* Align the sizes up by bridge rules */ + inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1; + inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1; + + /* PPB - PCI bridge Device will normaller also have "outer" != NULL. */ + if (bridge) { + /* Adjust the bus' allocation requirements */ + /* PPB's pci device Bridge resources */ + + bus->resource[0] = &bridge->resource[PCI_BRIDGE_RESOURCES]; + bus->resource[1] = &bridge->resource[PCI_BRIDGE_RESOURCES + 1]; + + bus->resource[0]->start = bus->resource[1]->start = 0; + bus->resource[0]->parent= bus->resource[1]->parent = NULL; + + bus->resource[0]->end = inner.io_end; + bus->resource[0]->flags = IORESOURCE_IO; + + bus->resource[1]->end = inner.mem_end; + bus->resource[1]->flags = IORESOURCE_MEM; + } + + /* adjust parent's resource requirements */ + if (outer) { + outer->io_end = ROUND_UP(outer->io_end, 4*1024); + outer->io_end += inner.io_end; + + outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024); + outer->mem_end += inner.mem_end; + } +} + +#undef ROUND_UP + + +int __devinit +pcibios_enable_device(struct pci_dev *dev) +{ + u16 cmd, old_cmd; + int idx; + + /* + ** The various platform PDC's (aka "BIOS" for PCs) don't + ** enable all the same bits. We just make sure they are here. + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + old_cmd = cmd; + + /* + ** See if any resources have been allocated + */ + for (idx=0; idx<6; idx++) { + struct resource *r = &dev->resource[idx]; + if (r->flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + if (r->flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + + /* + ** System error and Parity Error reporting are enabled by default. + ** Devices that do NOT want those behaviors should clear them + ** (eg PCI graphics, possibly networking). + ** Interfaces like SCSI certainly should not. We want the + ** system to crash if a system or parity error is detected. + ** At least until the device driver can recover from such an error. + */ + cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY); + + if (cmd != old_cmd) { + printk("PCIBIOS: Enabling device %s (%04x -> %04x)\n", + dev->slot_name, old_cmd, cmd); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + + return 0; +} + + +void __devinit +pcibios_assign_unassigned_resources(struct pci_bus *bus) +{ + struct list_head *ln; + + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) + { + pdev_assign_unassigned_resources(pci_dev_b(ln)); + } + + /* And for all of the sub-busses. */ + for (ln=bus->children.next; ln != &bus->children; ln=ln->next) + pcibios_assign_unassigned_resources(pci_bus_b(ln)); + +} + +/* +** PARISC specific (unfortunately) +*/ +void pcibios_register_hba(struct pci_hba_data *hba) +{ + hba->next = hba_list; + hba_list = hba; + + ASSERT(hba_count < PCI_HBA_MAX); + + /* + ** pci_port->in/out() uses parisc_pci_hba to lookup parameter. + */ + parisc_pci_hba[hba_count] = hba; + hba->hba_num = hba_count++; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/pdc.c linux/arch/parisc/kernel/pdc.c --- v2.4.0-test11/linux/arch/parisc/kernel/pdc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/pdc.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,217 @@ +/* arch/parisc/kernel/pdc.c - safe pdc access routines + * + * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org) + * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy) + * + * only these routines should be used out of the real kernel (i.e. everything + * using virtual addresses) for obvious reasons */ + +/* I think it would be in everyone's best interest to follow this + * guidelines when writing PDC wrappers: + * + * - the name of the pdc wrapper should match one of the macros + * used for the first two arguments + * - don't use caps for random parts of the name + * - use ASSERT_ALIGN to ensure the aligment of the arguments is + * correct + * - use __pa() to convert virtual (kernel) pointers to physical + * ones. + * - the name of the struct used for pdc return values should equal + * one of the macros used for the first two arguments to the + * corresponding PDC call + * - keep the order of arguments + * - don't be smart (setting trailing NUL bytes for strings, return + * something useful even if the call failed) unless you are sure + * it's not going to affect functionality or performance + * + * Example: + * int pdc_cache_info(struct pdc_cache_info *cache_info ) + * { + * ASSERT_ALIGN(cache_info, 8); + * + * return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); + * } + * prumpf 991016 + */ + +#include +#include + +#include +#include +#include +#include + + +#define ASSERT_ALIGN(ptr, align) \ + do { if(((unsigned long)(ptr)) & (align-1)) { \ + printk("PDC: %s:%d %s() called with " \ + "unaligned argument from %p", __FILE__, __LINE__, \ + __FUNCTION__, __builtin_return_address(0)); \ + \ + return -1; \ + } } while(0) + +/* verify address can be accessed without an HPMC */ +int pdc_add_valid(void *address) +{ + ASSERT_ALIGN(address, 4); + + return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address); +} + +#if 0 +int pdc_chassis_warn(struct pdc_chassis_warn *address) +{ + ASSERT_ALIGN(address, 4); + + return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0); +} +#endif + +int pdc_chassis_disp(unsigned long disp) +{ + return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp); +} + +int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len) +{ + ASSERT_ALIGN(pdc_result, 4); + ASSERT_ALIGN(chassis_info, 4); + return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO, + __pa(pdc_result), __pa(chassis_info), len); +} + +int pdc_hpa_processor(void *address) +{ + /* We're using 0 for the last parameter just to make sure. + It's actually HVERSION dependant. And remember, life is + hard without a backspace. */ + ASSERT_ALIGN(address, 4); + + return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0); +} + +#if 0 +int pdc_hpa_modules(void *address) +{ + return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address); +} +#endif + +int pdc_iodc_read(void *address, void * hpa, unsigned int index, + void * iodc_data, unsigned int iodc_data_size) +{ + ASSERT_ALIGN(address, 4); + ASSERT_ALIGN(iodc_data, 8); + return mem_pdc_call(PDC_IODC, PDC_IODC_READ, + __pa(address), hpa, index, __pa(iodc_data), iodc_data_size); +} + + +int pdc_system_map_find_mods(void *pdc_mod_info, + void *mod_path, int index) +{ + return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, + __pa(pdc_mod_info), __pa(mod_path), (long)index); +} + + +int pdc_model_info(struct pdc_model *model) { + ASSERT_ALIGN(model, 8); + return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0); +} + +/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */ +int pdc_model_sysmodel(char * name) +{ + struct pdc_model_sysmodel sys_model; + int retval; + + ASSERT_ALIGN(&sys_model, 8); + ASSERT_ALIGN(name, 4); + + sys_model.mod_len = 0; + retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model), + OS_ID_HPUX,__pa(name)); + + if (retval == PDC_RET_OK) + name[sys_model.mod_len] = '\0'; /* add trailing '\0' */ + else + name[0] = 0; + + return retval; +} + +/* id: 0 = cpu revision, 1 = boot-rom-version */ +int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) { + return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id); +} + +int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) { + cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */ + return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0); /* 6="return CPU ID" */ +} + +int pdc_cache_info(struct pdc_cache_info *cache_info) { + ASSERT_ALIGN(cache_info, 8); + + return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0); +} + +#ifndef __LP64__ +int pdc_btlb_info( struct pdc_btlb_info *btlb ) { + int status; + status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0); + if (status<0) btlb->max_size = 0; + return status; +} + +int pdc_mem_map_hpa(void *r_addr, void *mod_path) { + return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA, + __pa(r_addr),__pa(mod_path)); +} + +int pdc_lan_station_id(char *lan_addr, void *net_hpa) { + struct pdc_lan_station_id id; + unsigned char *addr; + + if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ, + __pa(&id), net_hpa) < 0) + addr = 0; /* FIXME: else read MAC from NVRAM */ + else + addr = id.addr; + if (addr) + memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE); + else + memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE); + return (addr != 0); +} +#endif + + +/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */ +int pdc_pci_irt_size(void *r_addr, void *hpa) +{ + return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, + __pa(r_addr), hpa); + +} + +int pdc_pci_irt(void *r_addr, void *hpa, void *tbl) +{ + return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, + __pa(r_addr), hpa, __pa(tbl)); +} + +/* access the TOD clock */ +int pdc_tod_read(struct pdc_tod *tod) +{ + ASSERT_ALIGN(tod, 8); + return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0); +} + +int pdc_tod_set(unsigned long sec, unsigned long usec) +{ + return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/pdc_cons.c linux/arch/parisc/kernel/pdc_cons.c --- v2.4.0-test11/linux/arch/parisc/kernel/pdc_cons.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/pdc_cons.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for iodc_call() proto and friends */ +#include + +static int __attribute__((aligned(8))) iodc_retbuf[32]; +static char __attribute__((aligned(64))) iodc_dbuf[4096]; + +/* + * pdc_putc: + * Console character print using IODC. + * + * Note that only these special chars are architected for console IODC io: + * BEL, BS, CR, and LF. Others are passed through. + * Since the HP console requires CR+LF to perform a 'newline', we translate + * "\n" to "\r\n". + */ + +static int posx; /* for simple TAB-Simulation... */ + +/* XXX Should we spinlock posx usage */ + +void pdc_putc(unsigned char c) +{ + unsigned int n; + unsigned long flags; + + switch (c) { + case '\n': + iodc_dbuf[0] = '\r'; + iodc_dbuf[1] = '\n'; + n = 2; + posx = 0; + break; + case '\t': + pdc_putc(' '); + while (posx & 7) /* expand TAB */ + pdc_putc(' '); + return; /* return since IODC can't handle this */ + case '\b': + posx-=2; /* BS */ + default: + iodc_dbuf[0] = c; + n = 1; + posx++; + break; + } + { + real32_call(PAGE0->mem_cons.iodc_io, + (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, + PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0); + } +} + +static void pdc_console_write(struct console *co, const char *s, unsigned count) +{ + while(count--) + pdc_putc(*s++); +} + +int pdc_console_wait_key(struct console *co) +{ + int ch = 'X'; + int status; + + /* Bail if no console input device. */ + if (!PAGE0->mem_kbd.iodc_io) + return 0; + + /* wait for a keyboard (rs232)-input */ + do { + unsigned long flags; + + save_flags(flags); + cli(); + status = real32_call(PAGE0->mem_kbd.iodc_io, + (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN, + PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), + __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0); + restore_flags(flags); + ch = *iodc_dbuf; /* save the character directly to ch */ + } while (*iodc_retbuf == 0); /* wait for a key */ + return ch; +} + +int pdc_getc(void) +{ + return pdc_console_wait_key(NULL); +} + +static int pdc_console_setup(struct console *co, char *options) +{ + return 0; +} + +static struct console pdc_cons = { + name: "ttyB", + write: pdc_console_write, + read: NULL, + device: NULL, + wait_key: pdc_console_wait_key, + unblank: NULL, + setup: pdc_console_setup, + flags: CON_PRINTBUFFER|CON_ENABLED, // |CON_CONSDEV, + index: -1, +}; + +static int pdc_console_initialized; + +void pdc_console_init(void) +{ + if (pdc_console_initialized) + return; + ++pdc_console_initialized; + + /* If the console is duplex then copy the COUT parameters to CIN. */ + if (PAGE0->mem_cons.cl_class == CL_DUPLEX) + memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons)); + + pdc_console_write(0, "PDC Console Initialized\n", 24); + /* register the pdc console */ + register_console(&pdc_cons); +} + + +/* Unregister the pdc console with the printk console layer */ +void pdc_console_die(void) +{ + printk("Switching from PDC console\n"); + if (!pdc_console_initialized) + return; + --pdc_console_initialized; + +#ifdef CONFIG_VT_CONSOLE + { + /* fixme (needed?): Wait for console-tasklet to finish !*/ + extern struct tasklet_struct console_tasklet; + tasklet_schedule(&console_tasklet); + } +#endif + + unregister_console(&pdc_cons); +} + + +/* + * Used for emergencies. Currently only used if an HPMC occurs. If an + * HPMC occurs, it is possible that the current console may not be + * properly initialed after the PDC IO reset. This routine unregisters all + * of the current consoles, reinitializes the pdc console and + * registers it. + */ + +void pdc_console_restart(void) +{ + struct console *console; + extern int log_size; + + if (pdc_console_initialized) + return; + + while ((console = console_drivers) != (struct console *)0) + unregister_console(console_drivers); + + log_size = 0; + pdc_console_init(); + printk("Switched to PDC console\n"); + return; +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/process.c linux/arch/parisc/kernel/process.c --- v2.4.0-test11/linux/arch/parisc/kernel/process.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/process.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,250 @@ +/* + * linux/arch/parisc/kernel/process.c + * based on the work for i386 + */ + +/* + * This file handles the architecture-dependent parts of process handling.. + */ + +#define __KERNEL_SYSCALLS__ +#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 + +spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED; + +#ifdef __LP64__ +/* The 64-bit code should work equally well in 32-bit land but I didn't + * want to take the time to confirm that. -PB + */ +extern unsigned int ret_from_kernel_thread; +#else +asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); +#endif + + +int hlt_counter=0; + +void disable_hlt(void) +{ + hlt_counter++; +} + +void enable_hlt(void) +{ + hlt_counter--; +} + +/* + * The idle thread. There's no useful work to be + * done, so just try to conserve power and have a + * low exit latency (ie sit in a loop waiting for + * somebody to say that they'd like to reschedule) + */ +void cpu_idle(void) +{ + /* endless idle loop with no priority at all */ + init_idle(); + current->nice = 20; + current->counter = -100; + + while (1) { + while (!current->need_resched) { + } + schedule(); + check_pgt_cache(); + } +} + +void __init reboot_setup(char *str, int *ints) +{ +} + +struct notifier_block *mach_notifier; + +void machine_restart(char *ptr) +{ + notifier_call_chain(&mach_notifier, MACH_RESTART, ptr); +} + +void machine_halt(void) +{ + notifier_call_chain(&mach_notifier, MACH_HALT, NULL); +} + +void machine_power_on(void) +{ + notifier_call_chain(&mach_notifier, MACH_POWER_ON, NULL); +} + +void machine_power_off(void) +{ + notifier_call_chain(&mach_notifier, MACH_POWER_OFF, NULL); +} + + +void machine_heartbeat(void) +{ +} + + +/* + * Create a kernel thread + */ + +extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); +pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) +{ + + /* + * FIXME: Once we are sure we don't need any debug here, + * kernel_thread can become a #define. + */ + + return __kernel_thread(fn, arg, flags); +} + +/* + * Free current thread data structures etc.. + */ +void exit_thread(void) +{ +} + +void flush_thread(void) +{ + set_fs(USER_DS); +} + +void release_thread(struct task_struct *dead_task) +{ +} + +/* + * Fill in the FPU structure for a core dump. + */ +int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r) +{ + memcpy(r, regs->fr, sizeof *r); + return 1; +} + +/* Note that "fork()" is implemented in terms of clone, with + parameters (SIGCHLD, regs->gr[30], regs). */ +int +sys_clone(unsigned long clone_flags, unsigned long usp, + struct pt_regs *regs) +{ + return do_fork(clone_flags, usp, regs, 0); +} + +int +sys_vfork(struct pt_regs *regs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, + regs->gr[30], regs, 0); +} + +int +copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, /* in ia64 this is "user_stack_size" */ + struct task_struct * p, struct pt_regs * pregs) +{ + struct pt_regs * cregs = &(p->thread.regs); + long ksp; + + *cregs = *pregs; + + /* Set the return value for the child. Note that this is not + actually restored by the syscall exit path, but we put it + here for consistency in case of signals. */ + cregs->gr[28] = 0; /* child */ + + /* + * We need to differentiate between a user fork and a + * kernel fork. We can't use user_mode, because the + * the syscall path doesn't save iaoq. Right now + * We rely on the fact that kernel_thread passes + * in zero for usp. + */ + if (usp == 0) { + /* Kernel Thread */ + ksp = (((unsigned long)(p)) + TASK_SZ_ALGN); + cregs->ksp = ksp; /* always return to kernel */ +#ifdef __LP64__ + cregs->kpc = (unsigned long) &ret_from_kernel_thread; +#else + cregs->kpc = (unsigned long) ret_from_kernel_thread; +#endif + + /* + * Copy function and argument to be called from + * ret_from_kernel_thread. + */ + cregs->gr[26] = pregs->gr[26]; + cregs->gr[25] = pregs->gr[25]; + + } else { + /* User Thread: + * + * Use same stack depth as parent when in wrapper + * + * Note that the fork wrappers are responsible + * for setting gr[20] and gr[21]. + */ + + cregs->ksp = ((unsigned long)(p)) + + (pregs->gr[20] & (INIT_TASK_SIZE - 1)); + cregs->kpc = pregs->gr[21]; + } + + return 0; +} + +/* + * sys_execve() executes a new program. + */ + +asmlinkage int sys_execve(struct pt_regs *regs) +{ + int error; + char *filename; + + filename = getname((char *) regs->gr[26]); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + error = do_execve(filename, (char **) regs->gr[25], + (char **) regs->gr[24], regs); + if (error == 0) + current->ptrace &= ~PT_DTRACE; + putname(filename); +out: + + return error; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/ptrace.c linux/arch/parisc/kernel/ptrace.c --- v2.4.0-test11/linux/arch/parisc/kernel/ptrace.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/ptrace.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,305 @@ +/* + * Kernel support for the ptrace() and syscall tracing interfaces. + * + * Copyright (C) 2000 Hewlett-Packard Co, Linuxcare Inc. + * Copyright (C) 2000 Matthew Wilcox + * Copyright (C) 2000 David Huggins-Daines + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* These are used in entry.S, syscall_restore_rfi. We need to record the + * current stepping mode somewhere other than in PSW, because there is no + * concept of saving and restoring the users PSW over a syscall. We choose + * to use these two bits in task->ptrace. These bits must not clash with + * any PT_* defined in include/linux/sched.h, and must match with the bit + * tests in entry.S + */ +#define PT_SINGLESTEP 0x10000 +#define PT_BLOCKSTEP 0x20000 + +long sys_ptrace(long request, pid_t pid, long addr, long data) +{ + struct task_struct *child; + long ret; + + lock_kernel(); + ret = -EPERM; + if (request == PTRACE_TRACEME) { + /* are we already being traced? */ + if (current->ptrace & PT_PTRACED) + goto out; + /* set the ptrace bit in the process flags. */ + current->ptrace |= PT_PTRACED; + ret = 0; + goto out; + } + + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + goto out; + ret = -EPERM; + if (pid == 1) /* no messing around with init! */ + goto out_tsk; + + if (request == PTRACE_ATTACH) { + if (child == current) + goto out_tsk; + if ((!child->dumpable || + (current->uid != child->euid) || + (current->uid != child->suid) || + (current->uid != child->uid) || + (current->gid != child->egid) || + (current->gid != child->sgid) || + (!cap_issubset(child->cap_permitted, current->cap_permitted)) || + (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)) + goto out_tsk; + /* the same process cannot be attached many times */ + if (child->ptrace & PT_PTRACED) + goto out_tsk; + child->ptrace |= PT_PTRACED; + if (child->p_pptr != current) { + unsigned long flags; + + write_lock_irqsave(&tasklist_lock, flags); + REMOVE_LINKS(child); + child->p_pptr = current; + SET_LINKS(child); + write_unlock_irqrestore(&tasklist_lock, flags); + } + send_sig(SIGSTOP, child, 1); + ret = 0; + goto out_tsk; + } + ret = -ESRCH; + if (!(child->ptrace & PT_PTRACED)) + goto out_tsk; + if (child->state != TASK_STOPPED) { + if (request != PTRACE_KILL) + goto out_tsk; + } + if (child->p_pptr != current) + goto out_tsk; + + switch (request) { + case PTRACE_PEEKTEXT: /* read word at location addr. */ + case PTRACE_PEEKDATA: { + unsigned long tmp; + int copied; + + copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0); + ret = -EIO; + if (copied != sizeof(tmp)) + goto out_tsk; + ret = put_user(tmp,(unsigned long *) data); + goto out_tsk; + } + + /* when I and D space are separate, this will have to be fixed. */ + case PTRACE_POKETEXT: /* write the word at location addr. */ + case PTRACE_POKEDATA: + ret = 0; + if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data)) + goto out_tsk; + ret = -EIO; + goto out_tsk; + + /* Read the word at location addr in the USER area. This will need + to change when the kernel no longer saves all regs on a syscall. */ + case PTRACE_PEEKUSR: { + unsigned long tmp; + + ret = -EIO; + if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs)) + goto out_tsk; + + tmp = *(unsigned long *) ((char *) task_regs(child) + addr); + ret = put_user(tmp, (unsigned long *) data); + goto out_tsk; + } + + /* Write the word at location addr in the USER area. This will need + to change when the kernel no longer saves all regs on a syscall. + FIXME. There is a problem at the moment in that r3-r18 are only + saved if the process is ptraced on syscall entry, and even then + those values are overwritten by actual register values on syscall + exit. */ + case PTRACE_POKEUSR: + ret = -EIO; + if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs)) + goto out_tsk; + /* XXX This test probably needs adjusting. We probably want to + * allow writes to some bits of PSW, and may want to block writes + * to (some) space registers. Some register values written here + * may be ignored in entry.S:syscall_restore_rfi; e.g. iaoq is + * written with r31/r31+4, and not with the values in pt_regs. + */ + /* Allow writing of gr1-gr31, fr*, sr*, iasq*, iaoq*, sar */ + if (addr == PT_PSW || (addr > PT_IAOQ1 && addr != PT_SAR)) + goto out_tsk; + + *(unsigned long *) ((char *) task_regs(child) + addr) = data; + ret = 0; + goto out_tsk; + + case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ + case PTRACE_CONT: + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out_tsk; + child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); + if (request == PTRACE_SYSCALL) + child->ptrace |= PT_TRACESYS; + else + child->ptrace &= ~PT_TRACESYS; + child->exit_code = data; + goto out_wake_notrap; + + case PTRACE_KILL: + /* + * make the child exit. Best I can do is send it a + * sigkill. perhaps it should be put in the status + * that it wants to exit. + */ + if (child->state == TASK_ZOMBIE) /* already dead */ + goto out_tsk; + child->exit_code = SIGKILL; + goto out_wake_notrap; + + case PTRACE_SINGLEBLOCK: + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out_tsk; + child->ptrace &= ~(PT_TRACESYS|PT_SINGLESTEP); + child->ptrace |= PT_BLOCKSTEP; + child->exit_code = data; + + /* Enable taken branch trap. */ + pa_psw(child)->r = 0; + pa_psw(child)->t = 1; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; + goto out_wake; + + case PTRACE_SINGLESTEP: + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out_tsk; + child->ptrace &= ~(PT_TRACESYS|PT_BLOCKSTEP); + child->ptrace |= PT_SINGLESTEP; + child->exit_code = data; + + if (pa_psw(child)->n) { + struct siginfo si; + + /* Nullified, just crank over the queue. */ + task_regs(child)->iaoq[0] = task_regs(child)->iaoq[1]; + task_regs(child)->iasq[0] = task_regs(child)->iasq[1]; + task_regs(child)->iaoq[1] = task_regs(child)->iaoq[0] + 4; + pa_psw(child)->n = 0; + pa_psw(child)->x = 0; + pa_psw(child)->y = 0; + pa_psw(child)->z = 0; + pa_psw(child)->b = 0; + pa_psw(child)->r = 0; + pa_psw(child)->t = 0; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; + /* Don't wake up the child, but let the + parent know something happened. */ + si.si_code = TRAP_TRACE; + si.si_addr = (void *) (task_regs(child)->iaoq[0] & ~3); + si.si_signo = SIGTRAP; + si.si_errno = 0; + force_sig_info(SIGTRAP, &si, child); + //notify_parent(child, SIGCHLD); + //ret = 0; + goto out_wake; + } + + /* Enable recovery counter traps. The recovery counter + * itself will be set to zero on a task switch. If the + * task is suspended on a syscall then the syscall return + * path will overwrite the recovery counter with a suitable + * value such that it traps once back in user space. We + * disable interrupts in the childs PSW here also, to avoid + * interrupts while the recovery counter is decrementing. + */ + pa_psw(child)->r = 1; + pa_psw(child)->t = 0; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; + /* give it a chance to run. */ + goto out_wake; + + case PTRACE_DETACH: + ret = -EIO; + if ((unsigned long) data > _NSIG) + goto out_tsk; + child->ptrace &= ~(PT_PTRACED|PT_TRACESYS|PT_SINGLESTEP|PT_BLOCKSTEP); + child->exit_code = data; + write_lock_irq(&tasklist_lock); + REMOVE_LINKS(child); + child->p_pptr = child->p_opptr; + SET_LINKS(child); + write_unlock_irq(&tasklist_lock); + goto out_wake_notrap; + + default: + ret = -EIO; + goto out_tsk; + } + +out_wake_notrap: + /* make sure the trap bits are not set */ + pa_psw(child)->r = 0; + pa_psw(child)->t = 0; + pa_psw(child)->h = 0; + pa_psw(child)->l = 0; +out_wake: + wake_up_process(child); + ret = 0; +out_tsk: + free_task_struct(child); +out: + unlock_kernel(); + return ret; +} + +void syscall_trace(void) +{ + if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) != + (PT_PTRACED|PT_TRACESYS)) + return; + current->exit_code = SIGTRAP; + current->state = TASK_STOPPED; + notify_parent(current, SIGCHLD); + schedule(); + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/real1.c linux/arch/parisc/kernel/real1.c --- v2.4.0-test11/linux/arch/parisc/kernel/real1.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/real1.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,154 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com) + * + * most of these calls might reasonably be moved to ../kernel -PB + * + * The basic principle is to construct a stack frame in C then call + * some assembly which adopts that stack, does some rfi magic, may + * switch wide/narrow mode, and calls the routine described by the + * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!! + */ +#include +#include +#include +#include /* for __pa() */ +#include + +static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED; + +/***************** 32-bit real-mode calls ***********/ +/* The struct below is used + * to overlay real_stack (real2.S), preparing a 32-bit call frame. + * real32_call_asm() then uses this stack in narrow real mode + */ + +struct narrow_stack { + /* use int, not long which is 64 bits */ + unsigned int arg13; + unsigned int arg12; + unsigned int arg11; + unsigned int arg10; + unsigned int arg9; + unsigned int arg8; + unsigned int arg7; + unsigned int arg6; + unsigned int arg5; + unsigned int arg4; + unsigned int arg3; + unsigned int arg2; + unsigned int arg1; + unsigned int arg0; + unsigned int frame_marker[8]; + unsigned int sp; + /* in reality, there's nearly 8k of stack after this */ +}; + +long +real32_call(unsigned long fn, ...) +{ + unsigned long r; + va_list args; + unsigned long flags; + extern struct narrow_stack real_stack; + extern unsigned long real32_call_asm(unsigned int *, + unsigned int *, unsigned int); + + va_start(args, fn); + real_stack.arg0 = va_arg(args, unsigned int); + real_stack.arg1 = va_arg(args, unsigned int); + real_stack.arg2 = va_arg(args, unsigned int); + real_stack.arg3 = va_arg(args, unsigned int); + real_stack.arg4 = va_arg(args, unsigned int); + real_stack.arg5 = va_arg(args, unsigned int); + real_stack.arg6 = va_arg(args, unsigned int); + real_stack.arg7 = va_arg(args, unsigned int); + real_stack.arg8 = va_arg(args, unsigned int); + real_stack.arg9 = va_arg(args, unsigned int); + real_stack.arg10 = va_arg(args, unsigned int); + real_stack.arg11 = va_arg(args, unsigned int); + real_stack.arg12 = va_arg(args, unsigned int); + real_stack.arg13 = va_arg(args, unsigned int); + va_end(args); + + if (fn == 0) { + /* mem_pdc call */ + fn = PAGE0->mem_pdc; + } + + spin_lock_irqsave(&pdc_lock, flags); + r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn); + spin_unlock_irqrestore(&pdc_lock, flags); + + return r; +} + +#ifdef __LP64__ +/***************** 64-bit real-mode calls ***********/ + +struct wide_stack { + unsigned long arg0; + unsigned long arg1; + unsigned long arg2; + unsigned long arg3; + unsigned long arg4; + unsigned long arg5; + unsigned long arg6; + unsigned long arg7; + unsigned long arg8; + unsigned long arg9; + unsigned long arg10; + unsigned long arg11; + unsigned long arg12; + unsigned long arg13; + unsigned long frame_marker[2]; /* rp, previous sp */ + unsigned long sp; + /* in reality, there's nearly 8k of stack after this */ +}; + +long +real64_call(unsigned long fn, ...) +{ + unsigned long r; + va_list args; + unsigned long flags; + extern struct wide_stack real_stack; + extern unsigned long real64_call_asm(unsigned long *, + unsigned long *, unsigned long); + + va_start(args, fn); + real_stack.arg0 = va_arg(args, unsigned long); + real_stack.arg1 = va_arg(args, unsigned long); + real_stack.arg2 = va_arg(args, unsigned long); + real_stack.arg3 = va_arg(args, unsigned long); + real_stack.arg4 = va_arg(args, unsigned long); + real_stack.arg5 = va_arg(args, unsigned long); + real_stack.arg6 = va_arg(args, unsigned long); + real_stack.arg7 = va_arg(args, unsigned long); + real_stack.arg8 = va_arg(args, unsigned long); + real_stack.arg9 = va_arg(args, unsigned long); + real_stack.arg10 = va_arg(args, unsigned long); + real_stack.arg11 = va_arg(args, unsigned long); + real_stack.arg12 = va_arg(args, unsigned long); + real_stack.arg13 = va_arg(args, unsigned long); + va_end(args); + + if (fn == 0) { + /* mem_pdc call */ + fn = PAGE0->mem_pdc_hi; + fn <<= 32; + fn |= PAGE0->mem_pdc; + } + + spin_lock_irqsave(&pdc_lock, flags); + r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn); + spin_unlock_irqrestore(&pdc_lock, flags); + + return r; +} + +#endif diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/real2.S linux/arch/parisc/kernel/real2.S --- v2.4.0-test11/linux/arch/parisc/kernel/real2.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/real2.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,274 @@ +/* + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com) + * + */ +#define __ASSEMBLY__ +#include +#include + + .section .bss + .export real_stack + .align 64 +real_stack: + .block 8192 + +#ifdef __LP64__ +# define REG_SZ 8 +#else +# define REG_SZ 4 +#endif + +#define N_SAVED_REGS 9 + +save_cr_space: + .block REG_SZ * N_SAVED_REGS + + +/************************ 32-bit real-mode calls ***********************/ +/* This can be called in both narrow and wide kernels */ + .text + .export real32_call_asm + /* unsigned long real32_call_asm(unsigned int *sp, + * unsigned int *arg0p, + * unsigned int iodc_fn) + * sp is value of stack pointer to adopt before calling PDC (virt) + * arg0p points to where saved arg values may be found + * iodc_fn is the IODC function to call + */ +real32_call_asm: + STREG %rp, -RP_OFFSET(%sp) /* save RP */ +#ifdef __LP64__ + callee_save + ldo 2*REG_SZ(%sp), %sp /* room for a couple more saves */ + STREG %r27, -1*REG_SZ(%sp) + STREG %r29, -2*REG_SZ(%sp) +#endif + STREG %sp, -REG_SZ(%arg0) /* save SP on real-mode stack */ + copy %arg0, %sp /* adopt the real-mode SP */ + + /* save iodc_fn */ + copy %arg2, %r31 + + /* load up the arg registers from the saved arg area */ + /* 32-bit calling convention passes first 4 args in registers */ + ldw 0(%arg1), %arg0 /* note overwriting arg0 */ + ldw -8(%arg1), %arg2 + ldw -12(%arg1), %arg3 + ldw -4(%arg1), %arg1 /* obviously must do this one last! */ + + tophys %sp + + b,l rfi_virt2real,%r2 + nop + + b,l save_control_regs,%r2 /* modifies r1, r2, r28 */ + nop + +#ifdef __LP64__ + rsm PSW_SM_W, %r0 /* go narrow */ +#endif + + ldil L%PA(ric_ret), %r2 + ldo R%PA(ric_ret)(%r2), %r2 + bv 0(%r31) + nop +ric_ret: +#ifdef __LP64__ + ssm PSW_SM_W, %r0 /* go wide */ +#endif + /* restore CRs before going virtual in case we page fault */ + b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */ + nop + + b,l rfi_real2virt,%r2 + nop + + tovirt %sp + LDREG -REG_SZ(%sp), %sp /* restore SP */ +#ifdef __LP64__ + LDREG -1*REG_SZ(%sp), %r27 + LDREG -2*REG_SZ(%sp), %r29 + ldo -2*REG_SZ(%sp), %sp + callee_rest +#endif + LDREG -RP_OFFSET(%sp), %rp /* restore RP */ + bv 0(%rp) + nop + + +# define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where) +# define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r + + .text +save_control_regs: + load32 PA(save_cr_space), %r28 + PUSH_CR(%cr24, %r28) + PUSH_CR(%cr25, %r28) + PUSH_CR(%cr26, %r28) + PUSH_CR(%cr27, %r28) + PUSH_CR(%cr28, %r28) + PUSH_CR(%cr29, %r28) + PUSH_CR(%cr30, %r28) + PUSH_CR(%cr31, %r28) + PUSH_CR(%cr15, %r28) + bv 0(%r2) + nop + +restore_control_regs: + load32 PA(save_cr_space + (N_SAVED_REGS * REG_SZ)), %r26 + POP_CR(%cr15, %r26) + POP_CR(%cr31, %r26) + POP_CR(%cr30, %r26) + POP_CR(%cr29, %r26) + POP_CR(%cr28, %r26) + POP_CR(%cr27, %r26) + POP_CR(%cr26, %r26) + POP_CR(%cr25, %r26) + POP_CR(%cr24, %r26) + bv 0(%r2) + nop + +/* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for + * more general-purpose use by the several places which need RFIs + */ + .align 128 + .text +rfi_virt2real: + /* switch to real mode... */ + ssm 0,0 /* See "relied upon translation" */ + nop /* comment in interruption.S */ + nop + nop + nop + nop + nop + nop + nop + + mtsm 0 /* disable interruptions */ + mtctl 0, %cr17 /* space 0 */ + mtctl 0, %cr17 + load32 PA(rfi_v2r_1), %r1 + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + load32 PDC_PSW, %r1 + mtctl %r1, %cr22 + rfi + + nop + nop + nop + nop + nop + nop + nop + nop +rfi_v2r_1: + tophys %r2 + bv 0(%r2) + nop + + .text + .align 128 +rfi_real2virt: + ssm 0,0 /* See "relied upon translation" */ + nop /* comment in interruption.S */ + nop + nop + nop + nop + nop + nop + nop + + mtsm 0 /* disable interruptions */ + mtctl 0, %cr17 /* space 0 */ + mtctl 0, %cr17 + load32 (rfi_r2v_1), %r1 + mtctl %r1, %cr18 + ldo 4(%r1), %r1 + mtctl %r1, %cr18 + load32 KERNEL_PSW, %r1 + mtctl %r1, %cr22 + rfi + + nop + nop + nop + nop + nop + nop + nop + nop +rfi_r2v_1: + tovirt %r2 + bv 0(%r2) + nop + +#ifdef __LP64__ + +/************************ 64-bit real-mode calls ***********************/ +/* This is only usable in wide kernels right now and will probably stay so */ + .text + .export real64_call_asm + /* unsigned long real64_call_asm(unsigned long *sp, + * unsigned long *arg0p, + * unsigned long fn) + * sp is value of stack pointer to adopt before calling PDC (virt) + * arg0p points to where saved arg values may be found + * iodc_fn is the IODC function to call + */ +real64_call_asm: + std %rp, -0x10(%sp) /* save RP */ + std %sp, -8(%arg0) /* save SP on real-mode stack */ + copy %arg0, %sp /* adopt the real-mode SP */ + + /* save fn */ + copy %arg2, %r31 + + /* set up the new ap */ + ldo 64(%arg1), %r29 + + /* load up the arg registers from the saved arg area */ + /* 32-bit calling convention passes first 4 args in registers */ + ldd 0*REG_SZ(%arg1), %arg0 /* note overwriting arg0 */ + ldd 2*REG_SZ(%arg1), %arg2 + ldd 3*REG_SZ(%arg1), %arg3 + ldd 4*REG_SZ(%arg1), %r22 + ldd 5*REG_SZ(%arg1), %r21 + ldd 6*REG_SZ(%arg1), %r20 + ldd 7*REG_SZ(%arg1), %r19 + ldd 1*REG_SZ(%arg1), %arg1 /* do this one last! */ + + tophys %sp + + b,l rfi_virt2real,%r2 + nop + + b,l save_control_regs,%r2 /* modifies r1, r2, r28 */ + nop + + load32 PA(r64_ret), %r2 + bv 0(%r31) + nop +r64_ret: + /* restore CRs before going virtual in case we page fault */ + b,l restore_control_regs, %r2 /* modifies r1, r2, r26 */ + nop + + b,l rfi_real2virt,%r2 + nop + + tovirt %sp + ldd -8(%sp), %sp /* restore SP */ + ldd -0x10(%sp), %rp /* restore RP */ + bv 0(%rp) + nop + +#endif diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/sba_iommu.c linux/arch/parisc/kernel/sba_iommu.c --- v2.4.0-test11/linux/arch/parisc/kernel/sba_iommu.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/sba_iommu.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,1752 @@ +/* +** System Bus Adapter (SBA) I/O MMU manager +** +** (c) Copyright 2000 Grant Grundler +** (c) Copyright 2000 Hewlett-Packard Company +** +** Portions (c) 1999 Dave S. Miller (from sparc64 I/O MMU code) +** +** 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 module initializes the IOC (I/O Controller) found on B1000/C3000/ +** J5000/J7000/N-class/L-class machines and their successors. +** +** FIXME: Multi-IOC support missing - depends on hp_device data +** FIXME: add DMA hint support programming in both sba and lba modules. +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#define PCI_DEBUG /* for ASSERT */ +#include +#undef PCI_DEBUG + +#include +#include +#include /* for DMA_CHUNK_SIZE */ + +#include /* for register_driver() stuff */ +#include /* FIXME: for gsc_read/gsc_write */ + +#include +#include /* for proc_runway_root */ + + +#define MODULE_NAME "SBA" + +/* +** The number of debug flags is a clue - this code is fragile. +** Don't even think about messing with it unless you have +** plenty of 710's to sacrafice to the computer gods. :^) +*/ +#undef DEBUG_SBA_INIT +#undef DEBUG_SBA_RUN +#undef DEBUG_SBA_RUN_SG +#undef DEBUG_SBA_RESOURCE +#undef ASSERT_PDIR_SANITY +#undef DEBUG_LARGE_SG_ENTRIES + +#if 1 +#define SBA_INLINE +#else +#define SBA_INLINE __inline__ +#endif + +#ifdef DEBUG_SBA_INIT +#define DBG_INIT(x...) printk(x) +#else +#define DBG_INIT(x...) +#endif + +#ifdef DEBUG_SBA_RUN +#define DBG_RUN(x...) printk(x) +#else +#define DBG_RUN(x...) +#endif + +#ifdef DEBUG_SBA_RUN_SG +#define DBG_RUN_SG(x...) printk(x) +#else +#define DBG_RUN_SG(x...) +#endif + + +#ifdef DEBUG_SBA_RESOURCE +#define DBG_RES(x...) printk(x) +#else +#define DBG_RES(x...) +#endif + +/* +** The number of pdir entries to "free" before issueing +** a read to PCOM register to flush out PCOM writes. +** Interacts with allocation granularity (ie 4 or 8 entries +** allocated and free'd/purged at a time might make this +** less interesting). +*/ +#if 0 +#define DELAYED_RESOURCE_CNT 16 +#else +#undef DELAYED_RESOURCE_CNT +#endif + +#define DEFAULT_DMA_HINT_REG 0 + +#define ASTRO_RUNWAY_PORT 0x582 +#define ASTRO_ROPES_PORT 0x780 + +#define IKE_MERCED_PORT 0x803 +#define IKE_ROPES_PORT 0x781 + +int sba_driver_callback(struct hp_device *, struct pa_iodc_driver *); + +static struct pa_iodc_driver sba_drivers_for[] = { + +/* FIXME: why is SVERSION checked? */ + + {HPHW_IOA, ASTRO_RUNWAY_PORT, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, + + {HPHW_BCPORT, ASTRO_ROPES_PORT, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, + +#if 0 +/* FIXME : N-class! Use a different "callback"? */ + {HPHW_BCPORT, IKE_MERCED_PORT, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, + + {HPHW_BCPORT, IKE_ROPES_PORT, 0x0, 0xb, 0, 0x10, + DRIVER_CHECK_HVERSION + + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + MODULE_NAME, "I/O MMU", (void *) sba_driver_callback}, +#endif + + {0,0,0,0,0,0, + 0, + (char *) NULL, (char *) NULL, (void *) NULL } +}; + + +#define SBA_FUNC_ID 0x0000 /* function id */ +#define SBA_FCLASS 0x0008 /* function class, bist, header, rev... */ + +#define IS_ASTRO(id) ( \ + (((id)->hw_type == HPHW_IOA) && ((id)->hversion == ASTRO_RUNWAY_PORT)) || \ + (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == ASTRO_ROPES_PORT)) \ +) + +#define CONFIG_FUNC_SIZE 4096 /* SBA configuration function reg set */ + +#define ASTRO_IOC_OFFSET 0x20000 +/* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */ +#define IKE_IOC_OFFSET(p) ((p+2)*CONFIG_FUNC_SIZE) + +#define IOC_CTRL 0x8 /* IOC_CTRL offset */ +#define IOC_CTRL_TE (0x1 << 0) /* TOC Enable */ +#define IOC_CTRL_RM (0x1 << 8) /* Real Mode */ +#define IOC_CTRL_NC (0x1 << 9) /* Non Coherent Mode */ + +#define MAX_IOC 2 /* per Ike. Astro only has 1 */ + + +/* +** Offsets into MBIB (Function 0 on Ike and hopefully Astro) +** Firmware programs this stuff. Don't touch it. +*/ +#define IOS_DIST_BASE 0x390 +#define IOS_DIST_MASK 0x398 +#define IOS_DIST_ROUTE 0x3A0 + +#define IOS_DIRECT_BASE 0x3C0 +#define IOS_DIRECT_MASK 0x3C8 +#define IOS_DIRECT_ROUTE 0x3D0 + +/* +** Offsets into I/O TLB (Function 2 and 3 on Ike) +*/ +#define ROPE0_CTL 0x200 /* "regbus pci0" */ +#define ROPE1_CTL 0x208 +#define ROPE2_CTL 0x210 +#define ROPE3_CTL 0x218 +#define ROPE4_CTL 0x220 +#define ROPE5_CTL 0x228 +#define ROPE6_CTL 0x230 +#define ROPE7_CTL 0x238 + +#define HF_ENABLE 0x40 + + +#define IOC_IBASE 0x300 /* IO TLB */ +#define IOC_IMASK 0x308 +#define IOC_PCOM 0x310 +#define IOC_TCNFG 0x318 +#define IOC_PDIR_BASE 0x320 + +#define IOC_IOVA_SPACE_BASE 0 /* IOVA ranges start at 0 */ + +/* +** IOC supports 4/8/16/64KB page sizes (see TCNFG register) +** It's safer (avoid memory corruption) to keep DMA page mappings +** equivalently sized to VM PAGE_SIZE. +** +** We really can't avoid generating a new mapping for each +** page since the Virtual Coherence Index has to be generated +** and updated for each page. +** +** IOVP_SIZE could only be greater than PAGE_SIZE if we are +** confident the drivers really only touch the next physical +** page iff that driver instance owns it. +*/ +#define IOVP_SIZE PAGE_SIZE +#define IOVP_SHIFT PAGE_SHIFT +#define IOVP_MASK PAGE_MASK + +#define SBA_PERF_CFG 0x708 /* Performance Counter stuff */ +#define SBA_PERF_MASK1 0x718 +#define SBA_PERF_MASK2 0x730 + + +/* +** Offsets into PCI Performance Counters (functions 12 and 13) +** Controlled by PERF registers in function 2 & 3 respectively. +*/ +#define SBA_PERF_CNT1 0x200 +#define SBA_PERF_CNT2 0x208 +#define SBA_PERF_CNT3 0x210 + + +struct ioc { + char *ioc_hpa; /* I/O MMU base address */ + char *res_map; /* resource map, bit == pdir entry */ + u64 *pdir_base; /* physical base address */ + + unsigned long *res_hint; /* next available IOVP - circular search */ + unsigned int res_bitshift; /* from the LEFT! */ + unsigned int res_size; /* size of resource map in bytes */ + unsigned int hint_shift_pdir; + spinlock_t res_lock; + unsigned long hint_mask_pdir; /* bits used for DMA hints */ +#ifdef DELAYED_RESOURCE_CNT + dma_addr_t res_delay[DELAYED_RESOURCE_CNT]; +#endif + +#ifdef CONFIG_PROC_FS +#define SBA_SEARCH_SAMPLE 0x100 + unsigned long avg_search[SBA_SEARCH_SAMPLE]; + unsigned long avg_idx; /* current index into avg_search */ + unsigned long used_pages; + unsigned long msingle_calls; + unsigned long msingle_pages; + unsigned long msg_calls; + unsigned long msg_pages; + unsigned long usingle_calls; + unsigned long usingle_pages; + unsigned long usg_calls; + unsigned long usg_pages; +#endif + + /* STUFF We don't need in performance path */ + unsigned int pdir_size; /* in bytes, determined by IOV Space size */ + unsigned long ibase; /* pdir IOV Space base - shared w/lba_pci */ + unsigned long imask; /* pdir IOV Space mask - shared w/lba_pci */ +}; + +struct sba_device { + struct sba_device *next; /* list of LBA's in system */ + struct hp_device *iodc; /* data about dev from firmware */ + char *sba_hpa; /* base address */ + spinlock_t sba_lock; + unsigned int flags; /* state/functionality enabled */ + unsigned int hw_rev; /* HW revision of chip */ + + unsigned int num_ioc; /* number of on-board IOC's */ + struct ioc ioc[MAX_IOC]; +}; + + +static struct sba_device *sba_list; +static int sba_count; + +/* Ratio of Host MEM to IOV Space size */ +static unsigned long sba_mem_ratio = 4; + +/* Looks nice and keeps the compiler happy */ +#define SBA_DEV(d) ((struct sba_device *) (d)) + + +#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1)) + + +/************************************ +** SBA register read and write support +** +** BE WARNED: register writes are posted. +** (ie follow writes which must reach HW with a read) +*/ +#define READ_U8(addr) gsc_readb(addr) +#define READ_U16(addr) gsc_readw((u16 *) (addr)) +#define READ_U32(addr) gsc_readl((u32 *) (addr)) +#define WRITE_U8(value, addr) gsc_writeb(value, addr) +#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr)) +#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr)) + +#define READ_REG8(addr) gsc_readb(addr) +#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr))) +#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr))) +#define READ_REG64(addr) le64_to_cpu(gsc_readq((u64 *) (addr))) +#define WRITE_REG8(value, addr) gsc_writeb(value, addr) +#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr)) +#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr)) +#define WRITE_REG64(value, addr) gsc_writeq(cpu_to_le64(value), (u64 *) (addr)) + +#ifdef DEBUG_SBA_INIT + +static void +sba_dump_ranges(char *hpa) +{ + printk("SBA at 0x%p\n", hpa); + printk("IOS_DIST_BASE : %08x %08x\n", + READ_REG32(hpa+IOS_DIST_BASE+4), + READ_REG32(hpa+IOS_DIST_BASE)); + printk("IOS_DIST_MASK : %08x %08x\n", + READ_REG32(hpa+IOS_DIST_MASK+4), + READ_REG32(hpa+IOS_DIST_MASK)); + printk("IOS_DIST_ROUTE : %08x %08x\n", + READ_REG32(hpa+IOS_DIST_ROUTE+4), + READ_REG32(hpa+IOS_DIST_ROUTE)); + printk("\n"); + printk("IOS_DIRECT_BASE : %08x %08x\n", + READ_REG32(hpa+IOS_DIRECT_BASE+4), + READ_REG32(hpa+IOS_DIRECT_BASE)); + printk("IOS_DIRECT_MASK : %08x %08x\n", + READ_REG32(hpa+IOS_DIRECT_MASK+4), + READ_REG32(hpa+IOS_DIRECT_MASK)); + printk("IOS_DIRECT_ROUTE: %08x %08x\n", + READ_REG32(hpa+IOS_DIRECT_ROUTE+4), + READ_REG32(hpa+IOS_DIRECT_ROUTE)); +} + +static void +sba_dump_tlb(char *hpa) +{ + printk("IO TLB at 0x%p\n", hpa); + printk("IOC_IBASE : %08x %08x\n", + READ_REG32(hpa+IOC_IBASE+4), + READ_REG32(hpa+IOC_IBASE)); + printk("IOC_IMASK : %08x %08x\n", + READ_REG32(hpa+IOC_IMASK+4), + READ_REG32(hpa+IOC_IMASK)); + printk("IOC_TCNFG : %08x %08x\n", + READ_REG32(hpa+IOC_TCNFG+4), + READ_REG32(hpa+IOC_TCNFG)); + printk("IOC_PDIR_BASE: %08x %08x\n", + READ_REG32(hpa+IOC_PDIR_BASE+4), + READ_REG32(hpa+IOC_PDIR_BASE)); + printk("\n"); +} +#endif + + +#ifdef ASSERT_PDIR_SANITY + +static void +sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide) +{ + /* start printing from lowest pde in rval */ + u64 *ptr = &(ioc->pdir_base[pide & (~0U * BITS_PER_LONG)]); + unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]); + uint rcnt; + + printk("SBA: %s rp %p bit %d rval 0x%lx\n", + msg, + rptr, pide & (BITS_PER_LONG - 1), *rptr); + + rcnt = 0; + while (rcnt < BITS_PER_LONG) { + printk("%s %2d %p %016Lx\n", + (rcnt == (pide & (BITS_PER_LONG - 1))) + ? " -->" : " ", + rcnt, ptr, *ptr ); + rcnt++; + ptr++; + } + printk(msg); +} + + +/* Verify the resource map and pdir state is consistent */ +static int +sba_check_pdir(struct ioc *ioc, char *msg) +{ + u32 *rptr_end = (u32 *) &(ioc->res_map[ioc->res_size]); + u32 *rptr = (u32 *) ioc->res_map; /* resource map ptr */ + u64 *pptr = ioc->pdir_base; /* pdir ptr */ + uint pide = 0; + + while (rptr < rptr_end) { + u32 rval = *rptr; + int rcnt = 32; /* number of bits we might check */ + + while (rcnt) { + /* Get last byte and highest bit from that */ + u32 pde = ((u32) (((char *)pptr)[7])) << 24; + if ((rval ^ pde) & 0x80000000) + { + /* + ** BUMMER! -- res_map != pdir -- + ** Dump rval and matching pdir entries + */ + sba_dump_pdir_entry(ioc, msg, pide); + return(1); + } + rcnt--; + rval <<= 1; /* try the next bit */ + pptr++; + pide++; + } + rptr++; /* look at next word of res_map */ + } + /* It'd be nice if we always got here :^) */ + return 0; +} + + +static void +sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents) +{ + while (nents-- > 0) { + printk(" %d : %08lx/%05x %p/%05x\n", + nents, + (unsigned long) sg_dma_address(startsg), + sg_dma_len(startsg), + startsg->address, startsg->length); + startsg++; + } +} + +#endif /* ASSERT_PDIR_SANITY */ + + + +/* +** One time initialization to let the world know the LBA was found. +** This is the only routine which is NOT static. +** Must be called exactly once before pci_init(). +*/ +void __init +sba_init(void) +{ + sba_list = (struct sba_device *) NULL; + sba_count = 0; + +#ifdef DEBUG_SBA_INIT + sba_dump_ranges((char *) 0xFED00000L); +#endif + + register_driver(sba_drivers_for); +} + + + +/************************************************************** +* +* I/O Pdir Resource Management +* +* Bits set in the resource map are in use. +* Each bit can represent a number of pages. +* LSbs represent lower addresses (IOVA's). +* +***************************************************************/ +#define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ + +/* Convert from IOVP to IOVA and vice versa. */ +#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((iovp) | (offset) | ((hint_reg)<<(ioc->hint_shift_pdir))) +#define SBA_IOVP(ioc,iova) ((iova) & ioc->hint_mask_pdir) + +/* FIXME : review these macros to verify correctness and usage */ +#define PDIR_INDEX(iovp) ((iovp)>>IOVP_SHIFT) +#define MKIOVP(dma_hint,pide) (dma_addr_t)((long)(dma_hint) | ((long)(pide) << IOVP_SHIFT)) +#define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset) + +#define RESMAP_MASK(n) (~0UL << (BITS_PER_LONG - (n))) +#define RESMAP_IDX_MASK (sizeof(unsigned long) - 1) + + +/* +** Perf optimizations: +** o search for log2(size) bits at a time. +** +** Search should use register width as "stride" to search the res_map. +*/ + +static SBA_INLINE unsigned long +sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted) +{ + unsigned long *res_ptr = ioc->res_hint; + unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]); + unsigned long pide = ~0UL; + + ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0); + ASSERT(res_ptr < res_end); + if (bits_wanted > (BITS_PER_LONG/2)) { + /* Search word at a time - no mask needed */ + for(; res_ptr < res_end; ++res_ptr) { + if (*res_ptr == 0) { + *res_ptr = RESMAP_MASK(bits_wanted); + pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); + pide <<= 3; /* convert to bit address */ + ASSERT(0 != pide); + break; + } + } + /* point to the next word on next pass */ + res_ptr++; + ioc->res_bitshift = 0; + } else { + /* + ** Search the resource bit map on well-aligned values. + ** "o" is the alignment. + ** We need the alignment to invalidate I/O TLB using + ** SBA HW features in the unmap path. + */ + unsigned long o = 1 << get_order(bits_wanted << PAGE_SHIFT); + uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); + unsigned long mask; + + if (bitshiftcnt >= BITS_PER_LONG) { + bitshiftcnt = 0; + res_ptr++; + } + mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt; + + DBG_RES("sba_search_bitmap() o %ld %p", o, res_ptr); + while(res_ptr < res_end) + { + DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); + ASSERT(0 != mask); + if(0 == ((*res_ptr) & mask)) { + *res_ptr |= mask; /* mark resources busy! */ + pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); + pide <<= 3; /* convert to bit address */ + pide += bitshiftcnt; + ASSERT(0 != pide); + break; + } + mask >>= o; + bitshiftcnt += o; + if (0 == mask) { + mask = RESMAP_MASK(bits_wanted); + bitshiftcnt=0; + res_ptr++; + } + } + /* look in the same word on the next pass */ + ioc->res_bitshift = bitshiftcnt + bits_wanted; + } + + /* wrapped ? */ + ioc->res_hint = (res_end == res_ptr) ? (unsigned long *) ioc->res_map : res_ptr; + return (pide); +} + + +static int +sba_alloc_range(struct ioc *ioc, size_t size) +{ + unsigned int pages_needed = size >> IOVP_SHIFT; +#ifdef CONFIG_PROC_FS + unsigned long cr_start = mfctl(16); +#endif + unsigned long pide; + + ASSERT(pages_needed); + ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE); + ASSERT(pages_needed < BITS_PER_LONG); + ASSERT(0 == (size & ~IOVP_MASK)); + + /* + ** "seek and ye shall find"...praying never hurts either... + ** ggg sacrifices another 710 to the computer gods. + */ + + pide = sba_search_bitmap(ioc, pages_needed); + if (pide >= (ioc->res_size << 3)) { + pide = sba_search_bitmap(ioc, pages_needed); + if (pide >= (ioc->res_size << 3)) + panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa); + } + +#ifdef ASSERT_PDIR_SANITY + /* verify the first enable bit is clear */ + if(0x00 != ((u8 *) ioc->pdir_base)[pide*sizeof(u64) + 7]) { + sba_dump_pdir_entry(ioc, "sba_search_bitmap() botched it?", pide); + } +#endif + + DBG_RES("sba_alloc_range(%x) %d -> %lx hint %x/%x\n", + size, pages_needed, pide, + (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), + ioc->res_bitshift ); + +#ifdef CONFIG_PROC_FS + { + unsigned long cr_end = mfctl(16); + unsigned long tmp = cr_end - cr_start; + /* check for roll over */ + cr_start = (cr_end < cr_start) ? -(tmp) : (tmp); + } + ioc->avg_search[ioc->avg_idx++] = cr_start; + ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1; + + ioc->used_pages += pages_needed; +#endif + + return (pide); +} + + +/* +** clear bits in the ioc's resource map +*/ +static SBA_INLINE void +sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) +{ + unsigned long iovp = SBA_IOVP(ioc, iova); + unsigned int pide = PDIR_INDEX(iovp); + unsigned int ridx = pide >> 3; /* convert bit to byte address */ + unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]); + + int bits_not_wanted = size >> IOVP_SHIFT; + + /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ + unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1)); + + DBG_RES("sba_free_range( ,%x,%x) %x/%lx %x %p %lx\n", + (uint) iova, size, + bits_not_wanted, m, pide, res_ptr, *res_ptr); + +#ifdef CONFIG_PROC_FS + ioc->used_pages -= bits_not_wanted; +#endif + + ASSERT(m != 0); + ASSERT(bits_not_wanted); + ASSERT((bits_not_wanted * IOVP_SIZE) < DMA_CHUNK_SIZE); + ASSERT(bits_not_wanted < BITS_PER_LONG); + ASSERT((*res_ptr & m) == m); /* verify same bits are set */ + *res_ptr &= ~m; +} + + +/************************************************************** +* +* "Dynamic DMA Mapping" support (aka "Coherent I/O") +* +***************************************************************/ + +#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir) + + +typedef unsigned long space_t; +#define KERNEL_SPACE 0 + +/* +* SBA Mapping Routine +* +* Given a virtual address (vba, arg2) and space id, (sid, arg1) +* sba_io_pdir_entry() loads the I/O PDIR entry pointed to by +* pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as +* shown below (MSB == bit 0): +* +* 0 19 51 55 63 +* +-+---------------------+----------------------------------+----+--------+ +* |V| U | PPN[43:12] | U | VI | +* +-+---------------------+----------------------------------+----+--------+ +* +* V == Valid Bit +* U == Unused +* PPN == Physical Page Number +* VI == Virtual Index (aka Coherent Index) +* +* The physical address fields are filled with the results of the LPA +* instruction. The virtual index field is filled with the results of +* of the LCI (Load Coherence Index) instruction. The 8 bits used for +* the virtual index are bits 12:19 of the value returned by LCI. +* +* We need to pre-swap the bytes since PCX-W is Big Endian. +*/ + +void SBA_INLINE +sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba) +{ + u64 pa; /* physical address */ + register unsigned ci; /* coherent index */ + + /* We currently only support kernel addresses */ + ASSERT(sid == 0); + ASSERT(((unsigned long) vba & 0xc0000000UL) == 0xc0000000UL); + + pa = virt_to_phys(vba); + pa &= ~4095ULL; /* clear out offset bits */ + + mtsp(sid,1); + asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba)); + pa |= (ci >> 12) & 0xff; /* move CI (8 bits) into lowest byte */ + + pa |= 0x8000000000000000ULL; /* set "valid" bit */ + *pdir_ptr = cpu_to_le64(pa); /* swap and store into I/O Pdir */ +} + + +/*********************************************************** + * The Ike PCOM (Purge Command Register) is to purge + * stale entries in the IO TLB when unmapping entries. + * + * The PCOM register supports purging of multiple pages, with a minium + * of 1 page and a maximum of 2GB. Hardware requires the address be + * aligned to the size of the range being purged. The size of the range + * must be a power of 2. + ***********************************************************/ +static SBA_INLINE void +sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) +{ + u32 iovp = (u32) SBA_IOVP(ioc,iova); + + /* Even though this is a big-endian machine, the entries + ** in the iopdir are swapped. That's why we clear the byte + ** at +7 instead of at +0. + */ + int off = PDIR_INDEX(iovp)*sizeof(u64)+7; + + /* Must be non-zero and rounded up */ + ASSERT(byte_cnt > 0); + ASSERT(0 == (byte_cnt & ~IOVP_MASK)); + +#ifdef ASSERT_PDIR_SANITY + /* Assert first pdir entry is set */ + if (0x80 != (((u8 *) ioc->pdir_base)[off])) { + sba_dump_pdir_entry(ioc,"sba_mark_invalid()", PDIR_INDEX(iovp)); + } +#endif + + if (byte_cnt <= IOVP_SIZE) + { + ASSERT( off < ioc->pdir_size); + + iovp |= IOVP_SHIFT; /* set "size" field for PCOM */ + + /* + ** clear I/O PDIR entry "valid" bit + ** Do NOT clear the rest - save it for debugging. + ** We should only clear bits that have previously + ** been enabled. + */ + ((u8 *)(ioc->pdir_base))[off] = 0; + } else { + u32 t = get_order(byte_cnt) + PAGE_SHIFT; + + iovp |= t; + ASSERT(t <= 31); /* 2GB! Max value of "size" field */ + + do { + /* verify this pdir entry is enabled */ + ASSERT(0x80 == (((u8 *) ioc->pdir_base)[off] & 0x80)); + /* clear I/O Pdir entry "valid" bit first */ + ((u8 *)(ioc->pdir_base))[off] = 0; + off += sizeof(u64); + byte_cnt -= IOVP_SIZE; + } while (byte_cnt > 0); + } + + WRITE_REG32(iovp, ioc->ioc_hpa+IOC_PCOM); +} + +static int +sba_dma_supported( struct pci_dev *dev, dma_addr_t mask) +{ + if (dev == NULL) { + printk(MODULE_NAME ": EISA/ISA/et al not supported\n"); + BUG(); + return(0); + } + + dev->dma_mask = mask; /* save it */ + + /* only support PCI devices */ + return((int) (mask >= 0xffffffff)); +} + + +/* +** map_single returns a fully formed IOVA +*/ +static dma_addr_t +sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction) +{ + struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */ + unsigned long flags; + dma_addr_t iovp; + dma_addr_t offset; + u64 *pdir_start; + int pide; + + ASSERT(size > 0); + + /* save offset bits */ + offset = ((dma_addr_t) addr) & ~IOVP_MASK; + + /* round up to nearest IOVP_SIZE */ + size = (size + offset + ~IOVP_MASK) & IOVP_MASK; + + spin_lock_irqsave(&ioc->res_lock, flags); +#ifdef ASSERT_PDIR_SANITY + sba_check_pdir(ioc,"Check before sba_map_single()"); +#endif + +#ifdef CONFIG_PROC_FS + ioc->msingle_calls++; + ioc->msingle_pages += size >> IOVP_SHIFT; +#endif + pide = sba_alloc_range(ioc, size); + iovp = (dma_addr_t) pide << IOVP_SHIFT; + + DBG_RUN("sba_map_single() 0x%p -> 0x%lx", addr, (long) iovp | offset); + + pdir_start = &(ioc->pdir_base[pide]); + + while (size > 0) { + ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */ + sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr); + + DBG_RUN(" pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n", + pdir_start, + (u8) (((u8 *) pdir_start)[7]), + (u8) (((u8 *) pdir_start)[6]), + (u8) (((u8 *) pdir_start)[5]), + (u8) (((u8 *) pdir_start)[4]), + (u8) (((u8 *) pdir_start)[3]), + (u8) (((u8 *) pdir_start)[2]), + (u8) (((u8 *) pdir_start)[1]), + (u8) (((u8 *) pdir_start)[0]) + ); + + addr += IOVP_SIZE; + size -= IOVP_SIZE; + pdir_start++; + } + /* form complete address */ +#ifdef ASSERT_PDIR_SANITY + sba_check_pdir(ioc,"Check after sba_map_single()"); +#endif + spin_unlock_irqrestore(&ioc->res_lock, flags); + return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG); +} + + +static void +sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction) +{ +#ifdef FIXME +/* Multi-IOC (ie N-class) : need to lookup IOC from dev +** o If we can't know about lba PCI data structs, that eliminates ->sysdata. +** o walking up pcidev->parent dead ends at elroy too +** o leaves hashing dev->bus->number into some lookup. +** (may only work for N-class) +** o use (struct pci_hba) and put fields in there for DMA. +** (ioc and per device dma_hint.) +** +** Last one seems the clearest and most promising. +** sba_dma_supported() fill in those fields when the driver queries +** the system for support. +*/ + struct ioc *ioc = (struct ioc *) ((struct pci_hba *) (dev->sysdata))->dma_data; +#else + struct ioc *ioc = &sba_list->ioc[0]; +#endif + + unsigned long flags; + dma_addr_t offset; + offset = iova & ~IOVP_MASK; + + DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size); + + iova ^= offset; /* clear offset bits */ + size += offset; + size = ROUNDUP(size, IOVP_SIZE); + + ASSERT(0 != iova); + + spin_lock_irqsave(&ioc->res_lock, flags); +#ifdef CONFIG_PROC_FS + ioc->usingle_calls++; + ioc->usingle_pages += size >> IOVP_SHIFT; +#endif +#ifdef DELAYED_RESOURCE_CNT + if (ioc->saved_cnt < DELAYED_RESOURCE_CNT) { + ioc->saved_iova[ioc->saved_cnt] = iova; + ioc->saved_size[ioc->saved_cnt] = size; + ioc_saved_cnt++; + } else { + do { +#endif + sba_mark_invalid(ioc, iova, size); + sba_free_range(ioc, iova, size); + +#ifdef DELAYED_RESOURCE_CNT + ioc->saved_cnt--; + iova = ioc->saved_iova[ioc->saved_cnt]; + size = ioc->saved_size[ioc->saved_cnt]; + } while (ioc->saved_cnt) + + /* flush purges */ + (void) (volatile) READ_REG32(ioc->ioc_hpa+IOC_PCOM); + } +#else + /* flush purges */ + READ_REG32(ioc->ioc_hpa+IOC_PCOM); +#endif + spin_unlock_irqrestore(&ioc->res_lock, flags); +} + + +static void * +sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) +{ + void *ret; + + if (!hwdev) { + /* only support PCI */ + *dma_handle = 0; + return 0; + } + + ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size)); + + if (ret) { + memset(ret, 0, size); + *dma_handle = sba_map_single(hwdev, ret, size, 0); + } + + return ret; +} + + +static void +sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) +{ + sba_unmap_single(hwdev, dma_handle, size, 0); + free_pages((unsigned long) vaddr, get_order(size)); +} + +/* +** Two address ranges are "virtually contiguous" iff: +** 1) end of prev == start of next, or... append case +** 3) end of next == start of prev prepend case +** +** and they are DMA contiguous *iff*: +** 2) end of prev and start of next are both on a page boundry +** +** (shift left is a quick trick to mask off upper bits) +*/ +#define DMA_CONTIG(__X, __Y) \ + (((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL) + +/* +** Assumption is two transactions are mutually exclusive. +** ie both go to different parts of memory. +** If both are true, then both transaction are on the same page. +*/ +#define DMA_SAME_PAGE(s1,e1,s2,e2) \ + ( ((((s1) ^ (s2)) >> PAGE_SHIFT) == 0) \ + && ((((e1) ^ (e2)) >> PAGE_SHIFT) == 0) ) + +/* +** Since 0 is a valid pdir_base index value, can't use that +** to determine if a value is valid or not. Use a flag to indicate +** the SG list entry contains a valid pdir index. +*/ +#define PIDE_FLAG 0x80000000UL + +#ifdef DEBUG_LARGE_SG_ENTRIES +int dump_run_sg = 0; +#endif + +static SBA_INLINE int +sba_fill_pdir( + struct ioc *ioc, + struct scatterlist *startsg, + int nents) +{ + struct scatterlist *dma_sg = startsg; /* pointer to current DMA */ + int n_mappings = 0; + u64 *pdirp = 0; + unsigned long dma_offset = 0; + + dma_sg--; + while (nents-- > 0) { + int cnt = sg_dma_len(startsg); + sg_dma_len(startsg) = 0; + +#ifdef DEBUG_LARGE_SG_ENTRIES + if (dump_run_sg) + printk(" %d : %08lx/%05x %p/%05x\n", + nents, + (unsigned long) sg_dma_address(startsg), cnt, + startsg->address, startsg->length + ); +#else + DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", + nents, + (unsigned long) sg_dma_address(startsg), cnt, + startsg->address, startsg->length + ); +#endif + /* + ** Look for the start of a new DMA stream + */ + if (sg_dma_address(startsg) & PIDE_FLAG) { + u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG; + dma_offset = (unsigned long) pide & ~IOVP_MASK; + pide >>= IOVP_SHIFT; + pdirp = &(ioc->pdir_base[pide]); + sg_dma_address(startsg) = 0; + ++dma_sg; + sg_dma_address(dma_sg) = (pide << IOVP_SHIFT) + dma_offset; + n_mappings++; + } + + /* + ** Look for a VCONTIG chunk + */ + if (cnt) { + unsigned long vaddr = (unsigned long) startsg->address; + ASSERT(pdirp); + + sg_dma_len(dma_sg) += cnt; + cnt += dma_offset; + dma_offset=0; /* only want offset on first chunk */ + cnt = ROUNDUP(cnt, IOVP_SIZE); +#ifdef CONFIG_PROC_FS + ioc->msg_pages += cnt >> IOVP_SHIFT; +#endif + do { + sba_io_pdir_entry(pdirp, KERNEL_SPACE, vaddr); + vaddr += IOVP_SIZE; + cnt -= IOVP_SIZE; + pdirp++; + } while (cnt > 0); + } + startsg++; + } +#ifdef DEBUG_LARGE_SG_ENTRIES + dump_run_sg = 0; +#endif + return(n_mappings); +} + + + +/* +** First pass is to walk the SG list and determine where the breaks are +** in the DMA stream. Allocates PDIR entries but does not fill them. +** Returns the number of DMA chunks. +** +** Doing the fill seperate from the coalescing/allocation keeps the +** code simpler. Future enhancement could make one pass through +** the sglist do both. +*/ +static SBA_INLINE int +sba_coalesce_chunks( struct ioc *ioc, + struct scatterlist *startsg, + int nents) +{ + int n_mappings = 0; + + while (nents > 0) { + struct scatterlist *dma_sg; /* next DMA stream head */ + unsigned long dma_offset, dma_len; /* start/len of DMA stream */ + struct scatterlist *chunksg; /* virtually contig chunk head */ + unsigned long chunk_addr, chunk_len; /* start/len of VCONTIG chunk */ + + /* + ** Prepare for first/next DMA stream + */ + dma_sg = chunksg = startsg; + dma_len = chunk_len = startsg->length; + chunk_addr = (unsigned long) startsg->address; + dma_offset = 0UL; + + /* + ** This loop terminates one iteration "early" since + ** it's always looking one "ahead". + */ + while (--nents > 0) { + /* ptr to coalesce prev and next */ + struct scatterlist *prev_sg = startsg; + unsigned long prev_end = (unsigned long) prev_sg->address + prev_sg->length; + unsigned long current_end; + + /* PARANOID: clear entries */ + sg_dma_address(startsg) = 0; + sg_dma_len(startsg) = 0; + + /* Now start looking ahead */ + startsg++; + current_end = (unsigned long) startsg->address + startsg->length; + + /* + ** First look for virtually contiguous blocks. + ** PARISC needs this since it's cache is virtually + ** indexed and we need the associated virtual + ** address for each I/O address we map. + ** + ** 1) can we *prepend* the next transaction? + */ + if (current_end == (unsigned long) prev_sg->address) + { + /* prepend : get new offset */ + chunksg = startsg; + chunk_addr = (unsigned long) prev_sg->address; + chunk_len += startsg->length; + dma_len += startsg->length; + continue; + } + + /* + ** 2) or append the next transaction? + */ + if (prev_end == (unsigned long) startsg->address) + { + chunk_len += startsg->length; + dma_len += startsg->length; + continue; + } + +#ifdef DEBUG_LARGE_SG_ENTRIES + dump_run_sg = (chunk_len > IOVP_SIZE); +#endif + /* + ** Not virtually contigous. + ** Terminate prev chunk. + ** Start a new chunk. + ** + ** Once we start a new VCONTIG chunk, the offset + ** can't change. And we need the offset from the first + ** chunk - not the last one. Ergo Successive chunks + ** must start on page boundaries and dove tail + ** with it's predecessor. + */ + sg_dma_len(prev_sg) = chunk_len; + + chunk_len = startsg->length; + dma_offset |= (chunk_addr & ~IOVP_MASK); + ASSERT((0 == (chunk_addr & ~IOVP_MASK)) || + (dma_offset == (chunk_addr & ~IOVP_MASK))); + +#if 0 + /* + ** 4) do the chunks end/start on page boundaries? + ** Easier than 3 since no offsets are involved. + */ + if (DMA_CONTIG(prev_end, startsg->address)) + { + /* + ** Yes. + ** Reset chunk ptr. + */ + chunksg = startsg; + chunk_addr = (unsigned long) startsg->address; + + continue; + } else +#endif + { + break; + } + } + + /* + ** End of DMA Stream + ** Terminate chunk. + ** Allocate space for DMA stream. + */ + sg_dma_len(startsg) = chunk_len; + dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK; + sg_dma_address(dma_sg) = + PIDE_FLAG + | (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT) + | dma_offset; + n_mappings++; + } + + return n_mappings; +} + + +/* +** And this algorithm still generally only ends up coalescing entries +** that happens to be on the same page due to how sglists are assembled. +*/ +static int +sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */ + int coalesced, filled = 0; + unsigned long flags; + + DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + + /* Fast path single entry scatterlists. */ + if (nents == 1) { + sg_dma_address(sglist)= sba_map_single(dev, sglist->address, + sglist->length, direction); + sg_dma_len(sglist)= sglist->length; + return 1; + } + + spin_lock_irqsave(&ioc->res_lock, flags); + +#ifdef ASSERT_PDIR_SANITY + if (sba_check_pdir(ioc,"Check before sba_map_sg()")) + { + sba_dump_sg(ioc, sglist, nents); + panic("Check before sba_map_sg()"); + } +#endif + +#ifdef CONFIG_PROC_FS + ioc->msg_calls++; +#endif + + /* + ** First coalesce the chunks and allocate I/O pdir space + ** + ** If this is one DMA stream, we can properly map using the + ** correct virtual address associated with each DMA page. + ** w/o this association, we wouldn't have coherent DMA! + ** Access to the virtual address is what forces a two pass algorithm. + */ + coalesced = sba_coalesce_chunks(ioc, sglist, nents); + + /* + ** Program the I/O Pdir + ** + ** map the virtual addresses to the I/O Pdir + ** o dma_address will contain the pdir index + ** o dma_len will contain the number of bytes to map + ** o address contains the virtual address. + */ + filled = sba_fill_pdir(ioc, sglist, nents); + +#ifdef ASSERT_PDIR_SANITY + if (sba_check_pdir(ioc,"Check after sba_map_sg()")) + { + sba_dump_sg(ioc, sglist, nents); + panic("Check after sba_map_sg()\n"); + } +#endif + + spin_unlock_irqrestore(&ioc->res_lock, flags); + + ASSERT(coalesced == filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + + return filled; +} + + +static void +sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction) +{ + struct ioc *ioc = &sba_list->ioc[0]; /* FIXME : see Multi-IOC below */ +#ifdef ASSERT_PDIR_SANITY + unsigned long flags; +#endif + + DBG_RUN_SG("%s() START %d entries, %p,%x\n", + __FUNCTION__, nents, sglist->address, sglist->length); + +#ifdef CONFIG_PROC_FS + ioc->usg_calls++; +#endif + +#ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); + sba_check_pdir(ioc,"Check before sba_unmap_sg()"); + spin_unlock_irqrestore(&ioc->res_lock, flags); +#endif + + while (sg_dma_len(sglist) && nents--) { + +#ifdef CONFIG_PROC_FS + ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT; +#endif + sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction); + ++sglist; + } + + DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); + +#ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); + sba_check_pdir(ioc,"Check after sba_unmap_sg()"); + spin_unlock_irqrestore(&ioc->res_lock, flags); +#endif + +} + +static struct pci_dma_ops sba_ops = { + sba_dma_supported, + sba_alloc_consistent, /* allocate cacheable host mem */ + sba_free_consistent, /* release cacheable host mem */ + sba_map_single, + sba_unmap_single, + sba_map_sg, + sba_unmap_sg, + NULL, /* dma_sync_single */ + NULL /* dma_sync_sg */ +}; + + +/************************************************************************** +** +** SBA PAT PDC support +** +** o call pdc_pat_cell_module() +** o store ranges in PCI "resource" structures +** +**************************************************************************/ + +static void +sba_get_pat_resources(struct sba_device *sba_dev) +{ +#if 0 +/* +** TODO/REVISIT/FIXME: support for directed ranges requires calls to +** PAT PDC to program the SBA/LBA directed range registers...this +** burden may fall on the LBA code since it directly supports the +** PCI subsystem. It's not clear yet. - ggg +*/ +PAT_MOD(mod)->mod_info.mod_pages = PAT_GET_MOD_PAGES(temp); + FIXME : ??? +PAT_MOD(mod)->mod_info.dvi = PAT_GET_DVI(temp); + Tells where the dvi bits are located in the address. +PAT_MOD(mod)->mod_info.ioc = PAT_GET_IOC(temp); + FIXME : ??? +#endif +} + + +/************************************************************** +* +* Initialization and claim +* +***************************************************************/ + + +static void +sba_ioc_init(struct ioc *ioc) +{ + extern unsigned long mem_max; /* arch.../setup.c */ + extern void lba_init_iregs(void *, u32, u32); /* arch.../lba_pci.c */ + + u32 iova_space_size, iova_space_mask; + void * pdir_base; + int pdir_size, iov_order; + + /* + ** Determine IOVA Space size from memory size. + ** Using "mem_max" is a kluge. + ** + ** Ideally, PCI drivers would register the maximum number + ** of DMA they can have outstanding for each device they + ** own. Next best thing would be to guess how much DMA + ** can be outstanding based on PCI Class/sub-class. Both + ** methods still require some "extra" to support PCI + ** Hot-Plug/Removal of PCI cards. (aka PCI OLARD). + ** + ** While we have 32-bits "IOVA" space, top two 2 bits are used + ** for DMA hints - ergo only 30 bits max. + */ + /* limit IOVA space size to 1MB-1GB */ + if (mem_max < (sba_mem_ratio*1024*1024)) { + iova_space_size = 1024*1024; +#ifdef __LP64__ + } else if (mem_max > (sba_mem_ratio*512*1024*1024)) { + iova_space_size = 512*1024*1024; +#endif + } else { + iova_space_size = (u32) (mem_max/sba_mem_ratio); + } + + /* + ** iova space must be log2() in size. + ** thus, pdir/res_map will also be log2(). + */ + iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT)); + ASSERT(iov_order <= (30 - IOVP_SHIFT)); /* iova_space_size <= 1GB */ + ASSERT(iov_order >= (20 - IOVP_SHIFT)); /* iova_space_size >= 1MB */ + iova_space_size = 1 << (iov_order + IOVP_SHIFT); + + ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); + + ASSERT(pdir_size < 4*1024*1024); /* max pdir size < 4MB */ + + /* Verify it's a power of two */ + ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT)); + + DBG_INIT("%s() hpa 0x%p mem %dMBIOV %dMB (%d bits) PDIR size 0x%0x", + __FUNCTION__, ioc->ioc_hpa, (int) (mem_max>>20), + iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size); + + /* FIXME : DMA HINTs not used */ + ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; + ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT)); + + ioc->pdir_base = + pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size)); + if (NULL == pdir_base) + { + panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__); + } + memset(pdir_base, 0, pdir_size); + + DBG_INIT("sba_ioc_init() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n", + pdir_base, pdir_size, + ioc->hint_shift_pdir, ioc->hint_mask_pdir); + + ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base); + WRITE_REG64(virt_to_phys(pdir_base), (u64 *)(ioc->ioc_hpa+IOC_PDIR_BASE)); + + DBG_INIT(" base %p\n", pdir_base); + + /* build IMASK for IOC and Elroy */ + iova_space_mask = 0xffffffff; + iova_space_mask <<= (iov_order + PAGE_SHIFT); + + /* + ** On C3000 w/512MB mem, HP-UX 10.20 reports: + ** ibase=0, imask=0xFE000000, size=0x2000000. + */ + ioc->ibase = IOC_IOVA_SPACE_BASE | 1; /* bit 0 == enable bit */ + ioc->imask = iova_space_mask; /* save it */ + + DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__, + ioc->ibase, ioc->imask); + + /* + ** FIXME: Hint registers are programmed with default hint + ** values during boot, so hints should be sane even if we + ** can't reprogram them the way drivers want. + */ + + /* + ** setup Elroy IBASE/IMASK registers as well. + */ + lba_init_iregs(ioc->ioc_hpa, ioc->ibase, ioc->imask); + + /* + ** Program the IOC's ibase and enable IOVA translation + */ + WRITE_REG32(ioc->ibase, ioc->ioc_hpa+IOC_IBASE); + WRITE_REG32(ioc->imask, ioc->ioc_hpa+IOC_IMASK); + + /* Set I/O PDIR Page size to 4K */ + WRITE_REG32(0, ioc->ioc_hpa+IOC_TCNFG); + + /* + ** Clear I/O TLB of any possible entries. + ** (Yes. This is a it paranoid...but so what) + */ + WRITE_REG32(0 | 31, ioc->ioc_hpa+IOC_PCOM); + + DBG_INIT("%s() DONE\n", __FUNCTION__); +} + + + +/************************************************************************** +** +** SBA initialization code (HW and SW) +** +** o identify SBA chip itself +** o initialize SBA chip modes (HardFail) +** o initialize SBA chip modes (HardFail) +** o FIXME: initialize DMA hints for reasonable defaults +** +**************************************************************************/ + +static void +sba_hw_init(struct sba_device *sba_dev) +{ + int i; + int num_ioc; + u32 ioc_ctl; + + ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL); + DBG_INIT("%s() hpa 0x%p ioc_ctl 0x%x ->", __FUNCTION__, sba_dev->sba_hpa, ioc_ctl ); + ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC); + ASSERT(ioc_ctl & IOC_CTRL_TE); /* astro: firmware enables this */ + + WRITE_REG32(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL); + +#ifdef SBA_DEBUG_INIT + ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL); + DBG_INIT(" 0x%x\n", ioc_ctl ); +#endif + + if (IS_ASTRO(sba_dev->iodc)) { + /* PAT_PDC (L-class) also reports the same goofy base */ + sba_dev->ioc[0].ioc_hpa = (char *) ASTRO_IOC_OFFSET; + num_ioc = 1; + } else { + sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0; + num_ioc = 2; + } + + sba_dev->num_ioc = num_ioc; + for( i = 0; i < num_ioc; i++) + { + (unsigned long) sba_dev->ioc[i].ioc_hpa += (unsigned long) sba_dev->sba_hpa + IKE_IOC_OFFSET(i); + + /* + ** Make sure the box crashes if we get any errors on a rope. + */ + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL); + WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); + + /* flush out the writes */ + READ_REG32(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL); + + sba_ioc_init(&(sba_dev->ioc[i])); + } +} + +static void +sba_common_init(struct sba_device *sba_dev) +{ + int i; + + /* add this one to the head of the list (order doesn't matter) + ** This will be useful for debugging - especially if we get coredumps + */ + sba_dev->next = sba_list; + sba_list = sba_dev; + sba_count++; + + for(i=0; i< sba_dev->num_ioc; i++) { + int res_size; +#ifdef CONFIG_DMB_TRAP + extern void iterate_pages(unsigned long , unsigned long , + void (*)(pte_t * , unsigned long), + unsigned long ); + void set_data_memory_break(pte_t * , unsigned long); +#endif + /* resource map size dictated by pdir_size */ + res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */ + res_size >>= 3; /* convert bit count to byte count */ + DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, res_size); + + sba_dev->ioc[i].res_size = res_size; + sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); + +#ifdef CONFIG_DMB_TRAP + iterate_pages( sba_dev->ioc[i].res_map, res_size, + set_data_memory_break, 0); +#endif + + if (NULL == sba_dev->ioc[i].res_map) + { + panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__ ); + } + + memset(sba_dev->ioc[i].res_map, 0, res_size); + /* next available IOVP - circular search */ + sba_dev->ioc[i].res_hint = (unsigned long *) + &(sba_dev->ioc[i].res_map[L1_CACHE_BYTES]); + +#ifdef ASSERT_PDIR_SANITY + /* Mark first bit busy - ie no IOVA 0 */ + sba_dev->ioc[i].res_map[0] = 0x80; + sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL; +#endif + +#ifdef CONFIG_DMB_TRAP + iterate_pages( sba_dev->ioc[i].res_map, res_size, + set_data_memory_break, 0); + iterate_pages( sba_dev->ioc[i].pdir_base, sba_dev->ioc[i].pdir_size, + set_data_memory_break, 0); +#endif + + DBG_INIT("sba_common_init() %d res_map %x %p\n", + i, res_size, sba_dev->ioc[i].res_map); + } + + sba_dev->sba_lock = SPIN_LOCK_UNLOCKED; +} + +#ifdef CONFIG_PROC_FS +static int sba_proc_info(char *buf, char **start, off_t offset, int len) +{ + struct sba_device *sba_dev = sba_list; +/* FIXME: Multi-IOC support broken! */ + struct ioc *ioc = &sba_dev->ioc[0]; + int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */ + unsigned long i = 0, avg = 0, min, max; + + sprintf(buf, "%s rev %d.%d\n", + parisc_getHWdescription(sba_dev->iodc->hw_type, + sba_dev->iodc->hversion, sba_dev->iodc->sversion), + (sba_dev->hw_rev & 0x7) + 1, + (sba_dev->hw_rev & 0x18) >> 3 + ); + sprintf(buf, "%sIO PDIR size : %d bytes (%d entries)\n", + buf, + ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits per byte */ + total_pages); /* 8 bits per byte */ + + sprintf(buf, "%sIO PDIR entries : %ld free %ld used (%d%%)\n", buf, + total_pages - ioc->used_pages, ioc->used_pages, + (int) (ioc->used_pages * 100 / total_pages)); + + sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", + buf, ioc->res_size, ioc->res_size << 3); /* 8 bits per byte */ + + min = max = ioc->avg_search[0]; + for (i = 0; i < SBA_SEARCH_SAMPLE; i++) { + avg += ioc->avg_search[i]; + if (ioc->avg_search[i] > max) max = ioc->avg_search[i]; + if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; + } + avg /= SBA_SEARCH_SAMPLE; + sprintf(buf, "%s Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + buf, min, avg, max); + + sprintf(buf, "%spci_map_single(): %8ld calls %8ld pages (avg %d/1000)\n", + buf, ioc->msingle_calls, ioc->msingle_pages, + (int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls)); + + /* KLUGE - unmap_sg calls unmap_single for each mapped page */ + min = ioc->usingle_calls - ioc->usg_calls; + max = ioc->usingle_pages - ioc->usg_pages; + sprintf(buf, "%spci_unmap_single: %8ld calls %8ld pages (avg %d/1000)\n", + buf, min, max, + (int) ((max * 1000)/min)); + + sprintf(buf, "%spci_map_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + buf, ioc->msg_calls, ioc->msg_pages, + (int) ((ioc->msg_pages * 1000)/ioc->msg_calls)); + + sprintf(buf, "%spci_unmap_sg() : %8ld calls %8ld pages (avg %d/1000)\n", + buf, ioc->usg_calls, ioc->usg_pages, + (int) ((ioc->usg_pages * 1000)/ioc->usg_calls)); + + return strlen(buf); +} + +static int +sba_resource_map(char *buf, char **start, off_t offset, int len) +{ + struct sba_device *sba_dev = sba_list; + struct ioc *ioc = &sba_dev->ioc[0]; + unsigned long *res_ptr = (unsigned long *)ioc->res_map; + int i; + + for(i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) { + if ((i & 7) == 0) + strcat(buf,"\n "); + sprintf(buf, "%s %08lx", buf, *res_ptr); + } + strcat(buf, "\n"); + + return strlen(buf); +} +#endif + +/* +** Determine if lba should claim this chip (return 0) or not (return 1). +** If so, initialize the chip and tell other partners in crime they +** have work to do. +*/ +int +sba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +{ + struct sba_device *sba_dev; + u32 func_class; + int i; + + if (IS_ASTRO(d)) { + static char astro_rev[]="Astro ?.?"; + + /* Read HW Rev First */ + func_class = READ_REG32(d->hpa); + + astro_rev[6] = '1' + (char) (func_class & 0x7); + astro_rev[8] = '0' + (char) ((func_class & 0x18) >> 3); + dri->version = astro_rev; + } else { + static char ike_rev[]="Ike rev ?"; + + /* Read HW Rev First */ + func_class = READ_REG32(d->hpa + SBA_FCLASS); + + ike_rev[8] = '0' + (char) (func_class & 0xff); + dri->version = ike_rev; + } + + printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa); + + sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL); + if (NULL == sba_dev) + { + printk(MODULE_NAME " - couldn't alloc sba_device\n"); + return(1); + } + memset(sba_dev, 0, sizeof(struct sba_device)); + for(i=0; iioc[i].res_lock)); + + + sba_dev->hw_rev = func_class; + sba_dev->iodc = d; + sba_dev->sba_hpa = d->hpa; /* faster access */ + + sba_get_pat_resources(sba_dev); + sba_hw_init(sba_dev); + sba_common_init(sba_dev); + + hppa_dma_ops = &sba_ops; + +#ifdef CONFIG_PROC_FS + if (IS_ASTRO(d)) { + create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info); + } else { + create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info); + } + create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map); +#endif + return 0; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/semaphore.c linux/arch/parisc/kernel/semaphore.c --- v2.4.0-test11/linux/arch/parisc/kernel/semaphore.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/semaphore.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,239 @@ +/* + * Just taken from alpha implementation. + * This can't work well, perhaps. + */ +/* + * Generic semaphore code. Buyer beware. Do your own + * specific changes in + */ + +#include +#include + +/* + * Semaphores are implemented using a two-way counter: + * The "count" variable is decremented for each process + * that tries to sleep, while the "waking" variable is + * incremented when the "up()" code goes to wake up waiting + * processes. + * + * Notably, the inline "up()" and "down()" functions can + * efficiently test if they need to do any extra work (up + * needs to do something only if count was negative before + * the increment operation. + * + * waking_non_zero() (from asm/semaphore.h) must execute + * atomically. + * + * When __up() is called, the count was negative before + * incrementing it, and we need to wake up somebody. + * + * This routine adds one to the count of processes that need to + * wake up and exit. ALL waiting processes actually wake up but + * only the one that gets to the "waking" field first will gate + * through and acquire the semaphore. The others will go back + * to sleep. + * + * Note that these functions are only called when there is + * contention on the lock, and as such all this is the + * "non-critical" part of the whole semaphore business. The + * critical part is the inline stuff in + * where we want to avoid any extra jumps and calls. + */ +void __up(struct semaphore *sem) +{ + wake_one_more(sem); + wake_up(&sem->wait); +} + +/* + * Perform the "down" function. Return zero for semaphore acquired, + * return negative for signalled out of the function. + * + * If called from __down, the return is ignored and the wait loop is + * not interruptible. This means that a task waiting on a semaphore + * using "down()" cannot be killed until someone does an "up()" on + * the semaphore. + * + * If called from __down_interruptible, the return value gets checked + * upon return. If the return value is negative then the task continues + * with the negative value in the return register (it can be tested by + * the caller). + * + * Either form may be used in conjunction with "up()". + * + */ + + +#define DOWN_HEAD(task_state) \ + \ + \ + current->state = (task_state); \ + add_wait_queue(&sem->wait, &wait); \ + \ + /* \ + * Ok, we're set up. sem->count is known to be less than zero \ + * so we must wait. \ + * \ + * We can let go the lock for purposes of waiting. \ + * We re-acquire it after awaking so as to protect \ + * all semaphore operations. \ + * \ + * If "up()" is called before we call waking_non_zero() then \ + * we will catch it right away. If it is called later then \ + * we will have to go through a wakeup cycle to catch it. \ + * \ + * Multiple waiters contend for the semaphore lock to see \ + * who gets to gate through and who has to wait some more. \ + */ \ + for (;;) { + +#define DOWN_TAIL(task_state) \ + current->state = (task_state); \ + } \ + current->state = TASK_RUNNING; \ + remove_wait_queue(&sem->wait, &wait); + +void __down(struct semaphore * sem) +{ + DECLARE_WAITQUEUE(wait, current); + + DOWN_HEAD(TASK_UNINTERRUPTIBLE) + if (waking_non_zero(sem)) + break; + schedule(); + DOWN_TAIL(TASK_UNINTERRUPTIBLE) +} + +int __down_interruptible(struct semaphore * sem) +{ + DECLARE_WAITQUEUE(wait, current); + int ret = 0; + + DOWN_HEAD(TASK_INTERRUPTIBLE) + + ret = waking_non_zero_interruptible(sem, current); + if (ret) + { + if (ret == 1) + /* ret != 0 only if we get interrupted -arca */ + ret = 0; + break; + } + schedule(); + DOWN_TAIL(TASK_INTERRUPTIBLE) + return ret; +} + +int __down_trylock(struct semaphore * sem) +{ + return waking_non_zero_trylock(sem); +} + + +/* Wait for the lock to become unbiased. Readers + * are non-exclusive. =) + */ +void down_read_failed(struct rw_semaphore *sem) +{ + DECLARE_WAITQUEUE(wait, current); + + __up_read(sem); /* this takes care of granting the lock */ + + add_wait_queue(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(current, TASK_UNINTERRUPTIBLE); + if (atomic_read(&sem->count) >= 0) + break; + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + current->state = TASK_RUNNING; +} + +void down_read_failed_biased(struct rw_semaphore *sem) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue(&sem->wait, &wait); /* put ourselves at the head of the list */ + + for (;;) { + if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0)) + break; + set_task_state(current, TASK_UNINTERRUPTIBLE); + if (!sem->read_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + current->state = TASK_RUNNING; +} + + +/* Wait for the lock to become unbiased. Since we're + * a writer, we'll make ourselves exclusive. + */ +void down_write_failed(struct rw_semaphore *sem) +{ + DECLARE_WAITQUEUE(wait, current); + + __up_write(sem); /* this takes care of granting the lock */ + + add_wait_queue_exclusive(&sem->wait, &wait); + + while (atomic_read(&sem->count) < 0) { + set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (atomic_read(&sem->count) >= 0) + break; /* we must attempt to aquire or bias the lock */ + schedule(); + } + + remove_wait_queue(&sem->wait, &wait); + current->state = TASK_RUNNING; +} + +void down_write_failed_biased(struct rw_semaphore *sem) +{ + DECLARE_WAITQUEUE(wait, current); + + add_wait_queue_exclusive(&sem->write_bias_wait, &wait); /* put ourselves at the end of the list */ + + for (;;) { + if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) + break; + set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + if (!sem->write_bias_granted) + schedule(); + } + + remove_wait_queue(&sem->write_bias_wait, &wait); + current->state = TASK_RUNNING; + + /* if the lock is currently unbiased, awaken the sleepers + * FIXME: this wakes up the readers early in a bit of a + * stampede -> bad! + */ + if (atomic_read(&sem->count) >= 0) + wake_up(&sem->wait); +} + + +/* Called when someone has done an up that transitioned from + * negative to non-negative, meaning that the lock has been + * granted to whomever owned the bias. + */ +void rwsem_wake_readers(struct rw_semaphore *sem) +{ + if (xchg(&sem->read_bias_granted, 1)) + BUG(); + wake_up(&sem->wait); +} + +void rwsem_wake_writer(struct rw_semaphore *sem) +{ + if (xchg(&sem->write_bias_granted, 1)) + BUG(); + wake_up(&sem->write_bias_wait); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/setup.c linux/arch/parisc/kernel/setup.c --- v2.4.0-test11/linux/arch/parisc/kernel/setup.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/setup.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,614 @@ +/* $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $ + * + * Initial setup-routines for HP 9000 based hardware. + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Modifications for PA-RISC (C) 1999 Helge Deller + * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf) + * Modifications copyright 2000 Martin K. Petersen + * Modifications copyright 2000 Philipp Rumpf + * + * Initial PA-RISC Version: 04-23-1999 by Helge Deller + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#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 /* for register_driver() stuff */ +#include +#include +#include +#include +#include +#include +#include /* for pa7300lc_init() proto */ + +#include /* for struct irq_region */ +#include /* for PA_VIEW PDC_PAT_CPU_GET_NUMBER etc */ + +#include + +#define COMMAND_LINE_SIZE 1024 +char saved_command_line[COMMAND_LINE_SIZE]; + +/* +** KLUGE ALERT! +** +** We *really* should be using a combination of request_resource() +** and request_region()! But request_region() requires kmalloc since +** returns a new struct resource. And kmalloc just isn't available +** until after mem_init() is called from start_kernel(). +** +** FIXME: assume contiguous memory initially. +** Additional chunks of memory might be added to sysram_resource.sibling. +*/ +static struct resource sysrom_resource = { + name: "System ROM", start: 0x0f0000000UL, end: 0x0f00fffffUL, + flags: IORESOURCE_BUSY | IORESOURCE_MEM, + parent: &iomem_resource, sibling: NULL, child: NULL }; + +static struct resource pdcdata_resource; + +static struct resource sysram_resource = { + name: "System RAM", start: 0UL, end: ~0UL /* bogus */, + flags: IORESOURCE_MEM, + parent: &iomem_resource, sibling: &sysrom_resource, child: &pdcdata_resource}; + +extern char _text; /* start of kernel code, defined by linker */ +extern int data_start; +extern char _edata; /* end of data, begin BSS, defined by linker */ +extern char _end; /* end of BSS, defined by linker */ + +static struct resource data_resource = { + name: "kernel Data", start: virt_to_phys(&data_start), end: virt_to_phys(&_end)-1, + flags: IORESOURCE_BUSY | IORESOURCE_MEM, + parent: &sysram_resource, sibling: NULL, child: NULL}; + +static struct resource code_resource = { + name: "Kernel Code", start: virt_to_phys(&_text), end: virt_to_phys(&data_start)-1, + flags: IORESOURCE_BUSY | IORESOURCE_MEM, + parent: &sysram_resource, sibling: &data_resource, child: NULL}; + +static struct resource pdcdata_resource = { + name: "PDC data (Page Zero)", start: 0, end: 0x9ff, + flags: IORESOURCE_BUSY | IORESOURCE_MEM, + parent: &sysram_resource, sibling: &code_resource, child: NULL}; + + + + +struct system_cpuinfo_parisc boot_cpu_data; +struct cpuinfo_parisc cpu_data[NR_CPUS]; + +extern void do_inventory(void); +extern void cache_init(void); +extern struct hp_device * register_module(void *hpa); + +static int cpu_driver_callback(struct hp_device *, struct pa_iodc_driver *); + +static struct pa_iodc_driver cpu_drivers_for[] = { + {HPHW_NPROC, 0x0, 0x0, 0x0, 0, 0, + DRIVER_CHECK_HWTYPE, + "CPU", "PARISC", (void *) cpu_driver_callback}, + {0,0,0,0,0,0, + 0, + (char *) NULL, (char *) NULL, (void *) NULL } +}; + +static long fallback_cpu_hpa[] = { 0xfffa0000L, 0xfffbe000L, 0x0 }; + + +/* +** PARISC CPU driver - claim "device" and initialize CPU data structures. +** +** Consolidate per CPU initialization into (mostly) one module. +** Monarch CPU will initialize boot_cpu_data which shouldn't +** change once the system has booted. +** +** The callback *should* do per-instance initialization of +** everything including the monarch. Some of the code that's +** in setup.c:start_parisc() should migrate here and start_parisc() +** should "register_driver(cpu_driver_for)" before calling +** do_inventory(). +** +** The goal of consolidating CPU initialization into one place is +** to make sure all CPU's get initialized the same way. +** It would be nice if the even the manarch through the exact same code path. +** (up to rendevous at least). +*/ +#undef ASSERT +#define ASSERT(expr) \ + if(!(expr)) { \ + printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \ + panic(#expr); \ + } + +static int +cpu_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri) +{ +#ifdef __LP64__ + extern int pdc_pat; /* arch/parisc/kernel/inventory.c */ + static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0}; +#endif + struct cpuinfo_parisc *p; + +#ifndef CONFIG_SMP + if (boot_cpu_data.cpu_count > 0) { + printk(KERN_INFO "CONFIG_SMP disabled - not claiming addional CPUs\n"); + return(1); + } +#endif + + p = &cpu_data[boot_cpu_data.cpu_count]; + boot_cpu_data.cpu_count++; + +/* TODO: Enable FP regs - done early in start_parisc() now */ + + /* initialize counters */ + memset(p, 0, sizeof(struct cpuinfo_parisc)); + + p->hpa = (unsigned long) d->hpa; /* save CPU hpa */ + +#ifdef __LP64__ + if (pdc_pat) { + ulong status; + pdc_pat_cell_mod_maddr_block_t pa_pdc_cell; + + status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, + d->mod_index, PA_VIEW, & pa_pdc_cell); + + ASSERT(PDC_RET_OK == status); + + /* verify it's the same as what do_pat_inventory() found */ + ASSERT(d->mod_info == pa_pdc_cell.mod_info); + ASSERT(d->pmod_loc == pa_pdc_cell.mod_location); + ASSERT(d->mod_path == pa_pdc_cell.mod_path); + + p->txn_addr = pa_pdc_cell.mod[0]; /* id_eid for IO sapic */ + + /* get the cpu number */ + status = mem_pdc_call( PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER, + __pa(& pdc_result), d->hpa); + + ASSERT(PDC_RET_OK == status); + + p->cpuid = pdc_result[0]; + + } else +#endif + { + p->txn_addr = (unsigned long) d->hpa; /* for normal parisc */ + + /* logical CPU ID and update global counter */ + p->cpuid = boot_cpu_data.cpu_count - 1; + } + + /* + ** itimer and ipi IRQ handlers are statically initialized in + ** arch/parisc/kernel/irq.c + */ + p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)]; + + return(0); +} + + +void __xchg_called_with_bad_pointer(void) +{ + printk(KERN_EMERG "xchg() called with bad pointer !\n"); +} + + +/* Some versions of IODC don't list the CPU, and since we don't walk + * the bus yet, we have to probe for processors at well known hpa + * addresses. + */ + +void __init register_fallback_cpu (void) +{ + struct hp_device *d = NULL; + int i = 0; + +#ifdef CONFIG_SMP +#error "Revisit CPU fallback addresses for SMP (Assuming bus walk hasn't been implemented)" +#endif + printk ("No CPUs reported by firmware - probing...\n"); + + while (fallback_cpu_hpa[i]) { + + d = register_module ((void *) fallback_cpu_hpa[i]); + + if (d > 0) { + printk ("Found CPU at %lx\n", fallback_cpu_hpa[i]); + cpu_driver_callback (d, 0); + return; + } + + i++; + } + + panic ("No CPUs found. System halted.\n"); + return; +} + + +/* + * Get CPU information and store it in the boot_cpu_data structure. */ +void __init collect_boot_cpu_data(void) +{ + memset(&boot_cpu_data,0,sizeof(boot_cpu_data)); + + boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */ + + /* get CPU-Model Information... */ +#define p ((unsigned long *)&boot_cpu_data.pdc.model) + if(pdc_model_info(&boot_cpu_data.pdc.model)==0) + printk("model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); +#undef p + + if(pdc_model_versions(&boot_cpu_data.pdc.versions, 0)==0) + printk("vers %08lx\n", boot_cpu_data.pdc.versions.cpuid); + + if(pdc_model_cpuid(&boot_cpu_data.pdc.cpuid)==0) + printk("cpuid %08lx\n", boot_cpu_data.pdc.cpuid.cpuid); + + printk("CPUID vers %ld rev %ld\n", + (boot_cpu_data.pdc.cpuid.cpuid >> 5) & 127, + boot_cpu_data.pdc.cpuid.cpuid & 31); + + if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name)==0) + printk("model %s\n",boot_cpu_data.pdc.sys_model_name); + + boot_cpu_data.model_name = parisc_getHWdescription(HPHW_NPROC, + boot_cpu_data.pdc.model.hversion>>4, + boot_cpu_data.pdc.model.sversion>>8); + + boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion; + boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion; + + boot_cpu_data.cpu_type = + parisc_get_cpu_type(boot_cpu_data.pdc.model.hversion); + + boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0]; + boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1]; +} + + +#ifdef __LP64__ +#define COMMAND_GLOBAL 0xfffffffffffe0030UL +#else +#define COMMAND_GLOBAL 0xfffe0030 +#endif + +#define CMD_RESET 5 /* reset any module */ + +/* +** The Wright Brothers and Gecko systems have a H/W problem +** (Lasi...'nuf said) may cause a broadcast reset to lockup +** the system. An HVERSION dependent PDC call was developed +** to perform a "safe", platform specific broadcast reset instead +** of kludging up all the code. +** +** Older machines which do not implement PDC_BROADCAST_RESET will +** return (with an error) and the regular broadcast reset can be +** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET +** the PDC call will not return (the system will be reset). +*/ +static int +reset_parisc(struct notifier_block *self, unsigned long command, void *ptr) +{ + printk("%s: %s(cmd=%lu)\n", __FILE__, __FUNCTION__, command); + + switch(command) { + case MACH_RESTART: +#ifdef FASTBOOT_SELFTEST_SUPPORT + /* + ** If user has modified the Firmware Selftest Bitmap, + ** run the tests specified in the bitmap after the + ** system is rebooted w/PDC_DO_RESET. + ** + ** ftc_bitmap = 0x1AUL "Skip destructive memory tests" + ** + ** Using "directed resets" at each processor with the MEM_TOC + ** vector cleared will also avoid running destructive + ** memory self tests. (Not implemented yet) + */ + if (ftc_bitmap) { + mem_pdc_call( PDC_BROADCAST_RESET, + PDC_DO_FIRM_TEST_RESET, PDC_FIRM_TEST_MAGIC, + ftc_bitmap); + } +#endif + + /* "Normal" system reset */ + (void) mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET, + 0L, 0L, 0L); + + /* Nope...box should reset with just CMD_RESET now */ + gsc_writel(CMD_RESET, COMMAND_GLOBAL); + + /* Wait for RESET to lay us to rest. */ + while (1) ; + + break; + } + return NOTIFY_DONE; +} + +static struct notifier_block parisc_block = { reset_parisc, NULL, 0 }; + + +/* start_parisc() will be called from head.S to setup our new memory_start + and actually start our kernel ! + Memory-Layout is: + - Kernel-Image (code+data+BSS) + - Stack (stack-size see below!, stack-setup-code is in head.S) + - memory_start at end of stack.. +*/ + +unsigned long mem_start, mem_max; +unsigned long start_pfn, max_pfn; +extern asmlinkage void __init start_kernel(void); + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) +#define PFN_PHYS(x) ((x) << PAGE_SHIFT) + +void __init start_parisc(unsigned arg0, unsigned arg1, + unsigned arg2, unsigned arg3) +{ + register unsigned long ccr; + unsigned long memory_start; + + /* Clear BSS */ + + { + char *p = &_edata, *q = &_end; + + while (p < q) { + *p++ = 0; + } + } + + + pdc_console_init(); + +#ifdef __LP64__ + printk("The 64-bit Kernel has started...\n"); +#else + printk("The 32-bit Kernel has started...\n"); +#endif + + /* + ** Enable FP coprocessor + ** + ** REVISIT: ccr should be set by PDC_COPROC results to support PA1.0. + ** Hardcoding works for PA1.1 processors. + ** + ** REVISIT: this could be done in the "code 22" trap handler. + ** (frowands idea - that way we know which processes need FP + ** registers saved on the interrupt stack.) + ** + ** NEWS FLASH: wide kernels need FP coprocessor enabled to handle + ** formatted printing of %lx for example (double divides I think) + */ + ccr = 0xc0; + mtctl(ccr, 10); + printk("Enabled FP coprocessor\n"); + +#ifdef __LP64__ + printk( "If this is the LAST MESSAGE YOU SEE, you're probably using\n" + "32-bit millicode by mistake.\n"); +#endif + + memory_start = (unsigned long) &_end; + memory_start = (memory_start + PAGE_SIZE) & PAGE_MASK; + printk("Free memory starts at: 0x%lx\n", memory_start); + + /* Collect stuff passed in from the boot loader */ + printk(KERN_WARNING "%s(0x%x,0x%x,0x%x,0x%x)\n", + __FUNCTION__, arg0, arg1, arg2, arg3); + + /* arg0 is free-mem start, arg1 is ptr to command line */ + if (arg0 < 64) { + /* called from hpux boot loader */ + saved_command_line[0] = '\0'; + } else { + strcpy(saved_command_line, (char *)__va(arg1)); + printk("PALO command line: '%s'\nPALO initrd %x-%x\n", + saved_command_line, arg2, arg3); + +#ifdef CONFIG_BLK_DEV_INITRD + if (arg2 != 0) /* did palo pass us a ramdisk? */ + { + initrd_start = (unsigned long)__va(arg2); + initrd_end = (unsigned long)__va(arg3); + } +#endif + } + + mem_start = __pa(memory_start); +#define MAX_MEM (512*1024*1024) + mem_max = (PAGE0->imm_max_mem > MAX_MEM ? MAX_MEM : PAGE0->imm_max_mem); + + collect_boot_cpu_data(); + + /* initialize the LCD/LED after boot_cpu_data is available ! */ + led_init(); /* LCD/LED initialization */ + + do_inventory(); /* probe for hardware */ + register_driver(cpu_drivers_for); /* claim all the CPUs */ + + if (boot_cpu_data.cpu_count == 0) + register_fallback_cpu(); + + printk("CPU(s): %d x %s at %d.%06d MHz\n", + boot_cpu_data.cpu_count, + boot_cpu_data.cpu_name, + boot_cpu_data.cpu_hz / 1000000, + boot_cpu_data.cpu_hz % 1000000 ); + + switch (boot_cpu_data.cpu_type) { + case pcx: + case pcxs: + case pcxt: + hppa_dma_ops = &pcx_dma_ops; + break; + case pcxl2: + pa7300lc_init(); + case pcxl: /* falls through */ + hppa_dma_ops = &pcxl_dma_ops; + break; + default: + break; + } + +#if 1 + /* KLUGE! this really belongs in kernel/resource.c! */ + iomem_resource.end = ~0UL; +#endif + sysram_resource.end = mem_max - 1; + notifier_chain_register(&mach_notifier, &parisc_block); + start_kernel(); /* now back to arch-generic code... */ +} + +void __init setup_arch(char **cmdline_p) +{ + unsigned long bootmap_size; + unsigned long start_pfn; + unsigned long mem_free; + + *cmdline_p = saved_command_line; + + /* initialize bootmem */ + + start_pfn = PFN_UP(mem_start); + max_pfn = PFN_DOWN(mem_max); + + bootmap_size = init_bootmem(start_pfn, max_pfn); + + mem_start += bootmap_size; + mem_free = mem_max - mem_start; + + /* free_bootmem handles rounding nicely */ + printk("free_bootmem(0x%lx, 0x%lx)\n", (unsigned long)mem_start, + (unsigned long)mem_free); + free_bootmem(mem_start, mem_free); + +#ifdef CONFIG_BLK_DEV_INITRD + printk("initrd: %08x-%08x\n", (int) initrd_start, (int) initrd_end); + + if (initrd_end != 0) { + initrd_below_start_ok = 1; + reserve_bootmem(__pa(initrd_start), initrd_end - initrd_start); + } +#endif + + cache_init(); + + paging_init(); + + if((unsigned long)&init_task_union&(INIT_TASK_SIZE - 1)) { + printk("init_task_union not aligned. Please recompile the kernel after changing the first line in arch/parisc/kernel/init_task.c from \n\"#define PAD 0\" to\n\"#define PAD 1\" or vice versa\n"); + for(;;); + } + + +#ifdef CONFIG_SERIAL_CONSOLE + /* nothing */ +#elif CONFIG_VT +#if defined(CONFIG_STI_CONSOLE) + conswitchp = &dummy_con; /* we use take_over_console() later ! */ +#elif defined(CONFIG_IODC_CONSOLE) + conswitchp = &prom_con; /* it's currently really "prom_con" */ +#elif defined(CONFIG_DUMMY_CONSOLE) + conswitchp = &dummy_con; +#endif +#endif + +} + +#ifdef CONFIG_PROC_FS +/* + * Get CPU information for use by procfs. + */ + +int get_cpuinfo(char *buffer) +{ + char *p = buffer; + int n; + + for(n=0; n + * Copyright (C) 2000 Linuxcare, Inc. + * + * Based on the ia64, i386, and alpha versions. + * + * Like the IA-64, we are a recent enough port (we are *starting* + * with glibc2.2) that we do not need to support the old non-realtime + * Linux signals. Therefore we don't. HP/UX signals will go in + * arch/parisc/hpux/signal.c when we figure out how to do them. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG_SIG 0 + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +extern long sys_wait4 (int, int *, int, struct rusage *); +int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall); + +int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from) +{ + if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t))) + return -EFAULT; + if (from->si_code < 0) + return __copy_to_user(to, from, sizeof(siginfo_t)); + else { + int err; + + /* + * If you change siginfo_t structure, please be sure + * this code is fixed accordingly. It should never + * copy any pad contained in the structure to avoid + * security leaks, but must copy the generic 3 ints + * plus the relevant union member. + */ + err = __put_user(from->si_signo, &to->si_signo); + err |= __put_user(from->si_errno, &to->si_errno); + err |= __put_user((short)from->si_code, &to->si_code); + switch (from->si_code >> 16) { + case __SI_FAULT >> 16: + /* FIXME: should we put the interruption code here? */ + case __SI_POLL >> 16: + err |= __put_user(from->si_addr, &to->si_addr); + break; + case __SI_CHLD >> 16: + err |= __put_user(from->si_utime, &to->si_utime); + err |= __put_user(from->si_stime, &to->si_stime); + err |= __put_user(from->si_status, &to->si_status); + default: + err |= __put_user(from->si_uid, &to->si_uid); + err |= __put_user(from->si_pid, &to->si_pid); + break; + /* case __SI_RT: This is not generated by the kernel as of now. */ + } + return err; + } +} + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +#ifdef __LP64__ +#include "sys32.h" +#endif + +asmlinkage int +sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs) +{ + sigset_t saveset, newset; +#ifdef __LP64__ + /* XXX FIXME -- assumes 32-bit user app! */ + sigset_t32 newset32; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t32)) + return -EINVAL; + + if (copy_from_user(&newset32, (sigset_t32 *)unewset, sizeof(newset32))) + return -EFAULT; + + newset.sig[0] = newset32.sig[0] | ((unsigned long)newset32.sig[1] << 32); +#else + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; +#endif + sigdelsetmask(&newset, ~_BLOCKABLE); + + spin_lock_irq(¤t->sigmask_lock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + regs->gr[28] = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + if (do_signal(&saveset, regs, 1)) + return -EINTR; + } +} + +/* + * Do a signal return - restore sigcontext. + */ + +struct rt_sigframe { + unsigned int tramp[4]; + struct siginfo info; + struct ucontext uc; +}; + +/* Trampoline for calling rt_sigreturn() */ +#define INSN_LDI_R25_0 0x34190000 /* ldi 0,%r25 (in_syscall=0) */ +#define INSN_LDI_R25_1 0x34190002 /* ldi 1,%r25 (in_syscall=1) */ +#define INSN_LDI_R20 0x3414015a /* ldi __NR_rt_sigreturn,%r20 */ +#define INSN_BLE_SR2_R0 0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */ +#define INSN_NOP 0x80000240 /* nop */ +/* For debugging */ +#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */ + +/* + * The 32-bit ABI wants at least 48 bytes for a function call frame: + * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of + * which Linux/parisc uses is sp-20 for the saved return pointer...) + * Then, the stack pointer must be rounded to a cache line (64 bytes). + */ +#define PARISC_RT_SIGFRAME_SIZE \ + (((sizeof(struct rt_sigframe) + 48) + 63) & -64) + +static long +restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs) +{ + long err = 0; + + err |= __copy_from_user(regs->gr, sc->sc_gr, sizeof(regs->gr)); + err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr)); + err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq)); + err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq)); + err |= __get_user(regs->sar, &sc->sc_sar); + +#if DEBUG_SIG + printk("restore_sigcontext: r28 is %ld\n", regs->gr[28]); +#endif + return err; +} + +void +sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) +{ + struct rt_sigframe *frame; + struct siginfo si; + sigset_t set; + unsigned long usp = regs->gr[30]; + + /* Unwind the user stack to get the rt_sigframe structure. */ + frame = (struct rt_sigframe *) + (usp - PARISC_RT_SIGFRAME_SIZE); +#if DEBUG_SIG + printk("in sys_rt_sigreturn, frame is %p\n", frame); +#endif + + /* Verify that it's a good sigcontext before using it */ + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto give_sigsegv; + if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) + goto give_sigsegv; + + sigdelsetmask(&set, ~_BLOCKABLE); + spin_lock_irq(¤t->sigmask_lock); + current->blocked = set; + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + + /* Good thing we saved the old gr[30], eh? */ + if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) + goto give_sigsegv; + +#if DEBUG_SIG + printk("usp: %#08lx stack %p", + usp, &frame->uc.uc_stack); +#endif + + /* I don't know why everyone else assumes they can call this + with a pointer to a stack_t on the kernel stack. That + makes no sense. Anyway we'll do it like m68k, since we + also are using segmentation in the same way as them. */ + if (do_sigaltstack(&frame->uc.uc_stack, NULL, usp) == -EFAULT) + goto give_sigsegv; + + /* If we are on the syscall path IAOQ will not be restored, and + * if we are on the interrupt path we must not corrupt gr31. + */ + if (in_syscall) + regs->gr[31] = regs->iaoq[0]; +#if DEBUG_SIG + printk("returning to %#lx\n", regs->iaoq[0]); + printk("in sys_rt_sigreturn:\n"); + show_regs(regs); +#endif + return; + +give_sigsegv: +#if DEBUG_SIG + printk("fuckup in sys_rt_sigreturn, sending SIGSEGV\n"); +#endif + si.si_signo = SIGSEGV; + si.si_errno = 0; + si.si_code = SI_KERNEL; + si.si_pid = current->pid; + si.si_uid = current->uid; + si.si_addr = &frame->uc; + force_sig_info(SIGSEGV, &si, current); + return; +} + +/* + * Set up a signal frame. + */ + +static inline void * +get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) +{ + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void *) sp; /* Stacks grow up. Fun. */ +} + +static long +setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, int in_syscall) + +{ + unsigned long flags = 0; + long err = 0; + + if (on_sig_stack((unsigned long) sc)) + flags |= PARISC_SC_FLAG_ONSTACK; + if (in_syscall) { + flags |= PARISC_SC_FLAG_IN_SYSCALL; + /* regs->iaoq is undefined in the syscall return path */ + err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]); + err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]); +#if DEBUG_SIG + printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->gr[31], regs->gr[31]); +#endif + } else { + err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq)); + err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq)); +#if DEBUG_SIG + printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->iaoq[0], regs->iaoq[1]); +#endif + } + + err |= __put_user(flags, &sc->sc_flags); + err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr)); + err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr)); + err |= __put_user(regs->sar, &sc->sc_sar); +#if DEBUG_SIG + printk("setup_sigcontext: r28 is %ld\n", regs->gr[28]); +#endif + + return err; +} + +static long +setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs, int in_syscall) +{ + struct rt_sigframe *frame; + unsigned long rp, usp, haddr; + struct siginfo si; + int err = 0; + + usp = regs->gr[30]; + /* access_ok is broken, so do a simplistic "are we stomping on + kernel space" assertion. */ + if (usp > PAGE_OFFSET) { + printk("setup_rt_frame: called on kernel space (usp=%#lx), NOW YOU MUST DIE!!!\n", + usp); + show_regs(regs); + while(1); + } + + frame = get_sigframe(ka, usp, sizeof(*frame)); + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + +#if DEBUG_SIG + printk("setup_rt_frame 1: frame %p info %p\n", frame, info); +#endif + + err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t)); + err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= __put_user(sas_ss_flags(regs->gr[30]), + &frame->uc.uc_stack.ss_flags); + err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + if (err) + goto give_sigsegv; + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0, + &frame->tramp[0]); + err |= __put_user(INSN_LDI_R20, &frame->tramp[1]); + err |= __put_user(INSN_BLE_SR2_R0, &frame->tramp[2]); + err |= __put_user(INSN_NOP, &frame->tramp[3]); + +#if DEBUG_SIG + /* Assert that we're flushing in the correct space... */ + { + int sid; + asm ("mfsp %%sr3,%0" : "=r" (sid)); + printk("flushing 64 bytes at space %#x offset %p\n", + sid, frame->tramp); + } +#endif + +#if CACHE_FLUSHING_IS_NOT_BROKEN + flush_icache_range((unsigned long) &frame->tramp[0], + (unsigned long) &frame->tramp[4]); +#else + /* It should *always* be cache line-aligned, but the compiler + sometimes screws up. */ + asm volatile("fdc 0(%%sr3,%0)\n\t" + "fdc %1(%%sr3,%0)\n\t" + "sync\n\t" + "fic 0(%%sr3,%0)\n\t" + "fic %1(%%sr3,%0)\n\t" + "sync\n\t" + : : "r" (frame->tramp), "r" (L1_CACHE_BYTES)); +#endif + rp = (unsigned long) frame->tramp; + + if (err) + goto give_sigsegv; + +#ifdef __LP64__ +/* Much more has to happen with signals than this -- but it'll at least */ +/* provide a pointer to some places which definitely need a look. */ +#define HACK unsigned int +#else +#define HACK unsigned long +#endif + haddr = (HACK) ka->sa.sa_handler; + /* ARGH! Fucking brain damage. You don't want to know. */ + if (haddr & 2) { + HACK *plabel; + HACK ltp; + + plabel = (HACK *) (haddr & ~3); + err |= __get_user(haddr, plabel); + err |= __get_user(ltp, plabel + 1); + if (err) + goto give_sigsegv; + regs->gr[19] = ltp; + } + + /* The syscall return path will create IAOQ values from r31. + */ + if (in_syscall) + regs->gr[31] = (HACK) haddr; + else { + regs->iaoq[0] = (HACK) haddr | 3; + regs->iaoq[1] = regs->iaoq[0] + 4; + } + + regs->gr[2] = rp; /* userland return pointer */ + regs->gr[26] = sig; /* signal number */ + regs->gr[25] = (HACK) &frame->info; /* siginfo pointer */ + regs->gr[24] = (HACK) &frame->uc; /* ucontext pointer */ +#if DEBUG_SIG + printk("making sigreturn frame: %#lx + %#lx = %#lx\n", + regs->gr[30], PARISC_RT_SIGFRAME_SIZE, + regs->gr[30] + PARISC_RT_SIGFRAME_SIZE); +#endif + /* Raise the user stack pointer to make a proper call frame. */ + regs->gr[30] = ((HACK) frame + PARISC_RT_SIGFRAME_SIZE); + +#if DEBUG_SIG + printk("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n", + current->comm, current->pid, frame, regs->gr[30], + regs->iaoq[0], regs->iaoq[1], rp); +#endif + + return 1; + +give_sigsegv: +#if DEBUG_SIG + printk("fuckup in setup_rt_frame, sending SIGSEGV\n"); +#endif + if (sig == SIGSEGV) + ka->sa.sa_handler = SIG_DFL; + si.si_signo = SIGSEGV; + si.si_errno = 0; + si.si_code = SI_KERNEL; + si.si_pid = current->pid; + si.si_uid = current->uid; + si.si_addr = frame; + force_sig_info(SIGSEGV, &si, current); + return 0; +} + +/* + * OK, we're invoking a handler. + */ + +static long +handle_signal(unsigned long sig, struct k_sigaction *ka, + siginfo_t *info, sigset_t *oldset, + struct pt_regs *regs, int in_syscall) +{ +#if DEBUG_SIG + printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n", + sig, ka, info, oldset, regs); +#endif + /* Set up the stack frame */ + if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) + return 0; + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + if (!(ka->sa.sa_flags & SA_NODEFER)) { + spin_lock_irq(¤t->sigmask_lock); + sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); + sigaddset(¤t->blocked,sig); + recalc_sigpending(current); + spin_unlock_irq(¤t->sigmask_lock); + } + return 1; +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * We need to be able to restore the syscall arguments (r21-r26) to + * restart syscalls. Thus, the syscall path should save them in the + * pt_regs structure (it's okay to do so since they are caller-save + * registers). As noted below, the syscall number gets restored for + * us due to the magic of delayed branching. + */ +asmlinkage int +do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall) +{ + siginfo_t info; + struct k_sigaction *ka; + +#if DEBUG_SIG + printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n", + oldset, regs, regs->sr[7], current->sigpending, in_syscall); +#endif + /* Everyone else checks to see if they are in kernel mode at + this point and exits if that's the case. I'm not sure why + we would be called in that case, but for some reason we + are. */ + + if (!oldset) + oldset = ¤t->blocked; + +#if DEBUG_SIG + printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]); +#endif + + for (;;) { + unsigned long signr; + + spin_lock_irq(¤t->sigmask_lock); + signr = dequeue_signal(¤t->blocked, &info); + spin_unlock_irq(¤t->sigmask_lock); +#if DEBUG_SIG + printk("do_signal: signr=%ld, pid=%d\n", signr, current->pid); +#endif + + if (!signr) + break; + + if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { + /* Let the debugger run. */ + current->exit_code = signr; + set_current_state(TASK_STOPPED); + notify_parent(current, SIGCHLD); + schedule(); + + /* We're back. Did the debugger cancel the sig? */ + if (!(signr = current->exit_code)) + continue; + current->exit_code = 0; + + /* The debugger continued. Ignore SIGSTOP. */ + if (signr == SIGSTOP) + continue; + + /* Update the siginfo structure. Is this good? */ + if (signr != info.si_signo) { + info.si_signo = signr; + info.si_errno = 0; + info.si_code = SI_USER; + info.si_pid = current->p_pptr->pid; + info.si_uid = current->p_pptr->uid; + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, &info, current); + continue; + } + } + + ka = ¤t->sig->action[signr-1]; +#if DEBUG_SIG + printk("sa_handler is %lx\n", ka->sa.sa_handler); +#endif + if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_IGN) { + if (signr != SIGCHLD) + continue; + while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0) + /* nothing */; + continue; + } + + if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_DFL) { + int exit_code = signr; + + /* Init gets no signals it doesn't want. */ + if (current->pid == 1) + continue; + + switch (signr) { + case SIGCONT: case SIGCHLD: case SIGWINCH: + continue; + + case SIGTSTP: case SIGTTIN: case SIGTTOU: + if (is_orphaned_pgrp(current->pgrp)) + continue; + /* FALLTHRU */ + + case SIGSTOP: + set_current_state(TASK_STOPPED); + current->exit_code = signr; + if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP)) + notify_parent(current, SIGCHLD); + schedule(); + continue; + + case SIGQUIT: case SIGILL: case SIGTRAP: + case SIGABRT: case SIGFPE: case SIGSEGV: + case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ: + if (signr == SIGQUIT) /* Userspace debugging */ + show_regs(regs); + if (do_coredump(signr, regs)) + exit_code |= 0x80; + /* FALLTHRU */ + + default: + lock_kernel(); + sigaddset(¤t->pending.signal, signr); + recalc_sigpending(current); + current->flags |= PF_SIGNALED; + do_exit(exit_code); + /* NOTREACHED */ + } + } + + /* Restart a system call if necessary. */ + if (in_syscall) { + /* Check the return code */ + switch (regs->gr[28]) { + case -ERESTARTNOHAND: +#if DEBUG_SIG + printk("ERESTARTNOHAND: returning -EINTR\n"); +#endif + regs->gr[28] = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { +#if DEBUG_SIG + printk("ERESTARTSYS: putting -EINTR\n"); +#endif + regs->gr[28] = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* A syscall is just a branch, so all + we have to do is fiddle the return + pointer. */ + regs->gr[31] -= 8; /* delayed branching */ + /* Preserve original r28. */ + regs->gr[28] = regs->orig_r28; + break; + } + } + /* Whee! Actually deliver the signal. If the + delivery failed, we need to continue to iterate in + this loop so we can deliver the SIGSEGV... */ + if (handle_signal(signr, ka, &info, oldset, regs, in_syscall)) { +#if DEBUG_SIG + printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]); +#endif + return 1; + } + } + + /* Did we come from a system call? */ + if (in_syscall) { + /* Restart the system call - no handlers present */ + if (regs->gr[28] == -ERESTARTNOHAND || + regs->gr[28] == -ERESTARTSYS || + regs->gr[28] == -ERESTARTNOINTR) { + /* Hooray for delayed branching. We don't + have to restore %r20 (the system call + number) because it gets loaded in the delay + slot of the branch external instruction. */ + regs->gr[31] -= 8; + /* Preserve original r28. */ + regs->gr[28] = regs->orig_r28; + } + } +#if DEBUG_SIG + printk("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", regs->gr[28]); +#endif + return 0; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/sys_parisc.c linux/arch/parisc/kernel/sys_parisc.c --- v2.4.0-test11/linux/arch/parisc/kernel/sys_parisc.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/sys_parisc.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,88 @@ +/* + * linux/arch/parisc/kernel/sys_parisc.c + * + * this implements the missing syscalls. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* for some reason, "old_readdir" is the only syscall which does not begin + * with "sys_", which breaks the ENTRY_* macros in syscall.S so I "fixed" + * it here. + */ + +int sys_old_readdir(unsigned int fd, void *dirent, unsigned int count) +{ + return old_readdir(fd, dirent, count); +} + +int sys_pipe(int *fildes) +{ + int fd[2]; + int error; + + lock_kernel(); + error = do_pipe(fd); + unlock_kernel(); + if (!error) { + if (copy_to_user(fildes, fd, 2*sizeof(int))) + error = -EFAULT; + } + return error; +} + +int sys_pause(void) +{ + current->state = TASK_INTERRUPTIBLE; + schedule(); + return -ERESTARTNOHAND; +} + +int sys_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, unsigned long fd, + unsigned long offset) +{ + struct file * file = NULL; + int error; + + down(¤t->mm->mmap_sem); + lock_kernel(); + if (!(flags & MAP_ANONYMOUS)) { + error = -EBADF; + file = fget(fd); + if (!file) + goto out; + } + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + error = do_mmap(file, addr, len, prot, flags, offset); + if (file != NULL) + fput(file); +out: + unlock_kernel(); + up(¤t->mm->mmap_sem); + return error; +} + +int sys_ioperm(unsigned long from, unsigned long num, int on) +{ + return -ENOSYS; +} + +long sys_shmat_wrapper(int shmid, void *shmaddr, int shmflag) +{ + extern int sys_shmat(int shmid, char *shmaddr, int shmflg, + unsigned long * raddr); + unsigned long raddr; + int r; + + r = sys_shmat(shmid, shmaddr, shmflag, &raddr); + if (r < 0) + return r; + return raddr; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/syscall.S linux/arch/parisc/kernel/syscall.S --- v2.4.0-test11/linux/arch/parisc/kernel/syscall.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/syscall.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,563 @@ +/* + * Linux/PARISC Project (http://www.thepuffingroup.com/parisc) + * + * System call entry code Copyright (c) Matthew Wilcox 1999 + * Licensed under the GNU GPL. + * thanks to Philipp Rumpf, Mike Shaver and various others + * sorry about the wall, puffin.. + */ + +#include +#include +#include +#include + +#define __ASSEMBLY__ +#include +#include +#include + +#ifdef __LP64__ + .level 2.0w +#else + .level 1.1 +#endif + .text + + .import syscall_exit,code + .import syscall_exit_rfi,code + .export linux_gateway_page + + /* Linux gateway page is aliased to virtual page 0 in the kernel + * address space. Since it is a gateway page it cannot be + * dereferenced, so null pointers will still fault. We start + * the actual entry point at 0x100. We put break instructions + * at the beginning of the page to trap null indirect function + * pointers. + */ + + .align 4096 +linux_gateway_page: + + break 0,0 + + .align 256 +linux_gateway_entry: + mfsp %sr7,%r1 /* we must set sr3 to the space */ + mtsp %r1,%sr3 /* of the user before the gate */ + gate .+8, %r0 /* become privileged */ + mtsp %r0,%sr4 /* get kernel space into sr4 */ + mtsp %r0,%sr5 /* get kernel space into sr5 */ + mtsp %r0,%sr6 /* get kernel space into sr6 */ + mtsp %r0,%sr7 /* get kernel space into sr7 */ +#ifdef __LP64__ + /* for now we can *always* set the W bit on entry to the syscall + * since we don't support wide userland processes. We could + * also save the current SM other than in r0 and restore it on + * exit from the syscall, and also use that value to know + * whether to do narrow or wide syscalls. -PB + */ + ssm PSW_SM_W, %r0 +#endif + mtctl %r28,%cr27 + rsm PSW_I, %r28 /* no ints for a bit */ + mfctl %cr30,%r1 /* get the kernel task ptr */ + mtctl %r0,%cr30 /* zero it (flag) */ + + /* Save some registers for sigcontext and potential task + switch (see entry.S for the details of which ones are + saved/restored) */ + STREG %r2, TASK_PT_GR2(%r1) /* preserve rp */ + STREG %r19, TASK_PT_GR19(%r1) + STREG %r20, TASK_PT_GR20(%r1) + STREG %r21, TASK_PT_GR21(%r1) + STREG %r22, TASK_PT_GR22(%r1) + STREG %r23, TASK_PT_GR23(%r1) /* 4th argument */ + STREG %r24, TASK_PT_GR24(%r1) /* 3rd argument */ + STREG %r25, TASK_PT_GR25(%r1) /* 2nd argument */ + STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */ + STREG %r27, TASK_PT_GR27(%r1) /* user dp */ + mfctl %cr27,%r19 + STREG %r19, TASK_PT_GR28(%r1) /* return value 0 */ + STREG %r19, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */ + STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */ + STREG %r30, TASK_PT_GR30(%r1) /* preserve userspace sp */ + STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */ + + ldo TASK_PT_FR0(%r1), %r27 /* save fpregs from the kernel */ + save_fp %r27 /* or potential task switch */ + + mfctl %cr11, %r27 /* i.e. SAR */ + STREG %r27, TASK_PT_SAR(%r1) + + loadgp + + ldo TASK_SZ_ALGN+64(%r1),%r30 /* set up kernel stack */ + +#ifndef __LP64__ + /* no need to save these on stack because in wide mode the first 8 + * args are passed in registers */ + stw %r22, -52(%r30) /* 5th argument */ + stw %r21, -56(%r30) /* 6th argument */ +#endif + + /* for some unknown reason, task_struct.ptrace is an unsigned long so use LDREG */ + LDREG TASK_PTRACE(%r1), %r19 /* Are we being ptraced? */ + mtsm %r28 /* irqs back */ + + bb,<,n %r19, 31, .Ltracesys /* must match PT_PTRACE bit */ + + /* Note! We cannot use the syscall table that is mapped + nearby since the gateway page is mapped execute-only. */ + + ldil L%sys_call_table, %r1 + ldo R%sys_call_table(%r1), %r19 + LDIL_FIXUP(%r19) + + comiclr,>>= __NR_Linux_syscalls, %r20, %r0 + b,n .Lsyscall_nosys + +#ifdef __LP64__ + ldd,s %r20(%r19), %r19 +#else + ldwx,s %r20(%r19), %r19 +#endif + /* If this is a sys_rt_sigreturn call, and the signal was received + * when not in_syscall, then we want to return via syscall_exit_rfi, + * not syscall_exit. Signal no. in r20, in_syscall in r25 (see + * trampoline code in signal.c). + */ + ldi __NR_rt_sigreturn,%r2 + comb,= %r2,%r20,.Lrt_sigreturn +.Lin_syscall: + ldil L%syscall_exit,%r2 + LDIL_FIXUP(%r2) + be 0(%sr7,%r19) + ldo R%syscall_exit(%r2),%r2 +.Lrt_sigreturn: + comib,<> 0,%r25,.Lin_syscall + ldil L%syscall_exit_rfi,%r2 + LDIL_FIXUP(%r2) + be 0(%sr7,%r19) + ldo R%syscall_exit_rfi(%r2),%r2 + + /* Note! Because we are not running where we were linked, any + calls to functions external to this file must be indirect. To + be safe, we apply the opposite rule to functions within this + file, with local labels given to them to ensure correctness. */ + +.Lsyscall_nosys: +syscall_nosys: + ldil L%syscall_exit,%r1 + LDIL_FIXUP(%r1) + be R%syscall_exit(%sr7,%r1) + ldo -ENOSYS(%r0),%r28 /* set errno */ + + +/* Warning! This trace code is a virtual duplicate of the code above so be + * sure to maintain both! */ +.Ltracesys: +tracesys: + /* Need to save more registers so the debugger can see where we + * are. + */ + ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + ssm 0,%r2 /* Lower 8 bits only!! */ + STREG %r2,TASK_PT_PSW(%r1) + STREG %r1,TASK_PT_CR30(%r1) + mfsp %sr0,%r2 + STREG %r2,TASK_PT_SR0(%r1) + mfsp %sr1,%r2 + STREG %r2,TASK_PT_SR1(%r1) + mfsp %sr2,%r2 + STREG %r2,TASK_PT_SR2(%r1) + mfsp %sr3,%r2 + STREG %r2,TASK_PT_SR3(%r1) + STREG %r2,TASK_PT_SR4(%r1) + STREG %r2,TASK_PT_SR5(%r1) + STREG %r2,TASK_PT_SR6(%r1) + STREG %r2,TASK_PT_SR7(%r1) + STREG %r2,TASK_PT_IASQ0(%r1) + STREG %r2,TASK_PT_IASQ1(%r1) + LDREG TASK_PT_GR31(%r1),%r2 + STREG %r2,TASK_PT_IAOQ0(%r1) + ldo 4(%r2),%r2 + STREG %r2,TASK_PT_IAOQ1(%r1) + ldo TASK_REGS(%r1),%r2 + /* reg_save %r2 */ + STREG %r3,PT_GR3(%r2) + STREG %r4,PT_GR4(%r2) + STREG %r5,PT_GR5(%r2) + STREG %r6,PT_GR6(%r2) + STREG %r7,PT_GR7(%r2) + STREG %r8,PT_GR8(%r2) + STREG %r9,PT_GR9(%r2) + STREG %r10,PT_GR10(%r2) + STREG %r11,PT_GR11(%r2) + STREG %r12,PT_GR12(%r2) + STREG %r13,PT_GR13(%r2) + STREG %r14,PT_GR14(%r2) + STREG %r15,PT_GR15(%r2) + STREG %r16,PT_GR16(%r2) + STREG %r17,PT_GR17(%r2) + STREG %r18,PT_GR18(%r2) + /* Finished saving things for the debugger */ + + ldil L%syscall_trace,%r1 + LDIL_FIXUP(%r1) + ldil L%tracesys_next,%r2 + LDIL_FIXUP(%r2) + be R%syscall_trace(%sr7,%r1) + ldo R%tracesys_next(%r2),%r2 + +tracesys_next: + ldil L%sys_call_table,%r1 + LDIL_FIXUP(%r1) + ldo R%sys_call_table(%r1), %r19 + + ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + LDREG TASK_PT_GR20(%r1), %r20 + LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */ + LDREG TASK_PT_GR25(%r1), %r25 + LDREG TASK_PT_GR24(%r1), %r24 + LDREG TASK_PT_GR23(%r1), %r23 +#ifdef __LP64__ + LDREG TASK_PT_GR22(%r1), %r22 + LDREG TASK_PT_GR21(%r1), %r21 +#endif + + comiclr,>>= __NR_Linux_syscalls, %r20, %r0 + b,n .Lsyscall_nosys + +#ifdef __LP64__ + ldd,s %r20(%r19), %r19 +#else + ldwx,s %r20(%r19), %r19 +#endif + /* If this is a sys_rt_sigreturn call, and the signal was received + * when not in_syscall, then we want to return via syscall_exit_rfi, + * not syscall_exit. Signal no. in r20, in_syscall in r25 (see + * trampoline code in signal.c). + */ + ldi __NR_rt_sigreturn,%r2 + comb,= %r2,%r20,.Ltrace_rt_sigreturn +.Ltrace_in_syscall: + ldil L%tracesys_exit,%r2 + LDIL_FIXUP(%r2) + be 0(%sr7,%r19) + ldo R%tracesys_exit(%r2),%r2 + + /* Do *not* call this function on the gateway page, because it + makes a direct call to syscall_trace. */ + +tracesys_exit: + ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + bl syscall_trace, %r2 + STREG %r28,TASK_PT_GR28(%r1) /* save return value now */ + ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + LDREG TASK_PT_GR28(%r1), %r28 /* Restore return val. */ + + ldil L%syscall_exit,%r1 + LDIL_FIXUP(%r1) + be,n R%syscall_exit(%sr7,%r1) + +.Ltrace_rt_sigreturn: + comib,<> 0,%r25,.Ltrace_in_syscall + ldil L%tracesys_sigexit,%r2 + LDIL_FIXUP(%r2) + be 0(%sr7,%r19) + ldo R%tracesys_sigexit(%r2),%r2 + +tracesys_sigexit: + ldo -TASK_SZ_ALGN-64(%r30),%r1 /* get task ptr */ + bl syscall_trace, %r2 + nop + + ldil L%syscall_exit_rfi,%r1 + LDIL_FIXUP(%r1) + be,n R%syscall_exit_rfi(%sr7,%r1) + +#ifdef __LP64__ +/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and + * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific + * implementation is required on wide palinux. + */ +#define ENTRY_SAME(_name_) .dword sys_##_name_ +#define ENTRY_DIFF(_name_) .dword sys32_##_name_ +#define ENTRY_UHOH(_name_) .dword sys32_unimplemented +#else +#define ENTRY_SAME(_name_) .word sys_##_name_ +#define ENTRY_DIFF(_name_) .word sys_##_name_ +#define ENTRY_UHOH(_name_) .word sys_##_name_ +#endif + + .align 8 + .export sys_call_table +.Lsys_call_table: +sys_call_table: + ENTRY_SAME(ni_syscall) /* 0 - old "setup()" system call*/ + ENTRY_SAME(exit) + ENTRY_SAME(fork_wrapper) + ENTRY_SAME(read) + ENTRY_SAME(write) + ENTRY_SAME(open) /* 5 */ + ENTRY_SAME(close) + ENTRY_SAME(waitpid) + ENTRY_SAME(creat) + ENTRY_SAME(link) + ENTRY_SAME(unlink) /* 10 */ + ENTRY_DIFF(execve_wrapper) + ENTRY_SAME(chdir) + /* See comments in kernel/time.c!!! Maybe we don't need this? */ + ENTRY_DIFF(time) + ENTRY_SAME(mknod) + ENTRY_SAME(chmod) /* 15 */ + ENTRY_SAME(lchown) + ENTRY_SAME(socket) + /* struct stat is MAYBE identical wide and narrow ?? */ + ENTRY_DIFF(newstat) + ENTRY_SAME(lseek) + ENTRY_SAME(getpid) /* 20 */ + /* the 'void * data' parameter may need re-packing in wide */ + ENTRY_DIFF(mount) + /* concerned about struct sockaddr in wide/narrow */ + /* ---> I think sockaddr is OK unless the compiler packs the struct */ + /* differently to align the char array */ + ENTRY_SAME(bind) + ENTRY_SAME(setuid) + ENTRY_SAME(getuid) + ENTRY_SAME(stime) /* 25 */ + ENTRY_SAME(ptrace) + ENTRY_SAME(alarm) + /* see stat comment */ + ENTRY_DIFF(newfstat) + ENTRY_SAME(pause) + /* struct utimbuf uses time_t which might vary */ + ENTRY_DIFF(utime) /* 30 */ + /* struct sockaddr... */ + ENTRY_SAME(connect) + ENTRY_SAME(listen) + ENTRY_SAME(access) + ENTRY_SAME(nice) + /* struct sockaddr... */ + ENTRY_SAME(accept) /* 35 */ + ENTRY_SAME(sync) + ENTRY_SAME(kill) + ENTRY_SAME(rename) + ENTRY_SAME(mkdir) + ENTRY_SAME(rmdir) /* 40 */ + ENTRY_SAME(dup) + ENTRY_SAME(pipe) + ENTRY_DIFF(times) + /* struct sockaddr... */ + ENTRY_SAME(getsockname) + /* it seems possible brk() could return a >4G pointer... */ + ENTRY_SAME(brk) /* 45 */ + ENTRY_SAME(setgid) + ENTRY_SAME(getgid) + ENTRY_SAME(signal) + ENTRY_SAME(geteuid) + ENTRY_SAME(getegid) /* 50 */ + ENTRY_SAME(acct) + ENTRY_SAME(umount) + /* struct sockaddr... */ + ENTRY_SAME(getpeername) + /* This one's a huge ugly mess */ + ENTRY_DIFF(ioctl) + /* struct flock? */ + ENTRY_DIFF(fcntl) /* 55 */ + ENTRY_SAME(socketpair) + ENTRY_SAME(setpgid) + ENTRY_SAME(send) + ENTRY_SAME(newuname) + ENTRY_SAME(umask) /* 60 */ + ENTRY_SAME(chroot) + ENTRY_SAME(ustat) + ENTRY_SAME(dup2) + ENTRY_SAME(getppid) + ENTRY_SAME(getpgrp) /* 65 */ + ENTRY_SAME(setsid) + ENTRY_SAME(pivot_root) + /* I don't like this */ + ENTRY_UHOH(sgetmask) + ENTRY_UHOH(ssetmask) + ENTRY_SAME(setreuid) /* 70 */ + ENTRY_SAME(setregid) + ENTRY_SAME(mincore) + ENTRY_DIFF(sigpending) + ENTRY_SAME(sethostname) + /* Following 3 have linux-common-code structs containing longs -( */ + ENTRY_DIFF(setrlimit) /* 75 */ + ENTRY_DIFF(getrlimit) + ENTRY_DIFF(getrusage) + /* struct timeval and timezone are maybe?? consistent wide and narrow */ + ENTRY_SAME(gettimeofday) + ENTRY_SAME(settimeofday) + ENTRY_SAME(getgroups) /* 80 */ + ENTRY_SAME(setgroups) + /* struct socketaddr... */ + ENTRY_SAME(sendto) + ENTRY_SAME(symlink) + /* see stat comment */ + ENTRY_DIFF(newlstat) + ENTRY_SAME(readlink) /* 85 */ + /* suspect we'll need some work for narrow shlibs on wide kernel */ + ENTRY_UHOH(uselib) + ENTRY_SAME(swapon) + ENTRY_SAME(reboot) + /* argh! struct dirent contains a long */ + ENTRY_UHOH(old_readdir) + /* I'm not certain about off_t... */ + ENTRY_SAME(mmap) /* 90 */ + ENTRY_SAME(munmap) + ENTRY_SAME(truncate) + ENTRY_SAME(ftruncate) + ENTRY_SAME(fchmod) + ENTRY_SAME(fchown) /* 95 */ + ENTRY_SAME(getpriority) + ENTRY_SAME(setpriority) + ENTRY_SAME(recv) + ENTRY_DIFF(statfs) + ENTRY_DIFF(fstatfs) /* 100 */ + ENTRY_SAME(ni_syscall) + /* don't think hppa glibc even provides an entry pt for this + * so disable for now */ + ENTRY_UHOH(socketcall) + ENTRY_SAME(syslog) + /* even though manpage says struct timeval contains longs, ours has + * time_t and suseconds_t -- both of which are safe wide/narrow */ + ENTRY_SAME(setitimer) + ENTRY_SAME(getitimer) /* 105 */ + ENTRY_SAME(capget) + ENTRY_SAME(capset) + ENTRY_SAME(pread) + ENTRY_SAME(pwrite) + ENTRY_SAME(getcwd) /* 110 */ + ENTRY_SAME(vhangup) + ENTRY_SAME(ni_syscall) + ENTRY_SAME(vfork_wrapper) + /* struct rusage contains longs... */ + ENTRY_DIFF(wait4) + ENTRY_SAME(swapoff) /* 115 */ + /* struct sysinfo contains longs */ + ENTRY_SAME(sysinfo) + ENTRY_SAME(shutdown) + ENTRY_SAME(fsync) + ENTRY_SAME(madvise) + ENTRY_SAME(clone_wrapper) /* 120 */ + ENTRY_SAME(setdomainname) + ENTRY_SAME(sendfile) + /* struct sockaddr... */ + ENTRY_SAME(recvfrom) + /* struct timex contains longs */ + ENTRY_UHOH(adjtimex) + ENTRY_SAME(mprotect) /* 125 */ + /* old_sigset_t forced to 32 bits. Beware glibc sigset_t */ + ENTRY_DIFF(sigprocmask) + ENTRY_SAME(create_module) + /* struct module contains longs, but insmod builds a 64 bit struct + * if running under a 64 bit kernel */ + ENTRY_SAME(init_module) + ENTRY_SAME(delete_module) + /* struct kernel_sym contains a long. Linus never heard of size_t? */ + ENTRY_DIFF(get_kernel_syms) /* 130 */ + ENTRY_SAME(quotactl) + ENTRY_SAME(getpgid) + ENTRY_SAME(fchdir) + /* bdflush(func, addr) where func has least-significant-bit set means + * addr is a pointer to long :-( */ + ENTRY_UHOH(bdflush) + ENTRY_SAME(sysfs) /* 135 */ + ENTRY_SAME(personality) + ENTRY_SAME(ni_syscall) /* for afs_syscall */ + ENTRY_SAME(setfsuid) + ENTRY_SAME(setfsgid) + /* I think this might work */ + ENTRY_SAME(llseek) /* 140 */ + /* struct linux_dirent has longs, like 'unsigned long d_ino' which + * almost definitely should be 'ino_t d_ino' but it's too late now */ + ENTRY_DIFF(getdents) + /* it is POSSIBLE that select will be OK because even though fd_set + * contains longs, the macros and sizes are clever. */ + ENTRY_SAME(select) + ENTRY_SAME(flock) + ENTRY_SAME(msync) + /* struct iovec contains pointers */ + ENTRY_UHOH(readv) /* 145 */ + ENTRY_UHOH(writev) + ENTRY_SAME(getsid) + ENTRY_SAME(fdatasync) + /* struct __sysctl_args is a mess */ + ENTRY_DIFF(sysctl) + ENTRY_SAME(mlock) /* 150 */ + ENTRY_SAME(munlock) + ENTRY_SAME(mlockall) + ENTRY_SAME(munlockall) + /* struct sched_param is ok for now */ + ENTRY_SAME(sched_setparam) + ENTRY_SAME(sched_getparam) /* 155 */ + ENTRY_SAME(sched_setscheduler) + ENTRY_SAME(sched_getscheduler) + ENTRY_SAME(sched_yield) + ENTRY_SAME(sched_get_priority_max) + ENTRY_SAME(sched_get_priority_min) /* 160 */ + /* These 2 would've worked if someone had defined struct timespec + * carefully, like timeval for example (which is about the same). + * Unfortunately it contains a long :-( */ + ENTRY_DIFF(sched_rr_get_interval) + ENTRY_DIFF(nanosleep) + ENTRY_SAME(mremap) + ENTRY_SAME(setresuid) + ENTRY_SAME(getresuid) /* 165 */ + /* might work, but in general signals need a thorough review */ + ENTRY_UHOH(sigaltstack_wrapper) + /* struct passed back to user can contain long symbol values */ + ENTRY_DIFF(query_module) + ENTRY_SAME(poll) + /* structs contain pointers and an in_addr... */ + ENTRY_UHOH(nfsservctl) + ENTRY_SAME(setresgid) /* 170 */ + ENTRY_SAME(getresgid) + ENTRY_SAME(prctl) + /* signals need a careful review */ + ENTRY_SAME(rt_sigreturn_wrapper) + ENTRY_DIFF(rt_sigaction) + ENTRY_DIFF(rt_sigprocmask) /* 175 */ + ENTRY_DIFF(rt_sigpending) + ENTRY_UHOH(rt_sigtimedwait) + ENTRY_UHOH(rt_sigqueueinfo) + ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */ + ENTRY_SAME(chown) /* 180 */ + /* *sockopt() might work... */ + ENTRY_SAME(setsockopt) + ENTRY_SAME(getsockopt) + /* struct msghdr contains pointers... */ + ENTRY_UHOH(sendmsg) + ENTRY_UHOH(recvmsg) + ENTRY_SAME(semop) /* 185 */ + ENTRY_SAME(semget) + /* needs a more careful review */ + ENTRY_UHOH(semctl) + /* struct msgbuf contains a long */ + ENTRY_UHOH(msgsnd) + ENTRY_UHOH(msgrcv) + ENTRY_SAME(msgget) /* 190 */ + /* struct msqid_ds contains pointers */ + ENTRY_UHOH(msgctl) + ENTRY_SAME(shmat_wrapper) + ENTRY_SAME(shmdt) + ENTRY_SAME(shmget) + /***************/ + /* struct shmid_ds contains pointers */ + ENTRY_UHOH(shmctl) /* 195 */ + ENTRY_SAME(ni_syscall) /* streams1 */ + ENTRY_SAME(ni_syscall) /* streams2 */ + +.end + + /* Make sure nothing else is placed on this page */ + + .align 4096 + .export end_linux_gateway_page +end_linux_gateway_page: + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/time.c linux/arch/parisc/kernel/time.c --- v2.4.0-test11/linux/arch/parisc/kernel/time.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/time.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,98 @@ +/* + * linux/arch/arm/kernel/time.c + * + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King + * Copyright (C) 1999 SuSE GmbH, (Philipp Rumpf, prumpf@tux.org) + * + * 1994-07-02 Alan Modra + * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime + * 1998-12-20 Updated NTP code according to technical memorandum Jan '96 + * "A Kernel Model for Precision Timekeeping" by Dave Mills + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +extern rwlock_t xtime_lock; + +static int timer_value; +static int timer_delta; +static struct pdc_tod tod_data __attribute__((aligned(8))); + +void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + int old; + int lost = 0; + int cr16; + + old = timer_value; + + cr16 = mfctl(16); + while((timer_value - cr16) < (timer_delta / 2)) { + timer_value += timer_delta; + lost++; + } + + mtctl(timer_value ,16); + + do_timer(regs); + + led_interrupt_func(); +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + + read_lock_irqsave(&xtime_lock, flags); + tv->tv_sec = xtime.tv_sec; + tv->tv_usec = xtime.tv_usec; + read_unlock_irqrestore(&xtime_lock, flags); + +} + +void do_settimeofday(struct timeval *tv) +{ + write_lock_irq(&xtime_lock); + xtime.tv_sec = tv->tv_sec; + xtime.tv_usec = tv->tv_usec; + write_unlock_irq(&xtime_lock); +} + +void __init time_init(void) +{ + timer_delta = (100 * PAGE0->mem_10msec) / HZ; + + /* make the first timer interrupt go off in one second */ + timer_value = mfctl(16) + (HZ * timer_delta); + mtctl(timer_value, 16); + + + if(pdc_tod_read(&tod_data) == 0) { + xtime.tv_sec = tod_data.tod_sec; + xtime.tv_usec = tod_data.tod_usec; + } else { + printk(KERN_ERR "Error reading tod clock\n"); + xtime.tv_sec = 0; + xtime.tv_usec = 0; + } + +} + diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/kernel/traps.c linux/arch/parisc/kernel/traps.c --- v2.4.0-test11/linux/arch/parisc/kernel/traps.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/kernel/traps.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,895 @@ +/* + * linux/arch/parisc/traps.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1999, 2000 Philipp Rumpf + */ + +/* + * 'Traps.c' handles hardware traps and faults after we have saved some + * state in 'asm.s'. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_KWDB +#include /* for BI2_KGDB_GDB */ +#include /* for __() */ +#include /* for struct save_state */ +#include /* for pt_regs_to_ssp and ssp_to_pt_regs */ +#include /* for I_BRK_INST */ +#endif /* CONFIG_KWDB */ + + +static inline void console_verbose(void) +{ + extern int console_loglevel; + console_loglevel = 15; +} + + +void page_exception(void); + +/* + * These constants are for searching for possible module text + * segments. VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is + * a guess of how much space is likely to be vmalloced. + */ +#define VMALLOC_OFFSET (8*1024*1024) +#define MODULE_RANGE (8*1024*1024) + +int kstack_depth_to_print = 24; + +static void printbinary(unsigned long x, int nbits) +{ + unsigned long mask = 1UL << (nbits - 1); + while (mask != 0) { + printk(mask & x ? "1" : "0"); + mask >>= 1; + } +} + +void show_regs(struct pt_regs *regs) +{ + int i; +#ifdef __LP64__ +#define RFMT " %016lx" +#else +#define RFMT " %08lx" +#endif + + printk("\n"); /* don't want to have that pretty register dump messed up */ + + printk(" YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\nPSW: "); + printbinary(regs->gr[0], 32); + printk("\n"); + + for (i = 0; i < 32; i += 4) { + int j; + printk("r%d-%d\t", i, i + 3); + for (j = 0; j < 4; j++) { + printk(RFMT, i + j == 0 ? 0 : regs->gr[i + j]); + } + printk("\n"); + } + + for (i = 0; i < 8; i += 4) { + int j; + printk("sr%d-%d\t", i, i + 4); + for (j = 0; j < 4; j++) { + printk(RFMT, regs->sr[i + j]); + } + printk("\n"); + } + +#if REDICULOUSLY_VERBOSE + for (i = 0; i < 32; i++) { + printk("FR%2d : %016lx ", i, regs->fr[i]); + if ((i & 1) == 1) + printk("\n"); + } +#endif + + printk("\nIASQ:" RFMT RFMT " IAOQ:" RFMT RFMT "\n", + regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]); + printk(" IIR: %08lx ISR:" RFMT " IOR:" RFMT "\nORIG_R28:" RFMT + "\n", regs->iir, regs->isr, regs->ior, regs->orig_r28); +} + +void +die_if_kernel (char *str, struct pt_regs *regs, long err) +{ + if (user_mode(regs)) { +#if 1 + if (err == 0) + return; /* STFU */ + + /* XXX for debugging only */ + printk ("!!die_if_kernel: %s(%d): %s %ld\n", + current->comm, current->pid, str, err); + show_regs(regs); +#endif + return; + } + + printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err); + + show_regs(regs); + + /* Wot's wrong wif bein' racy? */ + if (current->thread.flags & PARISC_KERNEL_DEATH) { + printk("die_if_kernel recursion detected.\n"); + sti(); + while (1); + } + current->thread.flags |= PARISC_KERNEL_DEATH; + do_exit(SIGSEGV); +} + +asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code) +{ +} + +asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) +{ +} + +#ifndef CONFIG_MATH_EMULATION + +asmlinkage void math_emulate(long arg) +{ +} + +#endif /* CONFIG_MATH_EMULATION */ + +int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs) +{ + return syscall(regs); +} + +struct { + int retval; + + int (*func) (void *, struct pt_regs *); + void * data; +} ipi_action[NR_CPUS]; + +void ipi_interrupt(int irq, void *unused, struct pt_regs *regs) +{ + int cpu = smp_processor_id(); + + if(!ipi_action[cpu].func) + BUG(); + + ipi_action[cpu].retval = + ipi_action[cpu].func(ipi_action[cpu].data, regs); +} + +/* gdb uses break 4,8 */ +#define GDB_BREAK_INSN 0x10004 +void handle_gdb_break(struct pt_regs *regs, int wot) +{ + struct siginfo si; + + si.si_code = wot; + si.si_addr = (void *) (regs->iaoq[0] & ~3); + si.si_signo = SIGTRAP; + si.si_errno = 0; + force_sig_info(SIGTRAP, &si, current); +} + +void handle_break(unsigned iir, struct pt_regs *regs) +{ + struct siginfo si; +#ifdef CONFIG_KWDB + struct save_state ssp; +#endif /* CONFIG_KWDB */ + + flush_all_caches(); + switch(iir) { + case 0x00: + /* show registers, halt */ + cli(); + printk("break 0,0: pid=%d command='%s'\n", + current->pid, current->comm); + die_if_kernel("Breakpoint", regs, 0); + show_regs(regs); + si.si_code = TRAP_BRKPT; + si.si_addr = (void *) (regs->iaoq[0] & ~3); + si.si_signo = SIGTRAP; + force_sig_info(SIGTRAP, &si, current); + break; + + case GDB_BREAK_INSN: + die_if_kernel("Breakpoint", regs, 0); + handle_gdb_break(regs, TRAP_BRKPT); + break; + +#ifdef CONFIG_KWDB + + case KGDB_BREAK_INSN: + mtctl(0, 15); + pt_regs_to_ssp(regs, &ssp); + kgdb_trap(I_BRK_INST, &ssp, 1); + ssp_to_pt_regs(&ssp, regs); + break; + + case KGDB_INIT_BREAK_INSN: + mtctl(0, 15); + pt_regs_to_ssp(regs, &ssp); + kgdb_trap(I_BRK_INST, &ssp, 1); + ssp_to_pt_regs(&ssp, regs); + + /* Advance pcoq to skip break */ + regs->iaoq[0] = regs->iaoq[1]; + regs->iaoq[1] += 4; + break; + +#endif /* CONFIG_KWDB */ + + default: + set_eiem(0); + printk("break %#08x: pid=%d command='%s'\n", + iir, current->pid, current->comm); + show_regs(regs); + si.si_signo = SIGTRAP; + si.si_code = TRAP_BRKPT; + si.si_addr = (void *) (regs->iaoq[0] & ~3); + force_sig_info(SIGTRAP, &si, current); + return; + } +} + +/* Format of the floating-point exception registers. */ +struct exc_reg { + unsigned int exception : 6; + unsigned int ei : 26; +}; + +/* Macros for grabbing bits of the instruction format from the 'ei' + field above. */ +/* Major opcode 0c and 0e */ +#define FP0CE_UID(i) (((i) >> 6) & 3) +#define FP0CE_CLASS(i) (((i) >> 9) & 3) +#define FP0CE_SUBOP(i) (((i) >> 13) & 7) +#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */ +#define FP0C_FORMAT(i) (((i) >> 11) & 3) +#define FP0E_FORMAT(i) (((i) >> 11) & 1) + +/* Major opcode 0c, uid 2 (performance monitoring) */ +#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f) + +/* Major opcode 2e (fused operations). */ +#define FP2E_SUBOP(i) (((i) >> 5) & 1) +#define FP2E_FORMAT(i) (((i) >> 11) & 1) + +/* Major opcode 26 (FMPYSUB) */ +/* Major opcode 06 (FMPYADD) */ +#define FPx6_FORMAT(i) ((i) & 0x1f) + +/* Flags and enable bits of the status word. */ +#define FPSW_FLAGS(w) ((w) >> 27) +#define FPSW_ENABLE(w) ((w) & 0x1f) +#define FPSW_V (1<<4) +#define FPSW_Z (1<<3) +#define FPSW_O (1<<2) +#define FPSW_U (1<<1) +#define FPSW_I (1<<0) + +/* Emulate a floating point instruction if necessary and possible + (this will be moved elsewhere eventually). Return zero if + successful or if emulation was not required, -1 if the instruction + is actually illegal or unimplemented. The status word passed as + the first parameter will be modified to signal exceptions, if + any. */ + +/* FIXME!!! This is really incomplete and, at the moment, most + illegal FP instructions will simply act as no-ops. Obviously that + is *not* what we want. Also we don't even try to handle exception + types other than the 'unimplemented' ones. */ +int +fp_emul_insn(u32 *sw, struct exc_reg exc, struct pt_regs *regs) +{ + switch (exc.exception) { + case 0x3: /* Unimplemented, opcode 06 */ + break; + case 0x9: /* Unimplemented, opcode 0c */ + /* We do not support quadword operations, end of + story. There's no support for them in GCC. */ + if (FP0C_FORMAT(exc.ei) == 3) + return -1; /* SIGILL */ + /* Fall through. */ + case 0xa: /* Unimplemented, opcode 0e */ + if (FP0CE_CLASS(exc.ei) == 1) { + /* FCNV instructions of various sorts. */ + } else { + if (FP0CE_CLASS(exc.ei == 0) + && FP0CE_SUBOP(exc.ei == 5)) { + /* FRND instructions should be + emulated, at some point, I + guess. */ + return -1; /* SIGILL */ + } + } + break; + case 0x23: /* Unimplemented, opcode 26 */ + break; + case 0x2b: /* Unimplemented, opcode 2e */ + break; + case 0x1: /* Unimplemented, opcode 0e/0c */ + /* FIXME: How the hell are we supposed to tell which + opcode it is? */ + break; + default: + return -1; /* Punt */ + } + + return 0; +} + +/* Handle a floating point exception. Return zero if the faulting + instruction can be completed successfully. */ +int +handle_fpe(struct pt_regs *regs) +{ + struct siginfo si; + union { + struct fpsw { + /* flag bits */ + unsigned int fv : 1; + unsigned int fz : 1; + unsigned int fo : 1; + unsigned int fu : 1; + unsigned int fi : 1; + + unsigned int c : 1; + unsigned int pad1 : 4; + unsigned int cq : 11; + unsigned int rm : 2; + unsigned int pad2 : 2; + unsigned int t : 1; + unsigned int d : 1; + + /* enable bits */ + unsigned int ev : 1; + unsigned int ez : 1; + unsigned int eo : 1; + unsigned int eu : 1; + unsigned int ei : 1; + } status; + u32 word; + } sw; + struct exc_reg excepts[7]; + unsigned int code = 0; + unsigned int throw; + + /* Status word = FR0L. */ + memcpy(&sw, regs->fr, sizeof(sw)); + /* Exception words = FR0R-FR3R. */ + memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts)); + + /* This is all CPU dependent. Since there is no public + documentation on the PA2.0 processors we will just assume + everything is like the 7100/7100LC/7300LC for now. + + Specifically: All exceptions are marked as "unimplemented" + in the exception word, and the only exception word used is + excepts[1]. */ + + /* Try to emulate the instruction. Also determine if it is + really an illegal instruction in the process. + + FIXME: fp_emul_insn() only checks for the "unimplemented" + exceptions at the moment. So this may break horribly on + PA2.0, where we may want to also check to see if we should + just send SIGFPE (or maybe not, let's see the documentation + first...) */ + if (fp_emul_insn(&sw.word, excepts[1], regs) == -1) + goto send_sigill; + + /* Take the intersection of the flag bits in the FPSW and the + enable bits in the FPSW. */ + throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word); + + /* Concoct an appropriate si_code. Of course we don't know + what to do if multiple exceptions were enabled and multiple + flags were set. Maybe that's why HP/UX doesn't implement + feenableexcept(). */ + + if (throw == 0) + goto success; /* Duh. */ + else if (throw & FPSW_V) + code = FPE_FLTINV; + else if (throw & FPSW_Z) + code = FPE_FLTDIV; + else if (throw & FPSW_O) + code = FPE_FLTOVF; + else if (throw & FPSW_U) + code = FPE_FLTUND; + else if (throw & FPSW_I) + code = FPE_FLTRES; + +#if 1 /* Debugging... */ + printk("Unemulated floating point exception, pid=%d (%s)\n", + current->pid, current->comm); + show_regs(regs); + { + int i; + printk("FP Status: %08x\n", sw.word); + printk("FP Exceptions:\n"); + for (i = 0; i < 7; i++) { + printk("\tExcept%d: exception %03x insn %06x\n", + i, excepts[i].exception, excepts[i].ei); + } + } +#endif + + /* FIXME: Should we clear the flag bits, T bit, and exception + registers here? */ + + si.si_signo = SIGFPE; + si.si_errno = 0; + si.si_code = code; + si.si_addr = (void *) regs->iaoq[0]; + force_sig_info(SIGFPE, &si, current); + return -1; + + send_sigill: + si.si_signo = SIGILL; + si.si_errno = 0; + si.si_code = ILL_COPROC; + si.si_addr = (void *) regs->iaoq[0]; + force_sig_info(SIGILL, &si, current); + return -1; + + success: + /* We absolutely have to clear the T bit and exception + registers to allow the process to recover. Otherwise every + subsequent floating point instruction will trap. */ + sw.status.t = 0; + memset(excepts, 0, sizeof(excepts)); + + memcpy(regs->fr, &sw, sizeof(sw)); + memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts)); + return 0; +} + +int handle_toc(void) +{ + return 0; +} + +void default_trap(int code, struct pt_regs *regs) +{ + printk("Trap %d on CPU %d\n", code, smp_processor_id()); + + show_regs(regs); +} + +void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; + + +#ifdef CONFIG_KWDB +int +debug_call (void) { + printk ("Debug call.\n"); + return 0; +} + +int +debug_call_leaf (void) { + return 0; +} +#endif /* CONFIG_KWDB */ + +extern void do_page_fault(struct pt_regs *, int, unsigned long); +extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long); +extern void transfer_pim_to_trap_frame(struct pt_regs *); +extern void pdc_console_restart(void); + +void handle_interruption(int code, struct pt_regs *regs) +{ + unsigned long fault_address = 0; + unsigned long fault_space = 0; + struct siginfo si; +#ifdef CONFIG_KWDB + struct save_state ssp; +#endif /* CONFIG_KWDB */ + + if (code == 1) + pdc_console_restart(); /* switch back to pdc if HPMC */ + else + sti(); + +#ifdef __LP64__ + + /* + * FIXME: + * For 32 bit processes we don't want the b bits (bits 0 & 1) + * in the ior. This is more appropriately handled in the tlb + * miss handlers. Changes need to be made to support addresses + * >32 bits for 64 bit processes. + */ + + regs->ior &= 0x3FFFFFFFFFFFFFFFUL; +#endif + +#if 0 + printk("interrupted with code %d, regs %p\n", code, regs); + show_regs(regs); +#endif + + switch(code) { + case 1: + parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0); + /* NOT REACHED */ + case 3: /* Recovery counter trap */ + regs->gr[0] &= ~PSW_R; + if (regs->iasq[0]) + handle_gdb_break(regs, TRAP_TRACE); + /* else this must be the start of a syscall - just let it + * run. + */ + return; + + case 5: + flush_all_caches(); + cpu_lpmc(5, regs); + return; + + case 6: + fault_address = regs->iaoq[0]; + fault_space = regs->iasq[0]; + break; + + case 9: /* Break Instruction */ + handle_break(regs->iir,regs); + return; + + case 14: + /* Assist Exception Trap, i.e. floating point exception. */ + die_if_kernel("Floating point exception", regs, 0); /* quiet */ + handle_fpe(regs); + return; + case 15: + case 16: /* Non-Access TLB miss faulting address is in IOR */ + case 17: + case 26: + fault_address = regs->ior; + fault_space = regs->isr; + + if (code == 26 && fault_space == 0) + parisc_terminate("Data access rights fault in kernel",regs,code,fault_address); + break; + + case 19: + regs->gr[0] |= PSW_X; /* So we can single-step over the trap */ + /* fall thru */ + case 21: + handle_gdb_break(regs, TRAP_HWBKPT); + return; + + case 25: /* Taken branch trap */ + regs->gr[0] &= ~PSW_T; + if (regs->iasq[0]) + handle_gdb_break(regs, TRAP_BRANCH); + /* else this must be the start of a syscall - just let it + * run. + */ + return; + +#if 0 /* def CONFIG_KWDB */ + case I_TAKEN_BR: /* 25 */ + mtctl(0, 15); + pt_regs_to_ssp(regs, &ssp); + kgdb_trap(I_TAKEN_BR, &ssp, 1); + ssp_to_pt_regs(&ssp, regs); + break; +#endif /* CONFIG_KWDB */ + + case 8: + die_if_kernel("Illegal instruction", regs, code); + si.si_code = ILL_ILLOPC; + goto give_sigill; + + case 10: + die_if_kernel("Priviledged operation - shouldn't happen!", regs, code); + si.si_code = ILL_PRVOPC; + goto give_sigill; + case 11: + die_if_kernel("Priviledged register - shouldn't happen!", regs, code); + si.si_code = ILL_PRVREG; + give_sigill: + si.si_signo = SIGILL; + si.si_errno = 0; + si.si_addr = (void *) regs->iaoq[0]; + force_sig_info(SIGILL, &si, current); + return; + + case 28: /* Unaligned just causes SIGBUS for now */ + die_if_kernel("Unaligned data reference", regs, code); + si.si_code = BUS_ADRALN; + si.si_signo = SIGBUS; + si.si_errno = 0; + si.si_addr = (void *) regs->ior; + force_sig_info(SIGBUS, &si, current); + return; + + default: + if (user_mode(regs)) { + printk("\nhandle_interruption() pid=%d command='%s'\n", + current->pid, current->comm); + show_regs(regs); + /* SIGBUS, for lack of a better one. */ + si.si_signo = SIGBUS; + si.si_code = BUS_OBJERR; + si.si_errno = 0; + si.si_addr = (void *) regs->ior; + force_sig_info(SIGBUS, &si, current); + return; + } + parisc_terminate("Unexpected Interruption!",regs,code,0); + /* NOT REACHED */ + } + + if (user_mode(regs)) { + if (fault_space != regs->sr[7]) { + if (fault_space == 0) + printk("User Fault on Kernel Space "); + else /* this case should never happen, but whatever... */ + printk("User Fault (long pointer) "); + printk("pid=%d command='%s'\n", current->pid, current->comm); + show_regs(regs); + si.si_signo = SIGSEGV; + si.si_errno = 0; + si.si_code = SEGV_MAPERR; + si.si_addr = (void *) regs->ior; + force_sig_info(SIGSEGV, &si, current); + return; + } + } + else { + + /* + * The kernel should never fault on its own address space. + */ + + if (fault_space == 0) + parisc_terminate("Kernel Fault",regs,code,fault_address); + } + +#ifdef CONFIG_KWDB + debug_call_leaf (); +#endif /* CONFIG_KWDB */ + + do_page_fault(regs, code, fault_address); + + /* + * This should not be necessary. + * However, we do not currently + * implement flush_page_to_ram. + * + * The problem is that if we just + * brought in some code through the + * D-cache, the I-cache may not see + * it since it hasn't been flushed + * to ram. + */ + +/* flush_all_caches(); */ + +#if 0 + printk("returning %p\n", regs); +/* show_regs(regs); */ +#endif + + return; + +} + +void show_stack(unsigned long sp) +{ +#if 1 + if ((sp & 0xc0000000UL) == 0xc0000000UL) { + + __u32 *stackptr; + __u32 *dumpptr; + + /* Stack Dump! */ + + stackptr = (__u32 *)sp; + dumpptr = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1)); + printk("\nDumping Stack from %p to %p:\n",dumpptr,stackptr); + while (dumpptr < stackptr) { + printk("%04x %08x %08x %08x %08x %08x %08x %08x %08x\n", + ((__u32)dumpptr) & 0xffff, + dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3], + dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]); + dumpptr += 8; + } + } +#endif +} + + +void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset) +{ + set_eiem(0); + cli(); + + if (code == 1) + transfer_pim_to_trap_frame(regs); + +#if 1 + show_stack(regs->gr[30]); +#endif + + printk("\n%s: Code=%d regs=%p (Addr=%08lx)\n",msg,code,regs,offset); + show_regs(regs); + + for(;;) + ; +} + +void transfer_pim_to_trap_frame(struct pt_regs *regs) +{ + register int i; + extern unsigned int hpmc_pim_data[]; + struct pdc_hpmc_pim_11 *pim_narrow; + struct pdc_hpmc_pim_20 *pim_wide; + + if (boot_cpu_data.cpu_type >= pcxu) { + + pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data; + + /* + * Note: The following code will probably generate a + * bunch of truncation error warnings from the compiler. + * Could be handled with an ifdef, but perhaps there + * is a better way. + */ + + regs->gr[0] = pim_wide->cr[22]; + + for (i = 1; i < 32; i++) + regs->gr[i] = pim_wide->gr[i]; + + for (i = 0; i < 32; i++) + regs->fr[i] = pim_wide->fr[i]; + + for (i = 0; i < 8; i++) + regs->sr[i] = pim_wide->sr[i]; + + regs->iasq[0] = pim_wide->cr[17]; + regs->iasq[1] = pim_wide->iasq_back; + regs->iaoq[0] = pim_wide->cr[18]; + regs->iaoq[1] = pim_wide->iaoq_back; + + regs->cr30 = pim_wide->cr[30]; + regs->sar = pim_wide->cr[11]; + regs->iir = pim_wide->cr[19]; + regs->isr = pim_wide->cr[20]; + regs->ior = pim_wide->cr[21]; + } + else { + pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data; + + regs->gr[0] = pim_narrow->cr[22]; + + for (i = 1; i < 32; i++) + regs->gr[i] = pim_narrow->gr[i]; + + for (i = 0; i < 32; i++) + regs->fr[i] = pim_narrow->fr[i]; + + for (i = 0; i < 8; i++) + regs->sr[i] = pim_narrow->sr[i]; + + regs->iasq[0] = pim_narrow->cr[17]; + regs->iasq[1] = pim_narrow->iasq_back; + regs->iaoq[0] = pim_narrow->cr[18]; + regs->iaoq[1] = pim_narrow->iaoq_back; + + regs->cr30 = pim_narrow->cr[30]; + regs->sar = pim_narrow->cr[11]; + regs->iir = pim_narrow->cr[19]; + regs->isr = pim_narrow->cr[20]; + regs->ior = pim_narrow->cr[21]; + } + + /* + * The following fields only have meaning if we came through + * another path. So just zero them here. + */ + + regs->ksp = 0; + regs->kpc = 0; + regs->orig_r28 = 0; +} + +int __init check_ivt(void *iva) +{ + int i; + u32 check = 0; + u32 *ivap; + u32 *hpmcp; + u32 length; + extern void os_hpmc(void); + extern void os_hpmc_end(void); + + if(strcmp((char *)iva, "cows can fly")) + return -1; + + ivap = (u32 *)iva; + + for (i = 0; i < 8; i++) + *ivap++ = 0; + + /* Compute Checksum for HPMC handler */ + + length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc); + ivap[7] = length; + + hpmcp = (u32 *)os_hpmc; + + for(i=0; i= pcxu) + iva = (void *) &fault_vector_20; + else +#ifdef __LP64__ + panic("Can't boot 64-bit OS on PA1.1 processor!"); +#else + iva = (void *) &fault_vector_11; +#endif + + if(check_ivt(iva)) + panic("IVT invalid"); + + mtctl(0, 30); + mtctl(90000000, 16); + set_eiem(-1L); + mtctl(-1L, 23); + asm volatile ("rsm 0,%0" : "=r" (eiem)); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/lib/Makefile linux/arch/parisc/lib/Makefile --- v2.4.0-test11/linux/arch/parisc/lib/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/lib/Makefile Tue Dec 5 12:29:39 2000 @@ -0,0 +1,13 @@ +# +# Makefile for parisc-specific library files.. +# + + +L_TARGET = lib.a +L_OBJS = lusercopy.o bitops.o checksum.o + + +.S.o: + $(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/lib/bitops.c linux/arch/parisc/lib/bitops.c --- v2.4.0-test11/linux/arch/parisc/lib/bitops.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/lib/bitops.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,60 @@ +/* atomic.c: atomic operations which got too long to be inlined all over + * the place. + * + * Copyright 1999 Philipp Rumpf (prumpf@tux.org */ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_SMP +spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { + [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED +}; +#endif + +spinlock_t __atomic_lock = SPIN_LOCK_UNLOCKED; + +#ifndef __LP64__ +unsigned long __xchg(unsigned long x, unsigned long *ptr, int size) +{ + unsigned long temp, flags; + + if (size != sizeof x) { + printk("__xchg called with bad pointer\n"); + } + spin_lock_irqsave(&__atomic_lock, flags); + temp = *ptr; + *ptr = x; + spin_unlock_irqrestore(&__atomic_lock, flags); + return temp; +} +#else +unsigned long __xchg(unsigned long x, unsigned long *ptr, int size) +{ + unsigned long temp, flags; + unsigned int *ptr32; + + if (size == 8) { +try_long: + spin_lock_irqsave(&__atomic_lock, flags); + temp = *ptr; + *ptr = x; + spin_unlock_irqrestore(&__atomic_lock, flags); + return temp; + } + if (size == 4) { + ptr32 = (unsigned int *)ptr; + spin_lock_irqsave(&__atomic_lock, flags); + temp = (unsigned long)*ptr32; + *ptr32 = (unsigned int)x; + spin_unlock_irqrestore(&__atomic_lock, flags); + return temp; + } + + printk("__xchg called with bad pointer\n"); + goto try_long; +} +#endif diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/lib/checksum.c linux/arch/parisc/lib/checksum.c --- v2.4.0-test11/linux/arch/parisc/lib/checksum.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/lib/checksum.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,130 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * MIPS specific IP/TCP/UDP checksumming routines + * + * Authors: Ralf Baechle, + * Lots of code moved from tcp.c and ip.c; see those files + * for more names. + * + * 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. + * + * $Id: checksum.c,v 1.3 1997/12/01 17:57:34 ralf Exp $ + */ +#include +#include +#include +#include +#include + +static inline unsigned short from32to16(unsigned int x) +{ + /* 32 bits --> 16 bits + carry */ + x = (x & 0xffff) + (x >> 16); + /* 16 bits + carry --> 16 bits including carry */ + x = (x & 0xffff) + (x >> 16); + return (unsigned short)x; +} + +static inline unsigned int do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned int result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = be16_to_cpu(*buff); + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned int carry = 0; + do { + unsigned int w = *(unsigned int *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += le16_to_cpu(*buff); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + +/* + * computes a partial checksum, e.g. for TCP/UDP fragments + */ +unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) +{ + unsigned int result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += sum; + if(sum > result) + result += 1; + return result; +} + +/* + * copy while checksumming, otherwise like csum_partial + */ +unsigned int csum_partial_copy(const char *src, char *dst, + int len, unsigned int sum) +{ + /* + * It's 2:30 am and I don't feel like doing it real ... + * This is lots slower than the real thing (tm) + */ + sum = csum_partial(src, len, sum); + memcpy(dst, src, len); + + return sum; +} + +/* + * Copy from userspace and compute checksum. If we catch an exception + * then zero the rest of the buffer. + */ +unsigned int csum_partial_copy_from_user (const char *src, char *dst, + int len, unsigned int sum, + int *err_ptr) +{ + int missing; + + missing = copy_from_user(dst, src, len); + if (missing) { + memset(dst + len - missing, 0, missing); + *err_ptr = -EFAULT; + } + + return csum_partial(dst, len, sum); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/lib/lusercopy.S linux/arch/parisc/lib/lusercopy.S --- v2.4.0-test11/linux/arch/parisc/lib/lusercopy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/lib/lusercopy.S Tue Dec 5 12:29:39 2000 @@ -0,0 +1,242 @@ +/*------------------------------------------------------------------------------ + * Native PARISC/Linux Project (http://www.puffingroup.com/parisc) + * + * Assembly Language User Access Routines + * Copyright (C) 2000 Hewlett-Packard (John Marvin) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * These routines still have plenty of room for optimization + * (word & doubleword load/store, dual issue, store hints, etc.). + */ + +/* + * The following routines assume that space register 3 (sr3) contains + * the space id associated with the current users address space. + */ + + + .level 1.1 + .text + +#include +#include + + /* + * get_sr gets the appropriate space value into + * sr1 for kernel/user space access, depending + * on the flag stored in the task structure. + */ + + /* FIXME! depi below has hardcoded idea of kernel stack size */ + + .macro get_sr + copy %r30,%r1 ;! Get task structure + depi 0,31,14,%r1 ;! into r1 + ldw TASK_SEGMENT(%r1),%r22 + mfsp %sr3,%r1 + or,<> %r22,%r0,%r0 + copy %r0,%r1 + mtsp %r1,%sr1 + .endm + + /* + * unsigned long + * lcopy_to_user(void *to, const void *from, unsigned long n) + * + * Returns 0 for success. + * otherwise, returns number of bytes not transferred. + */ + + .export lcopy_to_user,code +lcopy_to_user: + .proc + .callinfo NO_CALLS + .entry + comib,=,n 0,%r24,$lctu_done + get_sr +$lctu_loop: + ldbs,ma 1(%r25),%r1 + addib,<> -1,%r24,$lctu_loop +1: stbs,ma %r1,1(%sr1,%r26) +$lctu_done: + bv %r0(%r2) + copy %r24,%r28 + .exit + +2: b $lctu_done + ldo 1(%r24),%r24 + + .section __ex_table,"a" + .word 1b,(2b-1b) + .previous + + .procend + + /* + * unsigned long + * lcopy_from_user(void *to, const void *from, unsigned long n) + * + * Returns 0 for success. + * otherwise, returns number of bytes not transferred. + * + * NOTE: This routine will also zero any bytes in the + * destination that were not copied due to a fault. + * + */ + + .export lcopy_from_user,code +lcopy_from_user: + .proc + .callinfo NO_CALLS + .entry + comib,=,n 0,%r24,$lcfu_done + get_sr +$lcfu_loop: +1: ldbs,ma 1(%sr1,%r25),%r1 + addib,<> -1,%r24,$lcfu_loop + stbs,ma %r1,1(%r26) +$lcfu_done: + bv %r0(%r2) + copy %r24,%r28 + .exit + +2: copy %r24,%r23 +$lcfu_zero_loop: + addib,<> -1,%r23,$lcfu_zero_loop + stbs,ma %r0,1(%r26) + b $lcfu_done + nop + + .section __ex_table,"a" + .word 1b,(2b-1b) + .previous + + .procend + + /* + * long lstrncpy_from_user(char *dst, const char *src, long n) + * + * Returns -EFAULT if exception before terminator, + * N if the entire buffer filled, + * otherwise strlen + 1 (i.e. includes zero byte) + */ + + .export lstrncpy_from_user,code +lstrncpy_from_user: + .proc + .callinfo NO_CALLS + .entry + comib,= 0,%r24,$lsfu_done + copy %r26,%r23 + get_sr +1: ldbs,ma 1(%sr1,%r25),%r1 +$lsfu_loop: + stbs,ma %r1,1(%r26) + comib,=,n 0,%r1,$lsfu_done + addib,<>,n -1,%r24,$lsfu_loop +2: ldbs,ma 1(%sr1,%r25),%r1 +$lsfu_done: + sub %r26,%r23,%r28 +$lsfu_exit: + bv %r0(%r2) + nop + .exit + +3: b $lsfu_exit + ldi -EFAULT,%r28 + + .section __ex_table,"a" + .word 1b,(3b-1b) + .word 2b,(2b-1b) + .previous + + .procend + + /* + * unsigned long lclear_user(void *to, unsigned long n) + * + * Returns 0 for success. + * otherwise, returns number of bytes not transferred. + */ + + .export lclear_user,code +lclear_user: + .proc + .callinfo NO_CALLS + .entry + comib,=,n 0,%r25,$lclu_done + get_sr +$lclu_loop: + addib,<> -1,%r25,$lclu_loop +1: stbs,ma %r0,1(%sr1,%r26) + +$lclu_done: + bv %r0(%r2) + copy %r25,%r28 + .exit + +2: b $lclu_done + ldo 1(%r25),%r25 + + .section __ex_table,"a" + .word 1b,(2b-1b) + .previous + + .procend + + /* + * long lstrnlen_user(char *s, long n) + * + * Returns 0 if exception before zero byte or reaching N, + * N+1 if N would be exceeded, + * else strlen + 1 (i.e. includes zero byte). + */ + + .export lstrnlen_user,code +lstrnlen_user: + .proc + .callinfo NO_CALLS + .entry + comib,= 0,%r25,$lslen_nzero + copy %r26,%r24 + get_sr +1: ldbs,ma 1(%sr1,%r26),%r1 +$lslen_loop: + comib,=,n 0,%r1,$lslen_done + addib,<> -1,%r25,$lslen_loop +2: ldbs,ma 1(%sr1,%r26),%r1 +$lslen_done: + bv %r0(%r2) + sub %r26,%r24,%r28 + .exit + +$lslen_nzero: + b $lslen_done + ldo 1(%r26),%r26 /* special case for N == 0 */ + +3: b $lslen_done + copy %r24,%r26 /* reset r26 so 0 is returned on fault */ + + .section __ex_table,"a" + .word 1b,(3b-1b) + .word 2b,(2b-1b) + .previous + + .procend + + .end diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/Makefile linux/arch/parisc/mm/Makefile --- v2.4.0-test11/linux/arch/parisc/mm/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/Makefile Tue Dec 5 12:29:39 2000 @@ -0,0 +1,13 @@ +# +# Makefile for the linux parisc-specific parts of the memory manager. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := mm.o +O_OBJS := init.o fault.o kmap.o extable.o + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/extable.c linux/arch/parisc/mm/extable.c --- v2.4.0-test11/linux/arch/parisc/mm/extable.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/extable.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,69 @@ +/* + * Kernel exception handling table support. Derived from arch/i386/mm/extable.c. + * + * Copyright (C) 2000 Hewlett-Packard Co + * Copyright (C) 2000 John Marvin (jsm@fc.hp.com) + */ + +#include +#include +#include +#include +#include + + +extern const struct exception_table_entry __start___ex_table[]; +extern const struct exception_table_entry __stop___ex_table[]; + +static inline const struct exception_table_entry * +search_one_table (const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long addr) +{ + /* Abort early if the search value is out of range. */ + + if ((addr < first->addr) || (addr > last->addr)) + return 0; + + while (first <= last) { + const struct exception_table_entry *mid; + long diff; + + mid = first + ((last - first)/2); + diff = mid->addr - addr; + + if (diff == 0) + return mid; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + + return 0; +} + +const struct exception_table_entry * +search_exception_table (unsigned long addr) +{ +#ifndef CONFIG_MODULE + /* There is only the kernel to search. */ + return search_one_table(__start___ex_table, + __stop___ex_table - 1, + addr); +#else + struct exception_table_entry *ret; + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + + for (mp = module_list; mp ; mp = mp->next) { + if (!mp->ex_table_start) + continue; + ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, + addr); + if (ret) + return ret; + } + return 0; +#endif +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/fault.c linux/arch/parisc/mm/fault.c --- v2.4.0-test11/linux/arch/parisc/mm/fault.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/fault.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,283 @@ +/* $Id: fault.c,v 1.5 2000/01/26 16:20:29 jsm Exp $ + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * + * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle + * Copyright 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org) + * Copyright 1999 Hewlett Packard Co. + * + */ + +#include +#include +#include +#include + +#include + + +/* Defines for parisc_acctyp() */ +#define READ 0 +#define WRITE 1 + +/* Various important other fields */ +#define bit22set(x) (x & 0x00000200) +#define bits23_25set(x) (x & 0x000001c0) +#define isGraphicsFlushRead(x) ((x & 0xfc003fdf) == 0x04001a80) + /* extended opcode is 0x6a */ + +#define BITSSET 0x1c0 /* for identifying LDCW */ + +/* + * parisc_acctyp(unsigned int inst) -- + * Given a PA-RISC memory access instruction, determine if the + * the instruction would perform a memory read or memory write + * operation. + * + * This function assumes that the given instruction is a memory access + * instruction (i.e. you should really only call it if you know that + * the instruction has generated some sort of a memory access fault). + * + * Returns: + * VM_READ if read operation + * VM_WRITE if write operation + * VM_EXEC if execute operation + */ +static unsigned long +parisc_acctyp(unsigned long code, unsigned int inst) +{ + if (code == 6 || code == 16) + return VM_EXEC; + + switch (inst & 0xf0000000) { + case 0x40000000: /* load */ + case 0x50000000: /* new load */ + return VM_READ; + + case 0x60000000: /* store */ + case 0x70000000: /* new store */ + return VM_WRITE; + + case 0x20000000: /* coproc */ + case 0x30000000: /* coproc2 */ + if (bit22set(inst)) + return VM_WRITE; + + case 0x0: /* indexed/memory management */ + if (bit22set(inst)) { + /* + * Check for the 'Graphics Flush Read' instruction. + * It resembles an FDC instruction, except for bits + * 20 and 21. Any combination other than zero will + * utilize the block mover functionality on some + * older PA-RISC platforms. The case where a block + * move is performed from VM to graphics IO space + * should be treated as a READ. + * + * The significance of bits 20,21 in the FDC + * instruction is: + * + * 00 Flush data cache (normal instruction behavior) + * 01 Graphics flush write (IO space -> VM) + * 10 Graphics flush read (VM -> IO space) + * 11 Graphics flush read/write (VM <-> IO space) + */ + if (isGraphicsFlushRead(inst)) + return VM_READ; + return VM_WRITE; + } else { + /* + * Check for LDCWX and LDCWS (semaphore instructions). + * If bits 23 through 25 are all 1's it is one of + * the above two instructions and is a write. + * + * Note: With the limited bits we are looking at, + * this will also catch PROBEW and PROBEWI. However, + * these should never get in here because they don't + * generate exceptions of the type: + * Data TLB miss fault/data page fault + * Data memory protection trap + */ + if (bits23_25set(inst) == BITSSET) + return VM_WRITE; + } + return VM_READ; /* Default */ + } + return VM_READ; /* Default */ +} + +#undef bit22set +#undef bits23_25set +#undef isGraphicsFlushRead +#undef BITSSET + +/* This is similar to expand_stack(), except that it is for stacks + * that grow upwards. + */ + +static inline int expand_stackup(struct vm_area_struct * vma, unsigned long address) +{ + unsigned long grow; + + address += 4 + PAGE_SIZE - 1; + address &= PAGE_MASK; + grow = (address - vma->vm_end) >> PAGE_SHIFT; + if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur || + ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur) + return -ENOMEM; + vma->vm_end = address; + vma->vm_mm->total_vm += grow; + if (vma->vm_flags & VM_LOCKED) + vma->vm_mm->locked_vm += grow; + return 0; +} + + +/* This is similar to find_vma(), except that it understands that stacks + * grow up rather than down. + * XXX Optimise by making use of cache and avl tree as per find_vma(). + */ + +struct vm_area_struct * pa_find_vma(struct mm_struct * mm, unsigned long addr) +{ + struct vm_area_struct *vma = NULL; + + if (mm) { + vma = mm->mmap; + if (!vma || addr < vma->vm_start) + return NULL; + while (vma->vm_next && addr >= vma->vm_next->vm_start) + vma = vma->vm_next; + } + return vma; +} + + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long); + +void do_page_fault(struct pt_regs *regs, unsigned long code, + unsigned long address) +{ + struct vm_area_struct * vma; + struct task_struct *tsk = current; + struct mm_struct *mm = tsk->mm; + const struct exception_table_entry *fix; + unsigned long acc_type; + + if (in_interrupt() || !mm) + goto no_context; + + down(&mm->mmap_sem); + vma = pa_find_vma(mm, address); + if (!vma) + goto bad_area; + if (address < vma->vm_end) + goto good_area; + if (!(vma->vm_flags & VM_GROWSUP) || expand_stackup(vma, address)) + goto bad_area; +/* + * Ok, we have a good vm_area for this memory access. We still need to + * check the access permissions. + */ + +good_area: + + acc_type = parisc_acctyp(code,regs->iir); + + if ((vma->vm_flags & acc_type) != acc_type) + goto bad_area; + + /* + * If for any reason at all we couldn't handle the fault, make + * sure we exit gracefully rather than endlessly redo the + * fault. + */ + + switch (handle_mm_fault(mm, vma, address, (acc_type & VM_WRITE) != 0)) { + case 1: + ++current->min_flt; + break; + case 2: + ++current->maj_flt; + break; + case 0: + /* + * We ran out of memory, or some other thing happened + * to us that made us unable to handle the page fault + * gracefully. + */ + goto bad_area; + default: + goto out_of_memory; + } + up(&mm->mmap_sem); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + */ +bad_area: + up(&mm->mmap_sem); + + if (user_mode(regs)) { + struct siginfo si; + + printk("\ndo_page_fault() pid=%d command='%s'\n", + tsk->pid, tsk->comm); + show_regs(regs); + /* FIXME: actually we need to get the signo and code correct */ + si.si_signo = SIGSEGV; + si.si_errno = 0; + si.si_code = SEGV_MAPERR; + si.si_addr = (void *) address; + force_sig_info(SIGSEGV, &si, current); + return; + } + +no_context: + + if (!user_mode(regs)) { + + fix = search_exception_table(regs->iaoq[0]); + + if (fix) { + + if (fix->skip & 1) + regs->gr[8] = -EFAULT; + if (fix->skip & 2) + regs->gr[9] = 0; + + regs->iaoq[0] += ((fix->skip) & ~3); + + /* + * NOTE: In some cases the faulting instruction + * may be in the delay slot of a branch. We + * don't want to take the branch, so we don't + * increment iaoq[1], instead we set it to be + * iaoq[0]+4, and clear the B bit in the PSW + */ + + regs->iaoq[1] = regs->iaoq[0] + 4; + regs->gr[0] &= ~PSW_B; /* IPSW in gr[0] */ + + return; + } + } + + parisc_terminate("Bad Address (null pointer deref?)",regs,code,address); + + out_of_memory: + up(&mm->mmap_sem); + printk("VM: killing process %s\n", current->comm); + if (user_mode(regs)) + do_exit(SIGKILL); + goto no_context; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/init.c linux/arch/parisc/mm/init.c --- v2.4.0-test11/linux/arch/parisc/mm/init.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/init.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,479 @@ +/* + * linux/arch/parisc/mm/init.c + * + * Copyright (C) 1995 Linus Torvalds + * Copyright 1999 SuSE GmbH + * changed by Philipp Rumpf + * Copyright 1999 Philipp Rumpf (prumpf@tux.org) + * + */ + +#include + +#include +#include +#include +#include +#include /* for hppa_dma_ops and pcxl_dma_ops */ +#include +#include + +#include + +static unsigned long totalram_pages; +extern unsigned long max_pfn, mem_max; + +void free_initmem(void) { +} + +/* + * Just an arbitrary offset to serve as a "hole" between mapping areas + * (between top of physical memory and a potential pcxl dma mapping + * area, and below the vmalloc mapping area). + * + * The current 32K value just means that there will be a 32K "hole" + * between mapping areas. That means that any out-of-bounds memory + * accesses will hopefully be caught. The vmalloc() routines leaves + * a hole of 4kB between each vmalloced area for the same reason. + */ + +#define VM_MAP_OFFSET (32*1024) +#define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \ + & ~(VM_MAP_OFFSET-1))) + +void *vmalloc_start; +unsigned long pcxl_dma_start; + +void __init mem_init(void) +{ + max_mapnr = num_physpages = max_low_pfn; + high_memory = __va(max_low_pfn * PAGE_SIZE); + + totalram_pages += free_all_bootmem(); + printk("Memory: %luk available\n", totalram_pages << (PAGE_SHIFT-10)); + + if (hppa_dma_ops == &pcxl_dma_ops) { + pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory); + vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE); + } + else { + pcxl_dma_start = 0; + vmalloc_start = SET_MAP_OFFSET(high_memory); + } +} + +void __bad_pgd(pgd_t *pgd) +{ + printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd)); + pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); +} + +void __bad_pmd(pmd_t *pmd) +{ + printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd)); + pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); +} + +pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset) +{ + pte_t *pte; + + pte = (pte_t *) __get_free_page(GFP_KERNEL); + + if (pmd_none(*pmd)) { + if (pte) { + clear_page(pte); + pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte); + return pte + offset; + } + pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE); + return NULL; + } + + free_page((unsigned long)pte); + + if (pmd_bad(*pmd)) { + __bad_pmd(pmd); + return NULL; + } + + return (pte_t *) pmd_page(*pmd) + offset; +} + +int do_check_pgt_cache(int low, int high) +{ + return 0; +} + +/* + * BAD_PAGE is the page that is used for page faults when linux + * is out-of-memory. Older versions of linux just did a + * do_exit(), but using this instead means there is less risk + * for a process dying in kernel mode, possibly leaving an inode + * unused etc.. + * + * BAD_PAGETABLE is the accompanying page-table: it is initialized + * to point to BAD_PAGE entries. + * + * ZERO_PAGE is a special page that is used for zero-initialized + * data and COW. + */ +pte_t * __bad_pagetable(void) +{ + return (pte_t *) NULL; +} + +unsigned long *empty_zero_page; +unsigned long *empty_bad_page; + +pte_t __bad_page(void) +{ + return *(pte_t *)NULL; +} + +void show_mem(void) +{ + int i,free = 0,total = 0,reserved = 0; + int shared = 0, cached = 0; + + printk("Mem-info:\n"); + show_free_areas(); + printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); + i = max_mapnr; + while (i-- > 0) { + total++; + if (PageReserved(mem_map+i)) + reserved++; + else if (PageSwapCache(mem_map+i)) + cached++; + else if (!atomic_read(&mem_map[i].count)) + free++; + else + shared += atomic_read(&mem_map[i].count) - 1; + } + printk("%d pages of RAM\n",total); + printk("%d reserved pages\n",reserved); + printk("%d pages shared\n",shared); + printk("%d pages swap cached\n",cached); + show_buffers(); +} + +void set_pte_phys (unsigned long vaddr, unsigned long phys) +{ +} + + +/* + * pagetable_init() sets up the page tables + * + * Note that gateway_init() places the Linux gateway page at page 0. + * Since gateway pages cannot be dereferenced this has the desirable + * side effect of trapping those pesky NULL-reference errors in the + * kernel. + */ +static void __init pagetable_init(void) +{ + pgd_t *pg_dir; + pmd_t *pmd; + pte_t *pg_table; + unsigned long tmp1; + unsigned long tmp2; + unsigned long address; + unsigned long ro_start; + unsigned long ro_end; + unsigned long fv_addr; + extern const int stext; + extern int data_start; + extern const unsigned long fault_vector_20; + + ro_start = __pa((unsigned long)&stext); + ro_end = __pa((unsigned long)&data_start); + fv_addr = __pa((unsigned long)&fault_vector_20) & PAGE_MASK; + + printk("pagetable_init\n"); + + /* Map whole memory from PAGE_OFFSET */ + pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS; + + address = 0; + while (address < mem_max) { + /* XXX: BTLB should be done here */ + +#if PTRS_PER_PMD == 1 + pmd = (pmd_t *)__pa(pg_dir); +#else + pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir)); + + /* + * pmd is physical at this point + */ + + if (!pmd) { + pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE); + pmd = (pmd_t *) __pa(pmd); + } + + pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd; +#endif + pg_dir++; + + /* now change pmd to kernel virtual addresses */ + + pmd = (pmd_t *) __va(pmd); + for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) { + + /* + * pg_table is physical at this point + */ + + pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd)); + if (!pg_table) { + pg_table = (pte_t *) + alloc_bootmem_low_pages(PAGE_SIZE); + pg_table = (pte_t *) __pa(pg_table); + } + + pmd_val(*pmd) = _PAGE_TABLE | + (unsigned long) pg_table; + + /* now change pg_table to kernel virtual addresses */ + + pg_table = (pte_t *) __va(pg_table); + for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) { + pte_t pte; + +#if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE) +#warning STI console should explicitly allocate executable pages but does not +/* KWDB needs to write kernel text when setting break points. +** +** The right thing to do seems like KWDB modify only the pte which +** has a break point on it...otherwise we might mask worse bugs. +*/ + if (address >= ro_start && address < ro_end + && address != fv_addr) + pte = __mk_pte(address, PAGE_KERNEL_RO); + else +#endif + pte = __mk_pte(address, PAGE_KERNEL); + + if (address >= mem_max) + pte_val(pte) = 0; + + set_pte(pg_table, pte); + + address += PAGE_SIZE; + } + + if (address >= mem_max) + break; + } + } + + empty_zero_page = alloc_bootmem_pages(PAGE_SIZE); + memset(empty_zero_page, 0, PAGE_SIZE); +} + +unsigned long gateway_pgd_offset; +unsigned long gateway_pgd_entry; + +static void __init gateway_init(void) +{ + unsigned long hpux_gateway_page_addr; + unsigned long linux_gateway_page_addr; + pgd_t *pg_dir; + pmd_t *pmd_base; + pmd_t *pmd; + pte_t *pg_table_base; + pte_t *pg_table; + /* FIXME: These are 'const' in order to trick the compiler + into not treating them as DP-relative data. */ + extern void * const hpux_gateway_page; + extern void * const linux_gateway_page; + pte_t pte; + + hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK; + linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK; + + gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT; + + /* + * Setup Linux Gateway page. + * + * The Linux gateway page will reside in kernel space (on virtual + * page 0), so it doesn't need to be aliased into user space. + */ + + pg_dir = (pgd_t *)swapper_pg_dir; + +#if PTRS_PER_PMD == 1 + pmd_base = (pmd_t *)pg_dir; + pmd = pmd_base + + ((linux_gateway_page_addr) >> PGDIR_SHIFT); + +#else + pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE); + pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) = + _PAGE_TABLE | __pa(pmd_base); + + pmd = pmd_base + + ((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >> + PMD_SHIFT); +#endif + + pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); + + pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base); + + pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY); + + pg_table = pg_table_base + + ((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >> + PAGE_SHIFT); + + set_pte(pg_table,pte); + + /* + * Setup HP-UX gateway page. + * This page will be aliased into each user address space. + */ + + pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); + + pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY); + pg_table = pg_table_base + + ((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >> + PAGE_SHIFT); + + set_pte(pg_table,pte); + + +#if PTRS_PER_PMD == 1 + pmd_base = (pmd_t *)pg_table_base; +#else + pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE); + pmd = pmd_base + + ((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >> + PMD_SHIFT); + pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base); +#endif + + gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base); + + /* + * We will be aliasing the HP-UX gateway page into all HP-UX + * user spaces at the same address (not counting the space register + * value) that will be equivalently mapped as long as space register + * hashing is disabled. It will be a problem if anyone touches + * the gateway pages at its "kernel" address, since that is + * NOT equivalently mapped. We'll flush the caches at this + * point, just in case some code has touched those addresses + * previous to this, but all bets are off if they get touched + * after this point. + */ + + flush_all_caches(); + + return; +} + +void __init paging_init(void) +{ + pagetable_init(); + gateway_init(); + + { + unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, }; + + free_area_init(zones_size); + } +} + +#define NR_SPACE_IDS 8192 + +static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))]; +static unsigned long space_id_index; +static unsigned long free_space_ids = NR_SPACE_IDS; + +/* + * XXX: We should probably unfold the set_bit / test_bit / clear_bit + * locking out of these two functions and have a single spinlock on the + * space_id data structures. + * + * Don't bother. This is all going to be significantly changed in the + * very near future. + */ + +#define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32) + +unsigned long alloc_sid(void) +{ + unsigned long index; + + if (free_space_ids == 0) + BUG(); + + free_space_ids--; + + do { + index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index); + } while(test_and_set_bit(index, space_id)); + + space_id_index = index; + + return index << SPACEID_SHIFT; +} + +void free_sid(unsigned long spaceid) +{ + unsigned long index = spaceid >> SPACEID_SHIFT; + if (index < 0) + BUG(); + + clear_bit(index, space_id); + + if (space_id_index > index) { + space_id_index = index; + } + free_space_ids++; +} + +#ifdef CONFIG_BLK_DEV_INITRD +void free_initrd_mem(unsigned long start, unsigned long end) +{ +#if 0 + for (; start < end; start += PAGE_SIZE) { + ClearPageReserved(mem_map + MAP_NR(start)); + set_page_count(mem_map+MAP_NR(start), 1); + free_page(start); + totalram_pages++; + } + printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); +#endif +} +#endif + +void si_meminfo(struct sysinfo *val) +{ + int i; + + i = max_mapnr; + val->totalram = totalram_pages; + val->sharedram = 0; + val->freeram = nr_free_pages(); + val->bufferram = atomic_read(&buffermem_pages); +#if 0 + while (i-- > 0) { + if (PageReserved(mem_map+i)) + continue; + val->totalram++; + if (!atomic_read(&mem_map[i].count)) + continue; + val->sharedram += atomic_read(&mem_map[i].count) - 1; + } + val->totalram <<= PAGE_SHIFT; + val->sharedram <<= PAGE_SHIFT; +#endif + val->totalhigh = 0; + val->freehigh = 0; + return; +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/kmap.c linux/arch/parisc/mm/kmap.c --- v2.4.0-test11/linux/arch/parisc/mm/kmap.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/kmap.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,143 @@ +/* +** Stolen mostly from arch/parisc/kernel/pci-dma.c +*/ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include /* get_order */ + +#undef flush_cache_all +#define flush_cache_all flush_all_caches + +typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg); + +#if 0 +/* XXX This routine could be used with iterate_page() to replace + * unmap_uncached_page() and save a little code space but I didn't + * do that since I'm not certain whether this is the right path. -PB + */ +static void unmap_cached_pte(pte_t * pte, unsigned long arg) +{ + pte_t page = *pte; + pte_clear(pte); + if (!pte_none(page)) { + if (pte_present(page)) { + unsigned long map_nr = pte_pagenr(page); + if (map_nr < max_mapnr) + __free_page(mem_map + map_nr); + } else { + printk(KERN_CRIT + "Whee.. Swapped out page in kernel page table\n"); + } + } +} +#endif + +/* These two routines should probably check a few things... */ +static void set_uncached(pte_t * pte, unsigned long arg) +{ + pte_val(*pte) |= _PAGE_NO_CACHE; +} + +static void set_cached(pte_t * pte, unsigned long arg) +{ + pte_val(*pte) &= ~_PAGE_NO_CACHE; +} + +static inline void iterate_pte(pmd_t * pmd, unsigned long address, + unsigned long size, pte_iterator_t op, + unsigned long arg) +{ + pte_t *pte; + unsigned long end; + + if (pmd_none(*pmd)) + return; + if (pmd_bad(*pmd)) { + pmd_ERROR(*pmd); + pmd_clear(pmd); + return; + } + pte = pte_offset(pmd, address); + address &= ~PMD_MASK; + end = address + size; + if (end > PMD_SIZE) + end = PMD_SIZE; + do { + op(pte, arg); + address += PAGE_SIZE; + pte++; + } while (address < end); +} + +static inline void iterate_pmd(pgd_t * dir, unsigned long address, + unsigned long size, pte_iterator_t op, + unsigned long arg) +{ + pmd_t *pmd; + unsigned long end; + + if (pgd_none(*dir)) + return; + if (pgd_bad(*dir)) { + pgd_ERROR(*dir); + pgd_clear(dir); + return; + } + pmd = pmd_offset(dir, address); + address &= ~PGDIR_MASK; + end = address + size; + if (end > PGDIR_SIZE) + end = PGDIR_SIZE; + do { + iterate_pte(pmd, address, end - address, op, arg); + address = (address + PMD_SIZE) & PMD_MASK; + pmd++; + } while (address < end); +} + +static void iterate_pages(unsigned long address, unsigned long size, + pte_iterator_t op, unsigned long arg) +{ + pgd_t *dir; + unsigned long end = address + size; + + dir = pgd_offset_k(address); + flush_cache_all(); + do { + iterate_pmd(dir, address, end - address, op, arg); + address = (address + PGDIR_SIZE) & PGDIR_MASK; + dir++; + } while (address && (address < end)); + flush_tlb_all(); +} + +void +kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what) +{ + switch (what) { + case IOMAP_FULL_CACHING: + iterate_pages(vaddr, size, set_cached, 0); + flush_tlb_range(&init_mm, vaddr, size); + break; + case IOMAP_NOCACHE_SER: + iterate_pages(vaddr, size, set_uncached, 0); + flush_tlb_range(&init_mm, vaddr, size); + break; + default: + printk(KERN_CRIT + "kernel_set_cachemode mode %d not understood\n", + what); + break; + } +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/pa11.c linux/arch/parisc/mm/pa11.c --- v2.4.0-test11/linux/arch/parisc/mm/pa11.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/pa11.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,170 @@ +/* $Id: pa11.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $ + * + * pa11.c: PA 1.1 specific mmu/cache code. + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +extern unsigned long mips_tlb_entries; + +/* page functions */ +void pa11_clear_page(unsigned long page) +{ +} + +static void pa11_copy_page(unsigned long to, unsigned long from) +{ +} + +/* Cache operations. */ +static inline void pa11_flush_cache_all(void) { } +static void pa11_flush_cache_mm(struct mm_struct *mm) { } +static void pa11_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ +} + +static void pa11_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ +} + +static void pa11_flush_page_to_ram(unsigned long page) +{ +} + +static void pa11_flush_cache_sigtramp(unsigned long page) +{ +} + +/* TLB operations. */ +static inline void pa11_flush_tlb_all(void) +{ + unsigned long flags; + int entry; + + save_and_cli(flags); +/* Here we will need to flush all the TLBs */ + restore_flags(flags); +} + +static void pa11_flush_tlb_mm(struct mm_struct *mm) +{ +/* This is what the MIPS does.. Is it the right thing for PA-RISC? */ + if(mm == current->mm) + pa11_flush_tlb_all(); +} + +static void pa11_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + if(mm == current->mm) + pa11_flush_tlb_all(); +} + +static void pa11_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + if(vma->vm_mm == current->mm) + pa11_flush_tlb_all(); +} + +static void pa11_load_pgd(unsigned long pg_dir) +{ + unsigned long flags; + /* We need to do the right thing here */ +} + +/* + * Initialize new page directory with pointers to invalid ptes + */ +static void pa11_pgd_init(unsigned long page) +{ + unsigned long dummy1, dummy2; + +} + +static void pa11_update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + pa11_flush_tlb_page(vma, address); +} + +static void pa11_show_regs(struct pt_regs * regs) +{ + /* + * Saved main processor registers + */ + printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], + (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], + (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], + (unsigned long) regs->regs[7]); + printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], + (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], + (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], + (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); + printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], + (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], + (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], + (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); + printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], + (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], + (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); + + /* + * Saved cp0 registers + */ + printk("epc : %08lx\nStatus: %08x\nCause : %08x\n", + (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status, + (unsigned int) regs->cp0_cause); +} + +static int pa11_user_mode(struct pt_regs *regs) +{ + /* Return user mode stuff?? */ +} + +__initfunc(void ld_mmu_pa11(void)) +{ + + /* Taken directly from the MIPS arch.. Lots of bad things here */ + clear_page = pa11_clear_page; + copy_page = pa11_copy_page; + + flush_cache_all = pa11_flush_cache_all; + flush_cache_mm = pa11_flush_cache_mm; + flush_cache_range = pa11_flush_cache_range; + flush_cache_page = pa11_flush_cache_page; + flush_cache_sigtramp = pa11_flush_cache_sigtramp; + flush_page_to_ram = pa11_flush_page_to_ram; + + flush_tlb_all = pa11_flush_tlb_all; + flush_tlb_mm = pa11_flush_tlb_mm; + flush_tlb_range = pa11_flush_tlb_range; + flush_tlb_page = pa11_flush_tlb_page; + pa11_asid_setup(); + + load_pgd = pa11_load_pgd; + pgd_init = pa11_pgd_init; + update_mmu_cache = pa11_update_mmu_cache; + + show_regs = pa11_show_regs; + + add_wired_entry = pa11_add_wired_entry; + + user_mode = pa11_user_mode; + flush_tlb_all(); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/mm/pa20.c linux/arch/parisc/mm/pa20.c --- v2.4.0-test11/linux/arch/parisc/mm/pa20.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/mm/pa20.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,170 @@ +/* $Id: pa20.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $ + * + * pa20.c: PA 2.0 specific mmu/cache code. + * + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +extern unsigned long mips_tlb_entries; + +/* page functions */ +void pa20_clear_page(unsigned long page) +{ +} + +static void pa20_copy_page(unsigned long to, unsigned long from) +{ +} + +/* Cache operations. */ +static inline void pa20_flush_cache_all(void) { } +static void pa20_flush_cache_mm(struct mm_struct *mm) { } +static void pa20_flush_cache_range(struct mm_struct *mm, + unsigned long start, + unsigned long end) +{ +} + +static void pa20_flush_cache_page(struct vm_area_struct *vma, + unsigned long page) +{ +} + +static void pa20_flush_page_to_ram(unsigned long page) +{ +} + +static void pa20_flush_cache_sigtramp(unsigned long page) +{ +} + +/* TLB operations. */ +static inline void pa20_flush_tlb_all(void) +{ + unsigned long flags; + int entry; + + save_and_cli(flags); +/* Here we will need to flush all the TLBs */ + restore_flags(flags); +} + +static void pa20_flush_tlb_mm(struct mm_struct *mm) +{ +/* This is what the MIPS does.. Is it the right thing for PA-RISC? */ + if(mm == current->mm) + pa20_flush_tlb_all(); +} + +static void pa20_flush_tlb_range(struct mm_struct *mm, unsigned long start, + unsigned long end) +{ + if(mm == current->mm) + pa20_flush_tlb_all(); +} + +static void pa20_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + if(vma->vm_mm == current->mm) + pa20_flush_tlb_all(); +} + +static void pa20_load_pgd(unsigned long pg_dir) +{ + unsigned long flags; + /* We need to do the right thing here */ +} + +/* + * Initialize new page directory with pointers to invalid ptes + */ +static void pa20_pgd_init(unsigned long page) +{ + unsigned long dummy1, dummy2; + +} + +static void pa20_update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + pa20_flush_tlb_page(vma, address); +} + +static void pa20_show_regs(struct pt_regs * regs) +{ + /* + * Saved main processor registers + */ + printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + 0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2], + (unsigned long) regs->regs[3], (unsigned long) regs->regs[4], + (unsigned long) regs->regs[5], (unsigned long) regs->regs[6], + (unsigned long) regs->regs[7]); + printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[8], (unsigned long) regs->regs[9], + (unsigned long) regs->regs[10], (unsigned long) regs->regs[11], + (unsigned long) regs->regs[12], (unsigned long) regs->regs[13], + (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]); + printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[16], (unsigned long) regs->regs[17], + (unsigned long) regs->regs[18], (unsigned long) regs->regs[19], + (unsigned long) regs->regs[20], (unsigned long) regs->regs[21], + (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]); + printk("$24: %08lx %08lx %08lx %08lx %08lx %08lx\n", + (unsigned long) regs->regs[24], (unsigned long) regs->regs[25], + (unsigned long) regs->regs[28], (unsigned long) regs->regs[29], + (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]); + + /* + * Saved cp0 registers + */ + printk("epc : %08lx\nStatus: %08x\nCause : %08x\n", + (unsigned long) regs->cp0_epc, (unsigned int) regs->cp0_status, + (unsigned int) regs->cp0_cause); +} + +static int pa20_user_mode(struct pt_regs *regs) +{ + /* Return user mode stuff?? */ +} + +__initfunc(void ld_mmu_pa20(void)) +{ + + /* Taken directly from the MIPS arch.. Lots of bad things here */ + clear_page = pa20_clear_page; + copy_page = pa20_copy_page; + + flush_cache_all = pa20_flush_cache_all; + flush_cache_mm = pa20_flush_cache_mm; + flush_cache_range = pa20_flush_cache_range; + flush_cache_page = pa20_flush_cache_page; + flush_cache_sigtramp = pa20_flush_cache_sigtramp; + flush_page_to_ram = pa20_flush_page_to_ram; + + flush_tlb_all = pa20_flush_tlb_all; + flush_tlb_mm = pa20_flush_tlb_mm; + flush_tlb_range = pa20_flush_tlb_range; + flush_tlb_page = pa20_flush_tlb_page; + pa20_asid_setup(); + + load_pgd = pa20_load_pgd; + pgd_init = pa20_pgd_init; + update_mmu_cache = pa20_update_mmu_cache; + + show_regs = pa20_show_regs; + + add_wired_entry = pa20_add_wired_entry; + + user_mode = pa20_user_mode; + flush_tlb_all(); +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/tools/Makefile linux/arch/parisc/tools/Makefile --- v2.4.0-test11/linux/arch/parisc/tools/Makefile Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/tools/Makefile Tue Dec 5 12:29:39 2000 @@ -0,0 +1,28 @@ +# Makefile for MIPS kernel build tools. +# +# Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) +# Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu) +# +# $Id: Makefile,v 1.3 1999/09/29 05:19:56 grundler Exp $ +# +TARGET := $(TOPDIR)/include/asm-$(ARCH)/offset.h + +.S.s: + $(CPP) $(CFLAGS) $< -o $*.s +.S.o: + $(CC) $(CFLAGS) -c $< -o $*.o + +all: $(TARGET) + +$(TARGET): offset.h + cmp -s $^ $@ || (cp $^ $(TARGET).new && mv $(TARGET).new $(TARGET)) + +offset.h: offset.s + sed -n '/^@@@/s///p' $^ >$@ + +offset.s: offset.c + +clean: + rm -f offset.[hs] $(TARGET).new + +include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/tools/offset.c linux/arch/parisc/tools/offset.c --- v2.4.0-test11/linux/arch/parisc/tools/offset.c Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/tools/offset.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,326 @@ +/* $Id: offset.c,v 1.2 2000/01/31 13:42:59 jsm Exp $ + * + * offset.c: Calculate pt_regs and task_struct offsets. + * + * Copyright (C) 1996 David S. Miller + * Made portable by Ralf Baechle + * Adapted to parisc by Philipp Rumpf, (C) 1999 SuSE GmbH Nuernberg */ + +#include +#include +#include + +#include +#include +#include + +#define text(t) __asm__("\n@@@" t) +#define _offset(type, member) (&(((type *)NULL)->member)) + +#define offset(string, ptr, member) \ + __asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member))) +#define size(string, size) \ + __asm__("\n@@@" string "%0" : : "i" (sizeof(size))) +#define align(x,y) (((x)+(2*(y))-1)-(((x)+(y)-1)%(y))) +#define size_align(string, size, algn) \ + __asm__("\n@@@" string "%0" : : "i" \ + align(sizeof(size),algn)) +#define linefeed text("") + +text("/* DO NOT TOUCH, AUTOGENERATED BY OFFSET.C */"); +linefeed; +text("#ifndef _PARISC_OFFSET_H"); +text("#define _PARISC_OFFSET_H"); +linefeed; + +void output_task_ptreg_defines(void) +{ + text("/* PA-RISC task pt_regs offsets. */"); + offset("#define TASK_REGS ", struct task_struct, thread.regs); + offset("#define TASK_PT_PSW ", struct task_struct, thread.regs.gr[ 0]); + offset("#define TASK_PT_GR1 ", struct task_struct, thread.regs.gr[ 1]); + offset("#define TASK_PT_GR2 ", struct task_struct, thread.regs.gr[ 2]); + offset("#define TASK_PT_GR3 ", struct task_struct, thread.regs.gr[ 3]); + offset("#define TASK_PT_GR4 ", struct task_struct, thread.regs.gr[ 4]); + offset("#define TASK_PT_GR5 ", struct task_struct, thread.regs.gr[ 5]); + offset("#define TASK_PT_GR6 ", struct task_struct, thread.regs.gr[ 6]); + offset("#define TASK_PT_GR7 ", struct task_struct, thread.regs.gr[ 7]); + offset("#define TASK_PT_GR8 ", struct task_struct, thread.regs.gr[ 8]); + offset("#define TASK_PT_GR9 ", struct task_struct, thread.regs.gr[ 9]); + offset("#define TASK_PT_GR10 ", struct task_struct, thread.regs.gr[10]); + offset("#define TASK_PT_GR11 ", struct task_struct, thread.regs.gr[11]); + offset("#define TASK_PT_GR12 ", struct task_struct, thread.regs.gr[12]); + offset("#define TASK_PT_GR13 ", struct task_struct, thread.regs.gr[13]); + offset("#define TASK_PT_GR14 ", struct task_struct, thread.regs.gr[14]); + offset("#define TASK_PT_GR15 ", struct task_struct, thread.regs.gr[15]); + offset("#define TASK_PT_GR16 ", struct task_struct, thread.regs.gr[16]); + offset("#define TASK_PT_GR17 ", struct task_struct, thread.regs.gr[17]); + offset("#define TASK_PT_GR18 ", struct task_struct, thread.regs.gr[18]); + offset("#define TASK_PT_GR19 ", struct task_struct, thread.regs.gr[19]); + offset("#define TASK_PT_GR20 ", struct task_struct, thread.regs.gr[20]); + offset("#define TASK_PT_GR21 ", struct task_struct, thread.regs.gr[21]); + offset("#define TASK_PT_GR22 ", struct task_struct, thread.regs.gr[22]); + offset("#define TASK_PT_GR23 ", struct task_struct, thread.regs.gr[23]); + offset("#define TASK_PT_GR24 ", struct task_struct, thread.regs.gr[24]); + offset("#define TASK_PT_GR25 ", struct task_struct, thread.regs.gr[25]); + offset("#define TASK_PT_GR26 ", struct task_struct, thread.regs.gr[26]); + offset("#define TASK_PT_GR27 ", struct task_struct, thread.regs.gr[27]); + offset("#define TASK_PT_GR28 ", struct task_struct, thread.regs.gr[28]); + offset("#define TASK_PT_GR29 ", struct task_struct, thread.regs.gr[29]); + offset("#define TASK_PT_GR30 ", struct task_struct, thread.regs.gr[30]); + offset("#define TASK_PT_GR31 ", struct task_struct, thread.regs.gr[31]); + offset("#define TASK_PT_FR0 ", struct task_struct, thread.regs.fr[ 0]); + offset("#define TASK_PT_FR1 ", struct task_struct, thread.regs.fr[ 1]); + offset("#define TASK_PT_FR2 ", struct task_struct, thread.regs.fr[ 2]); + offset("#define TASK_PT_FR3 ", struct task_struct, thread.regs.fr[ 3]); + offset("#define TASK_PT_FR4 ", struct task_struct, thread.regs.fr[ 4]); + offset("#define TASK_PT_FR5 ", struct task_struct, thread.regs.fr[ 5]); + offset("#define TASK_PT_FR6 ", struct task_struct, thread.regs.fr[ 6]); + offset("#define TASK_PT_FR7 ", struct task_struct, thread.regs.fr[ 7]); + offset("#define TASK_PT_FR8 ", struct task_struct, thread.regs.fr[ 8]); + offset("#define TASK_PT_FR9 ", struct task_struct, thread.regs.fr[ 9]); + offset("#define TASK_PT_FR10 ", struct task_struct, thread.regs.fr[10]); + offset("#define TASK_PT_FR11 ", struct task_struct, thread.regs.fr[11]); + offset("#define TASK_PT_FR12 ", struct task_struct, thread.regs.fr[12]); + offset("#define TASK_PT_FR13 ", struct task_struct, thread.regs.fr[13]); + offset("#define TASK_PT_FR14 ", struct task_struct, thread.regs.fr[14]); + offset("#define TASK_PT_FR15 ", struct task_struct, thread.regs.fr[15]); + offset("#define TASK_PT_FR16 ", struct task_struct, thread.regs.fr[16]); + offset("#define TASK_PT_FR17 ", struct task_struct, thread.regs.fr[17]); + offset("#define TASK_PT_FR18 ", struct task_struct, thread.regs.fr[18]); + offset("#define TASK_PT_FR19 ", struct task_struct, thread.regs.fr[19]); + offset("#define TASK_PT_FR20 ", struct task_struct, thread.regs.fr[20]); + offset("#define TASK_PT_FR21 ", struct task_struct, thread.regs.fr[21]); + offset("#define TASK_PT_FR22 ", struct task_struct, thread.regs.fr[22]); + offset("#define TASK_PT_FR23 ", struct task_struct, thread.regs.fr[23]); + offset("#define TASK_PT_FR24 ", struct task_struct, thread.regs.fr[24]); + offset("#define TASK_PT_FR25 ", struct task_struct, thread.regs.fr[25]); + offset("#define TASK_PT_FR26 ", struct task_struct, thread.regs.fr[26]); + offset("#define TASK_PT_FR27 ", struct task_struct, thread.regs.fr[27]); + offset("#define TASK_PT_FR28 ", struct task_struct, thread.regs.fr[28]); + offset("#define TASK_PT_FR29 ", struct task_struct, thread.regs.fr[29]); + offset("#define TASK_PT_FR30 ", struct task_struct, thread.regs.fr[30]); + offset("#define TASK_PT_FR31 ", struct task_struct, thread.regs.fr[31]); + offset("#define TASK_PT_SR0 ", struct task_struct, thread.regs.sr[ 0]); + offset("#define TASK_PT_SR1 ", struct task_struct, thread.regs.sr[ 1]); + offset("#define TASK_PT_SR2 ", struct task_struct, thread.regs.sr[ 2]); + offset("#define TASK_PT_SR3 ", struct task_struct, thread.regs.sr[ 3]); + offset("#define TASK_PT_SR4 ", struct task_struct, thread.regs.sr[ 4]); + offset("#define TASK_PT_SR5 ", struct task_struct, thread.regs.sr[ 5]); + offset("#define TASK_PT_SR6 ", struct task_struct, thread.regs.sr[ 6]); + offset("#define TASK_PT_SR7 ", struct task_struct, thread.regs.sr[ 7]); + offset("#define TASK_PT_IASQ0 ", struct task_struct, thread.regs.iasq[0]); + offset("#define TASK_PT_IASQ1 ", struct task_struct, thread.regs.iasq[1]); + offset("#define TASK_PT_IAOQ0 ", struct task_struct, thread.regs.iaoq[0]); + offset("#define TASK_PT_IAOQ1 ", struct task_struct, thread.regs.iaoq[1]); + offset("#define TASK_PT_CR24 ", struct task_struct, thread.regs.cr24); + offset("#define TASK_PT_CR25 ", struct task_struct, thread.regs.cr25); + offset("#define TASK_PT_CR26 ", struct task_struct, thread.regs.cr26); + offset("#define TASK_PT_CR27 ", struct task_struct, thread.regs.cr27); + offset("#define TASK_PT_CR30 ", struct task_struct, thread.regs.cr30); + offset("#define TASK_PT_ORIG_R28 ", struct task_struct, thread.regs.orig_r28); + offset("#define TASK_PT_KSP ", struct task_struct, thread.regs.ksp); + offset("#define TASK_PT_KPC ", struct task_struct, thread.regs.kpc); + offset("#define TASK_PT_SAR ", struct task_struct, thread.regs.sar); + offset("#define TASK_PT_CR11 ", struct task_struct, thread.regs.sar); + offset("#define TASK_PT_IIR ", struct task_struct, thread.regs.iir); + offset("#define TASK_PT_ISR ", struct task_struct, thread.regs.isr); + offset("#define TASK_PT_IOR ", struct task_struct, thread.regs.ior); + offset("#define TASK_PT_CR_PID0 ", struct task_struct, thread.regs.cr_pid[0]); + offset("#define TASK_PT_CR_PID1 ", struct task_struct, thread.regs.cr_pid[1]); + offset("#define TASK_PT_CR_PID2 ", struct task_struct, thread.regs.cr_pid[2]); + offset("#define TASK_PT_CR_PID3 ", struct task_struct, thread.regs.cr_pid[3]); + size("#define TASK_SZ ", struct task_struct); + size_align("#define TASK_SZ_ALGN ", struct task_struct, 64); + linefeed; +} + +void output_ptreg_defines(void) +{ + text("/* PA-RISC pt_regs offsets. */"); + offset("#define PT_PSW ", struct pt_regs, gr[ 0]); + offset("#define PT_GR1 ", struct pt_regs, gr[ 1]); + offset("#define PT_GR2 ", struct pt_regs, gr[ 2]); + offset("#define PT_GR3 ", struct pt_regs, gr[ 3]); + offset("#define PT_GR4 ", struct pt_regs, gr[ 4]); + offset("#define PT_GR5 ", struct pt_regs, gr[ 5]); + offset("#define PT_GR6 ", struct pt_regs, gr[ 6]); + offset("#define PT_GR7 ", struct pt_regs, gr[ 7]); + offset("#define PT_GR8 ", struct pt_regs, gr[ 8]); + offset("#define PT_GR9 ", struct pt_regs, gr[ 9]); + offset("#define PT_GR10 ", struct pt_regs, gr[10]); + offset("#define PT_GR11 ", struct pt_regs, gr[11]); + offset("#define PT_GR12 ", struct pt_regs, gr[12]); + offset("#define PT_GR13 ", struct pt_regs, gr[13]); + offset("#define PT_GR14 ", struct pt_regs, gr[14]); + offset("#define PT_GR15 ", struct pt_regs, gr[15]); + offset("#define PT_GR16 ", struct pt_regs, gr[16]); + offset("#define PT_GR17 ", struct pt_regs, gr[17]); + offset("#define PT_GR18 ", struct pt_regs, gr[18]); + offset("#define PT_GR19 ", struct pt_regs, gr[19]); + offset("#define PT_GR20 ", struct pt_regs, gr[20]); + offset("#define PT_GR21 ", struct pt_regs, gr[21]); + offset("#define PT_GR22 ", struct pt_regs, gr[22]); + offset("#define PT_GR23 ", struct pt_regs, gr[23]); + offset("#define PT_GR24 ", struct pt_regs, gr[24]); + offset("#define PT_GR25 ", struct pt_regs, gr[25]); + offset("#define PT_GR26 ", struct pt_regs, gr[26]); + offset("#define PT_GR27 ", struct pt_regs, gr[27]); + offset("#define PT_GR28 ", struct pt_regs, gr[28]); + offset("#define PT_GR29 ", struct pt_regs, gr[29]); + offset("#define PT_GR30 ", struct pt_regs, gr[30]); + offset("#define PT_GR31 ", struct pt_regs, gr[31]); + offset("#define PT_FR0 ", struct pt_regs, fr[ 0]); + offset("#define PT_FR1 ", struct pt_regs, fr[ 1]); + offset("#define PT_FR2 ", struct pt_regs, fr[ 2]); + offset("#define PT_FR3 ", struct pt_regs, fr[ 3]); + offset("#define PT_FR4 ", struct pt_regs, fr[ 4]); + offset("#define PT_FR5 ", struct pt_regs, fr[ 5]); + offset("#define PT_FR6 ", struct pt_regs, fr[ 6]); + offset("#define PT_FR7 ", struct pt_regs, fr[ 7]); + offset("#define PT_FR8 ", struct pt_regs, fr[ 8]); + offset("#define PT_FR9 ", struct pt_regs, fr[ 9]); + offset("#define PT_FR10 ", struct pt_regs, fr[10]); + offset("#define PT_FR11 ", struct pt_regs, fr[11]); + offset("#define PT_FR12 ", struct pt_regs, fr[12]); + offset("#define PT_FR13 ", struct pt_regs, fr[13]); + offset("#define PT_FR14 ", struct pt_regs, fr[14]); + offset("#define PT_FR15 ", struct pt_regs, fr[15]); + offset("#define PT_FR16 ", struct pt_regs, fr[16]); + offset("#define PT_FR17 ", struct pt_regs, fr[17]); + offset("#define PT_FR18 ", struct pt_regs, fr[18]); + offset("#define PT_FR19 ", struct pt_regs, fr[19]); + offset("#define PT_FR20 ", struct pt_regs, fr[20]); + offset("#define PT_FR21 ", struct pt_regs, fr[21]); + offset("#define PT_FR22 ", struct pt_regs, fr[22]); + offset("#define PT_FR23 ", struct pt_regs, fr[23]); + offset("#define PT_FR24 ", struct pt_regs, fr[24]); + offset("#define PT_FR25 ", struct pt_regs, fr[25]); + offset("#define PT_FR26 ", struct pt_regs, fr[26]); + offset("#define PT_FR27 ", struct pt_regs, fr[27]); + offset("#define PT_FR28 ", struct pt_regs, fr[28]); + offset("#define PT_FR29 ", struct pt_regs, fr[29]); + offset("#define PT_FR30 ", struct pt_regs, fr[30]); + offset("#define PT_FR31 ", struct pt_regs, fr[31]); + offset("#define PT_SR0 ", struct pt_regs, sr[ 0]); + offset("#define PT_SR1 ", struct pt_regs, sr[ 1]); + offset("#define PT_SR2 ", struct pt_regs, sr[ 2]); + offset("#define PT_SR3 ", struct pt_regs, sr[ 3]); + offset("#define PT_SR4 ", struct pt_regs, sr[ 4]); + offset("#define PT_SR5 ", struct pt_regs, sr[ 5]); + offset("#define PT_SR6 ", struct pt_regs, sr[ 6]); + offset("#define PT_SR7 ", struct pt_regs, sr[ 7]); + offset("#define PT_IASQ0 ", struct pt_regs, iasq[0]); + offset("#define PT_IASQ1 ", struct pt_regs, iasq[1]); + offset("#define PT_IAOQ0 ", struct pt_regs, iaoq[0]); + offset("#define PT_IAOQ1 ", struct pt_regs, iaoq[1]); + offset("#define PT_CR24 ", struct pt_regs, cr24); + offset("#define PT_CR25 ", struct pt_regs, cr25); + offset("#define PT_CR26 ", struct pt_regs, cr26); + offset("#define PT_CR27 ", struct pt_regs, cr27); + offset("#define PT_CR30 ", struct pt_regs, cr30); + offset("#define PT_ORIG_R28 ", struct pt_regs, orig_r28); + offset("#define PT_KSP ", struct pt_regs, ksp); + offset("#define PT_KPC ", struct pt_regs, kpc); + offset("#define PT_SAR ", struct pt_regs, sar); + offset("#define PT_CR11 ", struct pt_regs, sar); + offset("#define PT_IIR ", struct pt_regs, iir); + offset("#define PT_ISR ", struct pt_regs, isr); + offset("#define PT_IOR ", struct pt_regs, ior); + offset("#define PT_CR_PID0 ", struct pt_regs, cr_pid[0]); + offset("#define PT_CR_PID1 ", struct pt_regs, cr_pid[1]); + offset("#define PT_CR_PID2 ", struct pt_regs, cr_pid[2]); + offset("#define PT_CR_PID3 ", struct pt_regs, cr_pid[3]); + size("#define PT_SIZE ", struct pt_regs); + size_align("#define PT_SZ_ALGN ", struct pt_regs, 64); + linefeed; +} + +void output_task_defines(void) +{ + text("/* PARISC task_struct offsets. */"); + offset("#define TASK_STATE ", struct task_struct, state); + offset("#define TASK_FLAGS ", struct task_struct, flags); + offset("#define TASK_SIGPENDING ", struct task_struct, sigpending); + offset("#define TASK_SEGMENT ", struct task_struct, addr_limit); + offset("#define TASK_NEED_RESCHED ", struct task_struct, need_resched); + offset("#define TASK_COUNTER ", struct task_struct, counter); + offset("#define TASK_PTRACE ", struct task_struct, ptrace); + offset("#define TASK_NICE ", struct task_struct, nice); + offset("#define TASK_MM ", struct task_struct, mm); + offset("#define TASK_PROCESSOR ", struct task_struct, processor); + size ("#define TASK_SZ ", struct task_struct); + size_align("#define TASK_SZ_ALGN ", struct task_struct, 64); + linefeed; +} + +void output_irq_stat_defines(void) +{ + text("/* PARISC irq_cpustat_t offsets. */"); + offset("#define IRQSTAT_SI_ACTIVE ", irq_cpustat_t, __softirq_active); + offset("#define IRQSTAT_SI_MASK ", irq_cpustat_t, __softirq_mask); + size ("#define IRQSTAT_SZ ", irq_cpustat_t); + linefeed; +} + +#ifdef PRUMPF_HAD_MORE_TIME +void output_thread_defines(void) +{ + text("/* PARISC specific thread_struct offsets. */"); + offset("#define THREAD_REG16 ", struct task_struct, thread.reg16); + offset("#define THREAD_REG17 ", struct task_struct, thread.reg17); + offset("#define THREAD_REG18 ", struct task_struct, thread.reg18); + offset("#define THREAD_REG19 ", struct task_struct, thread.reg19); + offset("#define THREAD_REG20 ", struct task_struct, thread.reg20); + offset("#define THREAD_REG21 ", struct task_struct, thread.reg21); + offset("#define THREAD_REG22 ", struct task_struct, thread.reg22); + offset("#define THREAD_REG23 ", struct task_struct, thread.reg23); + offset("#define THREAD_REG29 ", struct task_struct, thread.reg29); + offset("#define THREAD_REG30 ", struct task_struct, thread.reg30); + offset("#define THREAD_REG31 ", struct task_struct, thread.reg31); + offset("#define THREAD_STATUS ", struct task_struct, thread.cp0_status); + offset("#define THREAD_FPU ", struct task_struct, thread.fpu); + offset("#define THREAD_BVADDR ", struct task_struct, thread.cp0_badvaddr); + offset("#define THREAD_BUADDR ", struct task_struct, thread.cp0_baduaddr); + offset("#define THREAD_ECODE ", struct task_struct, thread.error_code); + offset("#define THREAD_TRAPNO ", struct task_struct, thread.trap_no); + offset("#define THREAD_PGDIR ", struct task_struct, thread.pg_dir); + offset("#define THREAD_MFLAGS ", struct task_struct, thread.mflags); + offset("#define THREAD_CURDS ", struct task_struct, thread.current_ds); + offset("#define THREAD_TRAMP ", struct task_struct, thread.irix_trampoline); + offset("#define THREAD_OLDCTX ", struct task_struct, thread.irix_oldctx); + linefeed; +} + +void output_mm_defines(void) +{ + text("/* Linux mm_struct offsets. */"); + offset("#define MM_COUNT ", struct mm_struct, count); + offset("#define MM_PGD ", struct mm_struct, pgd); + offset("#define MM_CONTEXT ", struct mm_struct, context); + linefeed; +} + +void output_sc_defines(void) +{ + text("/* Linux sigcontext offsets. */"); + offset("#define SC_REGMASK ", struct sigcontext, sc_regmask); + offset("#define SC_STATUS ", struct sigcontext, sc_status); + offset("#define SC_PC ", struct sigcontext, sc_pc); + offset("#define SC_REGS ", struct sigcontext, sc_regs); + offset("#define SC_FPREGS ", struct sigcontext, sc_fpregs); + offset("#define SC_OWNEDFP ", struct sigcontext, sc_ownedfp); + offset("#define SC_FPC_CSR ", struct sigcontext, sc_fpc_csr); + offset("#define SC_FPC_EIR ", struct sigcontext, sc_fpc_eir); + offset("#define SC_SSFLAGS ", struct sigcontext, sc_ssflags); + offset("#define SC_MDHI ", struct sigcontext, sc_mdhi); + offset("#define SC_MDLO ", struct sigcontext, sc_mdlo); + offset("#define SC_CAUSE ", struct sigcontext, sc_cause); + offset("#define SC_BADVADDR ", struct sigcontext, sc_badvaddr); + offset("#define SC_SIGSET ", struct sigcontext, sc_sigset); + linefeed; +} + +#endif + +text("#endif /* !(_PARISC_OFFSET_H) */"); diff -u --recursive --new-file v2.4.0-test11/linux/arch/parisc/vmlinux.lds linux/arch/parisc/vmlinux.lds --- v2.4.0-test11/linux/arch/parisc/vmlinux.lds Wed Dec 31 16:00:00 1969 +++ linux/arch/parisc/vmlinux.lds Tue Dec 5 12:29:39 2000 @@ -0,0 +1,79 @@ +/* ld script to make hppa Linux kernel */ +OUTPUT_FORMAT("elf32-hppa") +OUTPUT_ARCH(hppa) +ENTRY(_stext) +SECTIONS +{ + +/* right now use 0x10000/0x11000, later when we don't use Console and + * Boot-Device IODC, we will change this to 0x8000 !!! + */ + + . = 0xc0100000; +/* . = 0x10000; */ + + _text = .; /* Text and read-only data */ + .text BLOCK(16) : { + *(.text*) + *(.PARISC.unwind) + *(.fixup) + *(.lock.text) /* out-of-line lock text */ + *(.gnu.warning) + } = 0 + + . = ALIGN(16); + .rodata : { *(.rodata) } + .kstrtab : { *(.kstrtab) } + + _etext = .; /* End of text section */ + + .data BLOCK(8192) : { /* Data without special */ + data_start = .; + *(.data) + } + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + __start___ksymtab = .; /* Kernel symbol table */ + __ksymtab : { *(__ksymtab) } + __stop___ksymtab = .; + + + . = ALIGN(16384); + __init_begin = .; + .init.text : { *(.init.text) } + .init.data : { *(.init.data) } + . = ALIGN(16); + __setup_start = .; + .setup.init : { *(.setup.init) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { *(.initcall.init) } + __initcall_end = .; + __init_end = .; + + + init_task BLOCK(16384) : { *(init_task) } /* The initial task and kernel stack */ + + _edata = .; /* End of data section */ + + + .bss : { *(.bss) *(COMMON) } /* BSS */ + + + _end = . ; + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + .note 0 : { *(.note) } + +} diff -u --recursive --new-file v2.4.0-test11/linux/arch/ppc/8260_io/uart.c linux/arch/ppc/8260_io/uart.c --- v2.4.0-test11/linux/arch/ppc/8260_io/uart.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ppc/8260_io/uart.c Wed Dec 6 12:06:18 2000 @@ -496,8 +496,9 @@ #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif - queue_task(&info->tqueue_hangup, - &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&info->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; } } if (info->flags & ASYNC_CTS_FLOW) { @@ -624,10 +625,9 @@ struct tty_struct *tty; tty = info->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); + MOD_DEC_USE_COUNT; } /*static void rs_8xx_timer(void) diff -u --recursive --new-file v2.4.0-test11/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c --- v2.4.0-test11/linux/arch/ppc/8xx_io/fec.c Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/8xx_io/fec.c Wed Dec 6 12:06:18 2000 @@ -1214,7 +1214,7 @@ fep->phy_task.routine = (void *)mii_relink; fep->phy_task.data = dev; - queue_task(&fep->phy_task, &tq_scheduler); + schedule_task(&fep->phy_task); } static void mii_queue_config(uint mii_reg, struct net_device *dev) @@ -1223,7 +1223,7 @@ fep->phy_task.routine = (void *)mii_display_config; fep->phy_task.data = dev; - queue_task(&fep->phy_task, &tq_scheduler); + schedule_task(&fep->phy_task); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c --- v2.4.0-test11/linux/arch/ppc/8xx_io/uart.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ppc/8xx_io/uart.c Wed Dec 6 12:06:18 2000 @@ -514,8 +514,9 @@ #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif - queue_task(&info->tqueue_hangup, - &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&info->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; } } if (info->flags & ASYNC_CTS_FLOW) { @@ -645,10 +646,9 @@ struct tty_struct *tty; tty = info->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); + MOD_DEC_USE_COUNT; } /*static void rs_8xx_timer(void) diff -u --recursive --new-file v2.4.0-test11/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c --- v2.4.0-test11/linux/arch/ppc/amiga/config.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ppc/amiga/config.c Mon Nov 27 17:57:34 2000 @@ -49,11 +49,28 @@ unsigned char amiga_psfreq; struct amiga_hw_present amiga_hw_present; -static const char *amiga_models[] = { - "A500", "A500+", "A600", "A1000", "A1200", "A2000", "A2500", "A3000", - "A3000T", "A3000+", "A4000", "A4000T", "CDTV", "CD32", "Draco" +static const char s_a500[] __initdata = "A500"; +static const char s_a500p[] __initdata = "A500+"; +static const char s_a600[] __initdata = "A600"; +static const char s_a1000[] __initdata = "A1000"; +static const char s_a1200[] __initdata = "A1200"; +static const char s_a2000[] __initdata = "A2000"; +static const char s_a2500[] __initdata = "A2500"; +static const char s_a3000[] __initdata = "A3000"; +static const char s_a3000t[] __initdata = "A3000T"; +static const char s_a3000p[] __initdata = "A3000+"; +static const char s_a4000[] __initdata = "A4000"; +static const char s_a4000t[] __initdata = "A4000T"; +static const char s_cdtv[] __initdata = "CDTV"; +static const char s_cd32[] __initdata = "CD32"; +static const char s_draco[] __initdata = "Draco"; +static const char *amiga_models[] __initdata = { + s_a500, s_a500p, s_a600, s_a1000, s_a1200, s_a2000, s_a2500, s_a3000, + s_a3000t, s_a3000p, s_a4000, s_a4000t, s_cdtv, s_cd32, s_draco, }; +static char amiga_model_name[13] = "Amiga "; + extern char m68k_debug_device[]; static void amiga_sched_init(void (*handler)(int, void *, struct pt_regs *)); @@ -117,6 +134,26 @@ extern void (*kd_mksound)(unsigned int, unsigned int); + + /* + * Motherboard Resources present in all Amiga models + */ + +static struct resource mb_res[] = { + { "Ranger Memory", 0x00c00000, 0x00c7ffff }, + { "CIA B", 0x00bfd000, 0x00bfdfff }, + { "CIA A", 0x00bfe000, 0x00bfefff }, + { "Custom I/O", 0x00dff000, 0x00dfffff }, + { "Kickstart ROM", 0x00f80000, 0x00ffffff } +}; + +static struct resource rtc_resource = { + "A2000 RTC", 0x00dc0000, 0x00dcffff +}; + +static struct resource ram_resource[NUM_MEMINFO]; + + /* * Parse an Amiga-specific record in the bootinfo */ @@ -157,11 +194,15 @@ break; case BI_AMIGA_AUTOCON: - if (zorro_num_autocon < ZORRO_NUM_AUTO) - memcpy(&zorro_autocon[zorro_num_autocon++], - (const struct ConfigDev *)data, - sizeof(struct ConfigDev)); - else + if (zorro_num_autocon < ZORRO_NUM_AUTO) { + const struct ConfigDev *cd = (struct ConfigDev *)data; + struct zorro_dev *dev = &zorro_autocon[zorro_num_autocon++]; + dev->rom = cd->cd_Rom; + dev->slotaddr = cd->cd_SlotAddr; + dev->slotsize = cd->cd_SlotSize; + dev->resource.start = (unsigned long)cd->cd_BoardAddr; + dev->resource.end = dev->resource.start+cd->cd_BoardSize-1; + } else printk("amiga_parse_bootinfo: too many AutoConfig devices\n"); break; @@ -188,8 +229,10 @@ memset(&amiga_hw_present, 0, sizeof(amiga_hw_present)); printk("Amiga hardware found: "); - if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) + if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) { printk("[%s] ", amiga_models[amiga_model-AMI_500]); + strcat(amiga_model_name, amiga_models[amiga_model-AMI_500]); + } switch(amiga_model) { case AMI_UNKNOWN: @@ -342,9 +385,19 @@ void __init config_amiga(void) { + int i; + amiga_debug_init(); amiga_identify(); + /* Some APUS boxes may have PCI memory, but ... */ + iomem_resource.name = "Memory"; + request_resource(&iomem_resource, &ranger_resource); + request_resource(&iomem_resource, &ciab_resource); + request_resource(&iomem_resource, &ciaa_resource); + request_resource(&iomem_resource, &custom_chips_resource); + request_resource(&iomem_resource, &kickstart_resource); + mach_sched_init = amiga_sched_init; mach_keyb_init = amiga_keyb_init; mach_kbdrate = amiga_kbdrate; @@ -362,9 +415,12 @@ mach_gettimeoffset = amiga_gettimeoffset; if (AMIGAHW_PRESENT(A3000_CLK)){ mach_gettod = a3000_gettod; + rtc_resource.name[1] = '3'; + request_resource(&iomem_resource, &rtc_resource); } else{ /* if (AMIGAHW_PRESENT(A2000_CLK)) */ mach_gettod = a2000_gettod; + request_resource(&iomem_resource, &rtc_resource); } mach_max_dma_address = 0xffffffff; /* @@ -404,6 +460,17 @@ /* ensure that the DMA master bit is set */ custom.dmacon = DMAF_SETCLR | DMAF_MASTER; + /* request all RAM */ + for (i = 0; i < m68k_num_memory; i++) { + ram_resource[i].name = + (m68k_memory[i].addr >= 0x01000000) ? "32-bit Fast RAM" : + (m68k_memory[i].addr < 0x00c00000) ? "16-bit Fast RAM" : + "16-bit Slow RAM"; + ram_resource[i].start = m68k_memory[i].addr; + ram_resource[i].end = m68k_memory[i].addr+m68k_memory[i].size-1; + request_resource(&iomem_resource, &ram_resource[i]); + } + /* initialize chipram allocator */ amiga_chip_init (); @@ -437,6 +504,8 @@ { jiffy_ticks = (amiga_eclock+HZ/2)/HZ; + if (!request_mem_region(CIAB_PHYSADDR+0x400, 0x200, "timer")) + printk("Cannot allocate ciab.ta{lo,hi}\n"); ciab.cra &= 0xC0; /* turn off timer A, continuous mode, from Eclk */ ciab.talo = jiffy_ticks % 256; ciab.tahi = jiffy_ticks / 256; @@ -727,7 +796,7 @@ static void amiga_savekmsg_init(void) { - savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM); + savekmsg = (struct savekmsg *)amiga_chip_alloc(SAVEKMSG_MAXMEM, "Debug"); savekmsg->magic1 = SAVEKMSG_MAGIC1; savekmsg->magic2 = SAVEKMSG_MAGIC2; savekmsg->magicptr = virt_to_phys(savekmsg); @@ -840,9 +909,7 @@ static void amiga_get_model(char *model) { - strcpy(model, "Amiga "); - if (amiga_model >= AMI_500 && amiga_model <= AMI_DRACO) - strcat(model, amiga_models[amiga_model-AMI_500]); + strcpy(model, amiga_model_name); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.4.0-test11/linux/arch/ppc/mm/init.c Sun Nov 19 18:44:04 2000 +++ linux/arch/ppc/mm/init.c Tue Nov 28 22:43:39 2000 @@ -293,7 +293,7 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!atomic_read(&mem_map[i].count)) + else if (!page_count(mem_map+i)) free++; else shared += atomic_read(&mem_map[i].count) - 1; diff -u --recursive --new-file v2.4.0-test11/linux/arch/s390/kernel/traps.c linux/arch/s390/kernel/traps.c --- v2.4.0-test11/linux/arch/s390/kernel/traps.c Mon Jun 19 13:25:06 2000 +++ linux/arch/s390/kernel/traps.c Sun Dec 3 17:48:19 2000 @@ -47,12 +47,6 @@ asmlinkage int system_call(void); -static inline void console_verbose(void) -{ - extern int console_loglevel; - console_loglevel = 15; -} - #define DO_ERROR(trapnr, signr, str, name, tsk) \ asmlinkage void name(struct pt_regs * regs, long error_code) \ { \ diff -u --recursive --new-file v2.4.0-test11/linux/arch/s390/mm/init.c linux/arch/s390/mm/init.c --- v2.4.0-test11/linux/arch/s390/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/s390/mm/init.c Tue Nov 28 22:43:39 2000 @@ -192,7 +192,7 @@ void show_mem(void) { - int i,free = 0,total = 0,reserved = 0; + int i, total = 0, reserved = 0; int shared = 0, cached = 0; printk("Mem-info:\n"); @@ -205,9 +205,7 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!atomic_read(&mem_map[i].count)) - free++; - else + else if (page_count(mem_map+i)) shared += atomic_read(&mem_map[i].count) - 1; } printk("%d pages of RAM\n",total); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sh/kernel/traps.c linux/arch/sh/kernel/traps.c --- v2.4.0-test11/linux/arch/sh/kernel/traps.c Sun Oct 8 10:50:11 2000 +++ linux/arch/sh/kernel/traps.c Sun Dec 3 17:48:19 2000 @@ -28,12 +28,6 @@ #include #include -static inline void console_verbose(void) -{ - extern int console_loglevel; - console_loglevel = 15; -} - #define DO_ERROR(trapnr, signr, str, name, tsk) \ asmlinkage void do_##name(unsigned long r4, unsigned long r5, \ unsigned long r6, unsigned long r7, \ diff -u --recursive --new-file v2.4.0-test11/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c --- v2.4.0-test11/linux/arch/sh/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sh/mm/init.c Tue Nov 28 22:43:39 2000 @@ -150,7 +150,7 @@ void show_mem(void) { - int i,free = 0,total = 0,reserved = 0; + int i, total = 0, reserved = 0; int shared = 0, cached = 0; printk("Mem-info:\n"); @@ -163,9 +163,7 @@ reserved++; else if (PageSwapCache(mem_map+i)) cached++; - else if (!page_count(mem_map+i)) - free++; - else + else if (page_count(mem_map+i)) shared += page_count(mem_map+i) - 1; } printk("%d pages of RAM\n",total); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/boot/piggyback.c linux/arch/sparc/boot/piggyback.c --- v2.4.0-test11/linux/arch/sparc/boot/piggyback.c Sun Mar 12 19:11:16 2000 +++ linux/arch/sparc/boot/piggyback.c Mon Dec 11 12:37:02 2000 @@ -1,9 +1,10 @@ -/* $Id: piggyback.c,v 1.3 2000/03/11 00:22:26 zaitcev Exp $ +/* $Id: piggyback.c,v 1.4 2000/12/05 00:48:57 anton Exp $ Simple utility to make a single-image install kernel with initial ramdisk for Sparc tftpbooting without need to set up nfs. - + Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - + Pete Zaitcev endian fixes for cross-compiles, 2000. + 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 @@ -34,6 +35,24 @@ * as PROM looks for a.out image only. */ +unsigned short ld2(char *p) +{ + return (p[0] << 8) | p[1]; +} + +unsigned int ld4(char *p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +} + +void st4(char *p, unsigned int x) +{ + p[0] = x >> 24; + p[1] = x >> 16; + p[2] = x >> 8; + p[3] = x; +} + void usage(void) { /* fs_img.gz is an image of initial ramdisk. */ @@ -50,7 +69,8 @@ int main(int argc,char **argv) { - char buffer [1024], *q, *r; + static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; + unsigned char buffer[1024], *q, *r; unsigned int i, j, k, start, end, offset; FILE *map; struct stat s; @@ -74,21 +94,20 @@ } if ((image = open(argv[1],O_RDWR)) < 0) die(argv[1]); if (read(image,buffer,512) != 512) die(argv[1]); - if (!memcmp (buffer, "\177ELF", 4)) { - unsigned int *p = (unsigned int *)(buffer + *(unsigned int *)(buffer + 28)); - - i = p[1] + *(unsigned int *)(buffer + 24) - p[2]; + if (memcmp (buffer, "\177ELF", 4) == 0) { + q = buffer + ld4(buffer + 28); + i = ld4(q + 4) + ld4(buffer + 24) - ld4(q + 8); if (lseek(image,i,0) < 0) die("lseek"); if (read(image,buffer,512) != 512) die(argv[1]); j = 0; - } else if (*(unsigned int *)buffer == 0x01030107) { + } else if (memcmp(buffer, aout_magic, 4) == 0) { i = j = 32; } else { fprintf (stderr, "Not ELF nor a.out. Don't blame me.\n"); exit(1); } k = i; - i += ((*(unsigned short *)(buffer + j + 2))<<2) - 512; + i += (ld2(buffer + j + 2)<<2) - 512; if (lseek(image,i,0) < 0) die("lseek"); if (read(image,buffer,1024) != 1024) die(argv[1]); for (q = buffer, r = q + 512; q < r; q += 4) { @@ -101,10 +120,12 @@ } offset = i + (q - buffer) + 10; if (lseek(image, offset, 0) < 0) die ("lseek"); - *(unsigned *)buffer = 0; - *(unsigned *)(buffer + 4) = 0x01000000; - *(unsigned *)(buffer + 8) = ((end + 32 + 4095) & ~4095); - *(unsigned *)(buffer + 12) = s.st_size; + + st4(buffer, 0); + st4(buffer + 4, 0x01000000); + st4(buffer + 8, (end + 32 + 4095) & ~4095); + st4(buffer + 12, s.st_size); + if (write(image,buffer+2,14) != 14) die (argv[1]); if (lseek(image, k - start + ((end + 32 + 4095) & ~4095), 0) < 0) die ("lseek"); if ((tail = open(argv[3],O_RDONLY)) < 0) die(argv[3]); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.4.0-test11/linux/arch/sparc/config.in Sun Nov 19 18:44:04 2000 +++ linux/arch/sparc/config.in Tue Nov 28 21:53:44 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.105 2000/11/12 10:01:41 davem Exp $ +# $Id: config.in,v 1.106 2000/11/17 04:27:52 davem Exp $ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c --- v2.4.0-test11/linux/arch/sparc/kernel/ioport.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/kernel/ioport.c Mon Dec 11 12:37:02 2000 @@ -1,4 +1,4 @@ -/* $Id: ioport.c,v 1.40 2000/10/10 09:44:46 anton Exp $ +/* $Id: ioport.c,v 1.42 2000/12/05 00:56:36 anton Exp $ * ioport.c: Simple io mapping allocator. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -447,6 +447,7 @@ */ void sbus_dma_sync_single(struct sbus_dev *sdev, u32 ba, long size, int direction) { +#if 0 unsigned long va; struct resource *res; @@ -461,6 +462,7 @@ * to a kernel near you. - Anton */ /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ +#endif } void sbus_dma_sync_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) @@ -584,7 +586,8 @@ * Once the device is given the dma address, the device owns this memory * until either pci_unmap_single or pci_dma_sync_single is performed. */ -dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction) +dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, + int direction) { if (direction == PCI_DMA_NONE) BUG(); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c --- v2.4.0-test11/linux/arch/sparc/kernel/pcic.c Sun Nov 19 18:44:04 2000 +++ linux/arch/sparc/kernel/pcic.c Mon Dec 11 12:37:02 2000 @@ -1,4 +1,4 @@ -/* $Id: pcic.c,v 1.19 2000/11/08 04:49:17 davem Exp $ +/* $Id: pcic.c,v 1.20 2000/12/05 00:56:36 anton Exp $ * pcic.c: Sparc/PCI controller support * * Copyright (C) 1998 V. Roganov and G. Raiko @@ -556,8 +556,8 @@ */ 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); + "device '%s' at %02x:%02x)\n", address, + namebuf, dev->bus->number, dev->devfn); } } } @@ -568,12 +568,12 @@ { struct pcic_ca2irq *p; int i, ivec; - char namebuf[64]; /* P3 remove */ + char namebuf[64]; if (node == 0 || node == -1) { strcpy(namebuf, "???"); } else { - prom_getstring(node, "name", namebuf, sizeof(namebuf)); /* P3 remove */ + prom_getstring(node, "name", namebuf, sizeof(namebuf)); } if ((p = pcic->pcic_imap) == 0) { @@ -612,8 +612,8 @@ if (p->irq == 0 || p->irq >= 15) { /* Corrupted map */ printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {} } - printk("PCIC: setting irq %x for device (%x,%x)\n", - p->irq, dev->device, dev->vendor); + printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n", + p->irq, p->pin, dev->bus->number, dev->devfn); dev->irq = p->irq; i = p->pin; diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/smp.c linux/arch/sparc/kernel/smp.c --- v2.4.0-test11/linux/arch/sparc/kernel/smp.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/kernel/smp.c Tue Nov 28 21:53:44 2000 @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c --- v2.4.0-test11/linux/arch/sparc/kernel/sparc_ksyms.c Thu Sep 7 08:32:00 2000 +++ linux/arch/sparc/kernel/sparc_ksyms.c Mon Dec 11 12:37:02 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc_ksyms.c,v 1.104 2000/09/06 05:43:00 anton Exp $ +/* $Id: sparc_ksyms.c,v 1.105 2000/12/11 05:24:25 anton Exp $ * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -111,6 +111,11 @@ EXPORT_SYMBOL_PRIVATE(_rw_read_exit); EXPORT_SYMBOL_PRIVATE(_rw_write_enter); #endif +/* semaphores */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_trylock); +EXPORT_SYMBOL(__down_interruptible); /* rw semaphores */ EXPORT_SYMBOL_NOVERS(___down_read); EXPORT_SYMBOL_NOVERS(___down_write); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c --- v2.4.0-test11/linux/arch/sparc/kernel/sun4d_smp.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/kernel/sun4d_smp.c Tue Nov 28 21:53:44 2000 @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c --- v2.4.0-test11/linux/arch/sparc/kernel/sun4m_smp.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/kernel/sun4m_smp.c Tue Nov 28 21:53:44 2000 @@ -25,7 +25,6 @@ #include #include #include -#include #include #include diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/kernel/sys_sparc.c linux/arch/sparc/kernel/sys_sparc.c --- v2.4.0-test11/linux/arch/sparc/kernel/sys_sparc.c Tue Jul 11 11:07:55 2000 +++ linux/arch/sparc/kernel/sys_sparc.c Mon Dec 11 12:37:02 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.66 2000/07/10 20:57:35 davem Exp $ +/* $Id: sys_sparc.c,v 1.67 2000/11/30 08:37:31 anton Exp $ * linux/arch/sparc/kernel/sys_sparc.c * * This file contains various random system calls that @@ -34,6 +34,8 @@ return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */ } +#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) + unsigned long get_unmapped_area(unsigned long addr, unsigned long len) { struct vm_area_struct * vmm; @@ -45,7 +47,11 @@ return 0; if (!addr) addr = TASK_UNMAPPED_BASE; - addr = PAGE_ALIGN(addr); + + if (current->thread.flags & SPARC_FLAG_MMAPSHARED) + addr = COLOUR_ALIGN(addr); + else + addr = PAGE_ALIGN(addr); for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { /* At this point: (!vmm || addr < vmm->vm_end). */ @@ -58,6 +64,8 @@ if (!vmm || addr + len <= vmm->vm_start) return addr; addr = vmm->vm_end; + if (current->thread.flags & SPARC_FLAG_MMAPSHARED) + addr = COLOUR_ALIGN(addr); } } @@ -224,10 +232,16 @@ goto out_putf; flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + + if (flags & MAP_SHARED) + current->thread.flags |= SPARC_FLAG_MMAPSHARED; + down(¤t->mm->mmap_sem); retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); up(¤t->mm->mmap_sem); + current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); + out_putf: if (file) fput(file); @@ -259,6 +273,7 @@ unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) { + struct vm_area_struct *vma; unsigned long ret = -EINVAL; if (ARCH_SUN4C_SUN4) { if (old_len > 0x20000000 || new_len > 0x20000000) @@ -270,6 +285,9 @@ new_len > TASK_SIZE - PAGE_SIZE) goto out; down(¤t->mm->mmap_sem); + vma = find_vma(current->mm, addr); + if (vma && (vma->vm_flags & VM_SHARED)) + current->thread.flags |= SPARC_FLAG_MMAPSHARED; if (flags & MREMAP_FIXED) { if (ARCH_SUN4C_SUN4 && new_addr < 0xe0000000 && @@ -290,6 +308,7 @@ } ret = do_mremap(addr, old_len, new_len, flags, new_addr); out_sem: + current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); up(¤t->mm->mmap_sem); out: return ret; @@ -302,12 +321,10 @@ static int count = 0; if (count++ > 5) return -ENOSYS; - lock_kernel(); printk ("%s[%d]: Unimplemented SPARC system call %d\n", current->comm, current->pid, (int)regs->u_regs[1]); #ifdef DEBUG_UNIMP_SYSCALL show_regs (regs); #endif - unlock_kernel(); return -ENOSYS; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.4.0-test11/linux/arch/sparc/mm/init.c Sun Nov 19 18:44:04 2000 +++ linux/arch/sparc/mm/init.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.95 2000/11/10 04:49:56 davem Exp $ +/* $Id: init.c,v 1.96 2000/11/30 08:51:50 anton Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -579,7 +579,8 @@ void flush_page_to_ram(struct page *page) { - unsigned long vaddr = (unsigned long) kmap(page); - __flush_page_to_ram(vaddr); - kunmap(page); + unsigned long vaddr = (unsigned long)page_address(page); + + if (vaddr) + __flush_page_to_ram(vaddr); } diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.4.0-test11/linux/arch/sparc/mm/srmmu.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc/mm/srmmu.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.224 2000/11/09 22:40:05 davem Exp $ +/* $Id: srmmu.c,v 1.225 2000/11/30 08:37:31 anton Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -51,7 +51,6 @@ unsigned int hwbug_bitmask; int vac_cache_size; int vac_line_size; -int vac_badbits; extern struct resource sparc_iomap; @@ -1286,75 +1285,6 @@ } } -static void srmmu_vac_update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ - if((vma->vm_flags & (VM_WRITE|VM_SHARED)) == (VM_WRITE|VM_SHARED)) { - struct vm_area_struct *vmaring; - struct file *file; - struct address_space *mapping; - unsigned long flags, offset, vaddr, start; - int alias_found = 0; - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - __save_and_cli(flags); - - file = vma->vm_file; - if (!file) - goto done; - mapping = file->f_dentry->d_inode->i_mapping; - offset = (address & PAGE_MASK) - vma->vm_start; - spin_lock(&mapping->i_shared_lock); - vmaring = mapping->i_mmap_shared; - if (vmaring != NULL) do { - /* Do not mistake ourselves as another mapping. */ - if(vmaring == vma) - continue; - - vaddr = vmaring->vm_start + offset; - if ((vaddr ^ address) & vac_badbits) { - alias_found++; - start = vmaring->vm_start; - while (start < vmaring->vm_end) { - pgdp = srmmu_pgd_offset(vmaring->vm_mm, start); - if(!pgdp) goto next; - pmdp = srmmu_pmd_offset(pgdp, start); - if(!pmdp) goto next; - ptep = srmmu_pte_offset(pmdp, start); - if(!ptep) goto next; - - if((pte_val(*ptep) & SRMMU_ET_MASK) == SRMMU_VALID) { -#if 0 - printk("Fixing USER/USER alias [%ld:%08lx]\n", - vmaring->vm_mm->context, start); -#endif - flush_cache_page(vmaring, start); - srmmu_set_pte(ptep, __pte((pte_val(*ptep) & - ~SRMMU_CACHE))); - flush_tlb_page(vmaring, start); - } - next: - start += PAGE_SIZE; - } - } - } while ((vmaring = vmaring->vm_next_share) != NULL); - spin_unlock(&mapping->i_shared_lock); - - if(alias_found && ((pte_val(pte) & SRMMU_CACHE) != 0)) { - pgdp = srmmu_pgd_offset(vma->vm_mm, address); - pmdp = srmmu_pmd_offset(pgdp, address); - ptep = srmmu_pte_offset(pmdp, address); - flush_cache_page(vma, address); - srmmu_set_pte(ptep, __pte((pte_val(*ptep) & ~SRMMU_CACHE))); - flush_tlb_page(vma, address); - } - done: - __restore_flags(flags); - } -} - /* Init various srmmu chip types. */ static void __init srmmu_is_bad(void) { @@ -1389,7 +1319,6 @@ } vac_cache_size = cache_lines * vac_line_size; - vac_badbits = (vac_cache_size - 1) & PAGE_MASK; #ifdef CONFIG_SMP if(vac_cache_size > max_size) max_size = vac_cache_size; @@ -1410,7 +1339,6 @@ #ifdef CONFIG_SMP vac_cache_size = max_size; vac_line_size = min_line_size; - vac_badbits = (vac_cache_size - 1) & PAGE_MASK; #endif printk("SRMMU: Using VAC size of %d bytes, line size %d bytes.\n", (int)vac_cache_size, (int)vac_line_size); @@ -1465,7 +1393,6 @@ BTFIXUPSET_CALL(flush_page_for_dma, hypersparc_flush_page_for_dma, BTFIXUPCALL_NOP); - BTFIXUPSET_CALL(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM); poke_srmmu = poke_hypersparc; hypersparc_setup_blockops(); @@ -1532,7 +1459,6 @@ 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(update_mmu_cache, srmmu_vac_update_mmu_cache, BTFIXUPCALL_NORM); poke_srmmu = poke_cypress; } diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.4.0-test11/linux/arch/sparc/mm/sun4c.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc/mm/sun4c.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.201 2000/11/09 22:39:36 davem Exp $ +/* $Id: sun4c.c,v 1.202 2000/12/01 03:17:31 anton Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -2373,78 +2373,6 @@ return freed; } -/* There are really two cases of aliases to watch out for, and these - * are: - * - * 1) A user's page which can be aliased with the kernels virtual - * mapping of the physical page. - * - * 2) Multiple user mappings of the same inode/anonymous object - * such that two copies of the same data for the same phys page - * can live (writable) in the cache at the same time. - * - * We handle number 1 by flushing the kernel copy of the page always - * after COW page operations. - * - * NOTE: We are a bit slowed down now because the VMA arg is indeed used - * now, so our ref/mod bit tracking quick userfaults eat a few more - * cycles than they used to. - */ -static void sun4c_vac_alias_fixup(struct vm_area_struct *vma, unsigned long address, pte_t pte) -{ - pgd_t *pgdp; - pte_t *ptep; - - if (vma->vm_file) { - struct address_space *mapping; - unsigned long offset = (address & PAGE_MASK) - vma->vm_start; - struct vm_area_struct *vmaring; - int alias_found = 0; - - mapping = vma->vm_file->f_dentry->d_inode->i_mapping; - spin_lock(&mapping->i_shared_lock); - vmaring = mapping->i_mmap_shared; - if (vmaring != NULL) do { - unsigned long vaddr = vmaring->vm_start + offset; - unsigned long start; - - /* Do not mistake ourselves as another mapping. */ - if (vmaring == vma) - continue; - - if (S4CVAC_BADALIAS(vaddr, address)) { - alias_found++; - start = vmaring->vm_start; - while (start < vmaring->vm_end) { - pgdp = sun4c_pgd_offset(vmaring->vm_mm, start); - if (!pgdp) - goto next; - ptep = sun4c_pte_offset((pmd_t *) pgdp, start); - if (!ptep) - goto next; - - if (pte_val(*ptep) & _SUN4C_PAGE_PRESENT) { - flush_cache_page(vmaring, start); - *ptep = __pte(pte_val(*ptep) | - _SUN4C_PAGE_NOCACHE); - flush_tlb_page(vmaring, start); - } - next: - start += PAGE_SIZE; - } - } - } while ((vmaring = vmaring->vm_next_share) != NULL); - spin_unlock(&mapping->i_shared_lock); - - 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); - pte = *ptep; - } - } -} - /* An experiment, turn off by default for now... -DaveM */ #define SUN4C_PRELOAD_PSEG @@ -2486,8 +2414,6 @@ #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 @@ -2499,9 +2425,6 @@ remove_lru(entry); add_lru(entry); } - - 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); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.0-test11/linux/arch/sparc64/kernel/sparc64_ksyms.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.98 2000/11/13 10:03:32 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.99 2000/12/09 04:15:24 anton Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -179,6 +179,7 @@ EXPORT_SYMBOL(__flushw_user); +EXPORT_SYMBOL(flush_icache_range); EXPORT_SYMBOL(__flush_dcache_page); EXPORT_SYMBOL(mstk48t02_regs); diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c --- v2.4.0-test11/linux/arch/sparc64/kernel/sys_sparc.c Tue Aug 29 14:09:15 2000 +++ linux/arch/sparc64/kernel/sys_sparc.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc.c,v 1.46 2000/08/29 07:01:54 davem Exp $ +/* $Id: sys_sparc.c,v 1.47 2000/11/29 05:56:12 anton Exp $ * linux/arch/sparc64/kernel/sys_sparc.c * * This file contains various random system calls that @@ -40,6 +40,8 @@ return PAGE_SIZE; } +#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) + unsigned long get_unmapped_area(unsigned long addr, unsigned long len) { struct vm_area_struct * vmm; @@ -51,7 +53,11 @@ return 0; if (!addr) addr = TASK_UNMAPPED_BASE; - addr = PAGE_ALIGN(addr); + + if (current->thread.flags & SPARC_FLAG_MMAPSHARED) + addr = COLOUR_ALIGN(addr); + else + addr = PAGE_ALIGN(addr); task_size -= len; @@ -66,6 +72,8 @@ if (!vmm || addr + len <= vmm->vm_start) return addr; addr = vmm->vm_end; + if (current->thread.flags & SPARC_FLAG_MMAPSHARED) + addr = COLOUR_ALIGN(addr); } } @@ -232,10 +240,15 @@ goto out_putf; } + if (flags & MAP_SHARED) + current->thread.flags |= SPARC_FLAG_MMAPSHARED; + down(¤t->mm->mmap_sem); retval = do_mmap(file, addr, len, prot, flags, off); up(¤t->mm->mmap_sem); + current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); + out_putf: if (file) fput(file); @@ -264,6 +277,7 @@ unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) { + struct vm_area_struct *vma; unsigned long ret = -EINVAL; if (current->thread.flags & SPARC_FLAG_32BIT) goto out; @@ -272,6 +286,9 @@ if (addr < PAGE_OFFSET && addr + old_len > -PAGE_OFFSET) goto out; down(¤t->mm->mmap_sem); + vma = find_vma(current->mm, addr); + if (vma && (vma->vm_flags & VM_SHARED)) + current->thread.flags |= SPARC_FLAG_MMAPSHARED; if (flags & MREMAP_FIXED) { if (new_addr < PAGE_OFFSET && new_addr + new_len > -PAGE_OFFSET) @@ -280,13 +297,14 @@ ret = -ENOMEM; if (!(flags & MREMAP_MAYMOVE)) goto out_sem; - new_addr = get_unmapped_area (addr, new_len); + new_addr = get_unmapped_area(addr, new_len); if (!new_addr) goto out_sem; flags |= MREMAP_FIXED; } ret = do_mremap(addr, old_len, new_len, flags, new_addr); out_sem: + current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); up(¤t->mm->mmap_sem); out: return ret; diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.4.0-test11/linux/arch/sparc64/kernel/sys_sparc32.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc64/kernel/sys_sparc32.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.166 2000/11/10 04:49:56 davem Exp $ +/* $Id: sys_sparc32.c,v 1.168 2000/12/11 18:59:35 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -2966,6 +2966,7 @@ err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy); + flush_dcache_page(page); flush_page_to_ram(page); kunmap(page); @@ -4133,6 +4134,7 @@ unsigned long old_len, unsigned long new_len, unsigned long flags, u32 __new_addr) { + struct vm_area_struct *vma; unsigned long ret = -EINVAL; unsigned long new_addr = AA(__new_addr); @@ -4141,6 +4143,9 @@ if (addr > 0xf0000000UL - old_len) goto out; down(¤t->mm->mmap_sem); + vma = find_vma(current->mm, addr); + if (vma && (vma->vm_flags & VM_SHARED)) + current->thread.flags |= SPARC_FLAG_MMAPSHARED; if (flags & MREMAP_FIXED) { if (new_addr > 0xf0000000UL - new_len) goto out_sem; @@ -4148,13 +4153,14 @@ ret = -ENOMEM; if (!(flags & MREMAP_MAYMOVE)) goto out_sem; - new_addr = get_unmapped_area (addr, new_len); + new_addr = get_unmapped_area(addr, new_len); if (!new_addr) goto out_sem; flags |= MREMAP_FIXED; } ret = do_mremap(addr, old_len, new_len, flags, new_addr); out_sem: + current->thread.flags &= ~(SPARC_FLAG_MMAPSHARED); up(¤t->mm->mmap_sem); out: return ret; diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.4.0-test11/linux/arch/sparc64/kernel/sys_sunos32.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc64/kernel/sys_sunos32.c Tue Nov 28 21:53:44 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sunos32.c,v 1.54 2000/08/12 13:25:41 davem Exp $ +/* $Id: sys_sunos32.c,v 1.55 2000/11/18 02:10:59 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c --- v2.4.0-test11/linux/arch/sparc64/kernel/traps.c Fri Aug 4 18:16:11 2000 +++ linux/arch/sparc64/kernel/traps.c Tue Nov 28 21:53:44 2000 @@ -1,4 +1,4 @@ -/* $Id: traps.c,v 1.67 2000/07/30 23:12:24 davem Exp $ +/* $Id: traps.c,v 1.68 2000/11/22 06:50:37 davem Exp $ * arch/sparc64/kernel/traps.c * * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) @@ -551,7 +551,7 @@ else if (fsr & 0x01) info.si_code = FPE_FLTRES; } - send_sig_info(SIGFPE, &info, current); + force_sig_info(SIGFPE, &info, current); } } @@ -594,7 +594,7 @@ info.si_code = EMT_TAGOVF; info.si_addr = (void *)regs->tpc; info.si_trapno = 0; - send_sig_info(SIGEMT, &info, current); + force_sig_info(SIGEMT, &info, current); } void do_div0(struct pt_regs *regs) @@ -606,7 +606,7 @@ info.si_code = FPE_INTDIV; info.si_addr = (void *)regs->tpc; info.si_trapno = 0; - send_sig_info(SIGFPE, &info, current); + force_sig_info(SIGFPE, &info, current); } void instruction_dump (unsigned int *pc) @@ -715,7 +715,7 @@ info.si_code = ILL_ILLOPC; info.si_addr = (void *)pc; info.si_trapno = 0; - send_sig_info(SIGILL, &info, current); + force_sig_info(SIGILL, &info, current); } void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr) @@ -734,7 +734,7 @@ info.si_code = BUS_ADRALN; info.si_addr = (void *)sfar; info.si_trapno = 0; - send_sig_info(SIGBUS, &info, current); + force_sig_info(SIGBUS, &info, current); } void do_privop(struct pt_regs *regs) @@ -746,7 +746,7 @@ info.si_code = ILL_PRVOPC; info.si_addr = (void *)regs->tpc; info.si_trapno = 0; - send_sig_info(SIGILL, &info, current); + force_sig_info(SIGILL, &info, current); } void do_privact(struct pt_regs *regs) diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.4.0-test11/linux/arch/sparc64/mm/init.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc64/mm/init.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.159 2000/11/06 06:59:04 davem Exp $ +/* $Id: init.c,v 1.161 2000/12/09 20:16:58 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -111,6 +111,17 @@ clear_bit(PG_dcache_dirty, &page->flags); } __update_mmu_cache(vma, address, pte); +} + +/* In arch/sparc64/mm/ultra.S */ +extern void __flush_icache_page(unsigned long); + +void flush_icache_range(unsigned long start, unsigned long end) +{ + unsigned long kaddr; + + for (kaddr = start; kaddr < end; kaddr += PAGE_SIZE) + __flush_icache_page(__get_phys(kaddr)); } /* diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c --- v2.4.0-test11/linux/arch/sparc64/solaris/ioctl.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc64/solaris/ioctl.c Tue Nov 28 21:53:44 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl.c,v 1.15 2000/07/28 12:15:02 davem Exp $ +/* $Id: ioctl.c,v 1.16 2000/11/18 02:10:59 davem Exp $ * ioctl.c: Solaris ioctl emulation. * * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) diff -u --recursive --new-file v2.4.0-test11/linux/arch/sparc64/solaris/socket.c linux/arch/sparc64/solaris/socket.c --- v2.4.0-test11/linux/arch/sparc64/solaris/socket.c Sun Nov 19 18:44:05 2000 +++ linux/arch/sparc64/solaris/socket.c Tue Nov 28 21:53:44 2000 @@ -1,4 +1,4 @@ -/* $Id: socket.c,v 1.3 2000/08/14 23:50:31 anton Exp $ +/* $Id: socket.c,v 1.4 2000/11/18 02:11:00 davem Exp $ * socket.c: Socket syscall emulation for Solaris 2.6+ * * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c --- v2.4.0-test11/linux/drivers/acpi/driver.c Sun Nov 19 18:44:05 2000 +++ linux/drivers/acpi/driver.c Sun Dec 10 09:53:19 2000 @@ -336,9 +336,7 @@ interruptible_sleep_on(&acpi_thread_wait); if (signal_pending(current)) break; - do { - run_task_queue(&acpi_thread_run); - } while (acpi_thread_run); + run_task_queue(&acpi_thread_run); } /* diff -u --recursive --new-file v2.4.0-test11/linux/drivers/atm/ambassador.c linux/drivers/atm/ambassador.c --- v2.4.0-test11/linux/drivers/atm/ambassador.c Thu Jul 6 21:37:24 2000 +++ linux/drivers/atm/ambassador.c Mon Dec 11 12:39:44 2000 @@ -2397,7 +2397,7 @@ #ifdef FILL_RX_POOLS_IN_BH // initialise bottom half - dev->bh.next = 0; + INIT_LIST_HEAD(&dev->bh.list); dev->bh.sync = 0; dev->bh.routine = (void (*)(void *)) fill_rx_pools; dev->bh.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c --- v2.4.0-test11/linux/drivers/block/DAC960.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/block/DAC960.c Thu Dec 7 17:08:24 2000 @@ -19,8 +19,8 @@ */ -#define DAC960_DriverVersion "2.4.8" -#define DAC960_DriverDate "19 August 2000" +#define DAC960_DriverVersion "2.4.9" +#define DAC960_DriverDate "7 September 2000" #include @@ -300,13 +300,8 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) { - DECLARE_WAITQUEUE(WaitQueueEntry, current); - add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); - current->state = TASK_UNINTERRUPTIBLE; - spin_unlock(&io_request_lock); - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); + spin_unlock_irq(&io_request_lock); + __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands); spin_lock_irq(&io_request_lock); } @@ -4957,7 +4952,8 @@ } Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].start_sect; - return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T)); + return (copy_to_user(UserGeometry, &Geometry, + sizeof(DiskGeometry_T)) ? -EFAULT : 0); case BLKGETSIZE: /* Get Device Size. */ if ((long *) Argument == NULL) return -EINVAL; @@ -5078,8 +5074,8 @@ ControllerInfo.PCI_Address = Controller->PCI_Address; strcpy(ControllerInfo.ModelName, Controller->ModelName); strcpy(ControllerInfo.FirmwareVersion, Controller->FirmwareVersion); - return copy_to_user(UserSpaceControllerInfo, &ControllerInfo, - sizeof(DAC960_ControllerInfo_T)); + return (copy_to_user(UserSpaceControllerInfo, &ControllerInfo, + sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0); } case DAC960_IOCTL_V1_EXECUTE_COMMAND: { @@ -6401,7 +6397,7 @@ unsigned char CommandBuffer[80]; int Length; if (Count > sizeof(CommandBuffer)-1) return -EINVAL; - copy_from_user(CommandBuffer, Buffer, Count); + if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT; CommandBuffer[Count] = '\0'; Length = strlen(CommandBuffer); if (CommandBuffer[Length-1] == '\n') diff -u --recursive --new-file v2.4.0-test11/linux/drivers/block/acsi.c linux/drivers/block/acsi.c --- v2.4.0-test11/linux/drivers/block/acsi.c Wed Feb 16 15:42:05 2000 +++ linux/drivers/block/acsi.c Mon Nov 27 17:57:34 2000 @@ -1785,7 +1785,7 @@ return -EBUSY; } if (!(acsi_buffer = - (char *)atari_stram_alloc( ACSI_BUFFER_SIZE, NULL, "acsi" ))) { + (char *)atari_stram_alloc(ACSI_BUFFER_SIZE, "acsi"))) { printk( KERN_ERR "Unable to get ACSI ST-Ram buffer.\n" ); devfs_unregister_blkdev( MAJOR_NR, "ad" ); return -ENOMEM; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c --- v2.4.0-test11/linux/drivers/block/ataflop.c Wed Jul 5 11:24:40 2000 +++ linux/drivers/block/ataflop.c Tue Dec 5 12:29:38 2000 @@ -317,7 +317,7 @@ static DECLARE_WAIT_QUEUE_HEAD(fdc_wait); static DECLARE_WAIT_QUEUE_HEAD(format_wait); -static unsigned int changed_floppies = 0xff, fake_change = 0; +static unsigned long changed_floppies = 0xff, fake_change = 0; #define CHECK_CHANGE_DELAY HZ/2 #define FD_MOTOR_OFF_DELAY (3*HZ) @@ -1990,7 +1990,7 @@ SelectedDrive = -1; BufferDrive = -1; - DMABuffer = atari_stram_alloc( BUFFER_SIZE+512, NULL, "ataflop" ); + DMABuffer = atari_stram_alloc(BUFFER_SIZE+512, "ataflop"); if (!DMABuffer) { printk(KERN_ERR "atari_floppy_init: cannot get dma buffer\n"); unregister_blkdev(MAJOR_NR, "fd"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.4.0-test11/linux/drivers/block/ll_rw_blk.c Sun Nov 19 18:44:06 2000 +++ linux/drivers/block/ll_rw_blk.c Mon Dec 11 13:19:35 2000 @@ -176,14 +176,15 @@ * blk_cleanup_queue: - release a &request_queue_t when it is no longer needed * @q: the request queue to be released * - * Description: blk_cleanup_queue is the pair to blk_init_queue(). It should - * be called when a request queue is being released; typically when a block - * device is being de-registered. - * Currently, its primary task it to free all the &struct request structures - * that were allocated to the queue. - * Caveat: - * Hopefully the low level driver will have finished any outstanding - * requests first... + * Description: + * blk_cleanup_queue is the pair to blk_init_queue(). It should + * be called when a request queue is being released; typically + * when a block device is being de-registered. Currently, its + * primary task it to free all the &struct request structures that + * were allocated to the queue. + * Caveat: + * Hopefully the low level driver will have finished any + * outstanding requests first... **/ void blk_cleanup_queue(request_queue_t * q) { @@ -234,19 +235,21 @@ * @plug: the function to be called to plug a queue * * Description: - * A request queue will be "plugged" if a request is added to it while it - * is empty. This allows a number of requests to be added before any are - * processed, thus providing an opportunity for these requests to be merged - * or re-ordered. - * The default plugging function (generic_plug_device()) sets the "plugged" - * flag for the queue and adds a task to the $tq_disk task queue to unplug - * the queue and call the request function at a later time. - * - * A device driver may provide an alternate plugging function by passing it to - * blk_queue_pluggable(). This function should set the "plugged" flag if it - * want calls to the request_function to be blocked, and should place a - * task on $tq_disk which will unplug the queue. Alternately it can simply - * do nothing and there-by disable plugging of the device. + * A request queue will be "plugged" if a request is added to it + * while it is empty. This allows a number of requests to be added + * before any are processed, thus providing an opportunity for these + * requests to be merged or re-ordered. + * The default plugging function (generic_plug_device()) sets the + * "plugged" flag for the queue and adds a task to the $tq_disk task + * queue to unplug the queue and call the request function at a + * later time. + * + * A device driver may provide an alternate plugging function by + * passing it to blk_queue_pluggable(). This function should set + * the "plugged" flag if it want calls to the request_function to be + * blocked, and should place a task on $tq_disk which will unplug + * the queue. Alternately it can simply do nothing and there-by + * disable plugging of the device. **/ void blk_queue_pluggable (request_queue_t * q, plug_device_fn *plug) @@ -261,14 +264,21 @@ * @mfn: the alternate make_request function * * Description: - * The normal way for &struct buffer_heads to be passed to a device driver - * it to collect into requests on a request queue, and allow the device - * driver to select requests off that queue when it is ready. This works - * well for many block devices. However some block devices (typically - * virtual devices such as md or lvm) do not benefit from the processes on - * the request queue, and are served best by having the requests passed - * directly to them. This can be achieved by providing a function to - * blk_queue_make_request(). + * The normal way for &struct buffer_heads to be passed to a device + * driver is for them to be collected into requests on a request + * queue, and then to allow the device driver to select requests + * off that queue when it is ready. This works well for many block + * devices. However some block devices (typically virtual devices + * such as md or lvm) do not benefit from the processing on the + * request queue, and are served best by having the requests passed + * directly to them. This can be achieved by providing a function + * to blk_queue_make_request(). + * + * Caveat: + * The driver that does this *must* be able to deal appropriately + * with buffers in "highmemory", either by calling bh_kmap() to get + * a kernel mapping, to by calling create_bounce() to create a + * buffer in normal memory. **/ void blk_queue_make_request(request_queue_t * q, make_request_fn * mfn) @@ -347,9 +357,10 @@ */ static inline void __generic_unplug_device(request_queue_t *q) { - if (!list_empty(&q->queue_head)) { + if (q->plugged) { q->plugged = 0; - q->request_fn(q); + if (!list_empty(&q->queue_head)) + q->request_fn(q); } } @@ -383,6 +394,8 @@ spin_lock_init(&q->request_lock); } +static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh); + /** * blk_init_queue - prepare a request queue for use with a block device * @q: The &request_queue_t to be initialised @@ -416,7 +429,6 @@ * blk_init_queue() must be paired with a blk_cleanup-queue() call * when the block device is deactivated (such as at module unload). **/ -static int __make_request(request_queue_t * q, int rw, struct buffer_head * bh); void blk_init_queue(request_queue_t * q, request_fn_proc * rfn) { INIT_LIST_HEAD(&q->queue_head); @@ -635,7 +647,10 @@ next = blkdev_next_request(req); if (req->sector + req->nr_sectors != next->sector) return; - if (req->cmd != next->cmd || req->rq_dev != next->rq_dev || req->nr_sectors + next->nr_sectors > max_sectors || next->sem) + if (req->cmd != next->cmd + || req->rq_dev != next->rq_dev + || req->nr_sectors + next->nr_sectors > max_sectors + || next->sem) return; /* * If we are not allowed to merge these requests, then @@ -684,7 +699,7 @@ int max_segments = MAX_SEGMENTS; struct request * req = NULL, *freereq = NULL; int rw_ahead, max_sectors, el_ret; - struct list_head *head = &q->queue_head; + struct list_head *head; int latency; elevator_t *elevator = &q->elevator; @@ -738,6 +753,7 @@ /* * skip first entry, for devices with active queue head */ + head = &q->queue_head; if (q->head_active && !q->plugged) head = head->next; @@ -746,7 +762,8 @@ goto get_rq; } - el_ret = elevator->elevator_merge_fn(q, &req, bh, rw, &max_sectors, &max_segments); + el_ret = elevator->elevator_merge_fn(q, &req, bh, rw, + &max_sectors, &max_segments); switch (el_ret) { case ELEVATOR_BACK_MERGE: @@ -830,6 +847,40 @@ return 0; } +/** + * generic_make_request: hand a buffer head to it's device driver for I/O + * @rw: READ, WRITE, or READA - what sort of I/O is desired. + * @bh: The buffer head describing the location in memory and on the device. + * + * generic_make_request() is used to make I/O requests of block + * devices. It is passed a &struct buffer_head and a &rw value. The + * %READ and %WRITE options are (hopefully) obvious in meaning. The + * %READA value means that a read is required, but that the driver is + * free to fail the request if, for example, it cannot get needed + * resources immediately. + * + * generic_make_request() does not return any status. The + * success/failure status of the request, along with notification of + * completion, is delivered asynchronously through the bh->b_end_io + * function described (one day) else where. + * + * The caller of generic_make_request must make sure that b_page, + * b_addr, b_size are set to describe the memory buffer, that b_rdev + * and b_rsector are set to describe the device address, and the + * b_end_io and optionally b_private are set to describe how + * completion notification should be signaled. BH_Mapped should also + * be set (to confirm that b_dev and b_blocknr are valid). + * + * generic_make_request and the drivers it calls may use b_reqnext, + * and may change b_rdev and b_rsector. So the values of these fields + * should NOT be depended on after the call to generic_make_request. + * Because of this, the caller should record the device address + * information in b_dev and b_blocknr. + * + * Apart from those fields mentioned above, no other fields, and in + * particular, no other flags, are changed by generic_make_request or + * any lower level drivers. + * */ void generic_make_request (int rw, struct buffer_head * bh) { int major = MAJOR(bh->b_rdev); @@ -882,9 +933,76 @@ while (q->make_request_fn(q, rw, bh)); } -/* This function can be used to request a number of buffers from a block - device. Currently the only restriction is that all buffers must belong to - the same device */ + +/** + * submit_bh: submit a buffer_head to the block device later for I/O + * @rw: whether to %READ or %WRITE, or mayve to %READA (read ahead) + * @bh: The &struct buffer_head which describes the I/O + * + * submit_bh() is very similar in purpose to generic_make_request(), and + * uses that function to do most of the work. + * + * The extra functionality provided by submit_bh is to determine + * b_rsector from b_blocknr and b_size, and to set b_rdev from b_dev. + * This is is appropriate for IO requests that come from the buffer + * cache and page cache which (currently) always use aligned blocks. + */ +void submit_bh(int rw, struct buffer_head * bh) +{ + if (!test_bit(BH_Lock, &bh->b_state)) + BUG(); + + set_bit(BH_Req, &bh->b_state); + + /* + * First step, 'identity mapping' - RAID or LVM might + * further remap this. + */ + bh->b_rdev = bh->b_dev; + bh->b_rsector = bh->b_blocknr * (bh->b_size>>9); + + generic_make_request(rw, bh); +} + +/* + * Default IO end handler, used by "ll_rw_block()". + */ +static void end_buffer_io_sync(struct buffer_head *bh, int uptodate) +{ + mark_buffer_uptodate(bh, uptodate); + unlock_buffer(bh); +} + +/** + * ll_rw_block: low-level access to block devices + * @rw: whether to %READ or %WRITE or maybe %READA (readahead) + * @nr: number of &struct buffer_heads in the array + * @bhs: array of pointers to &struct buffer_head + * + * ll_rw_block() takes an array of pointers to &struct buffer_heads, + * and requests an I/O operation on them, either a %READ or a %WRITE. + * The third %READA option is described in the documentation for + * generic_make_request() which ll_rw_block() calls. + * + * This function provides extra functionality that is not in + * generic_make_request() that is relevant to buffers in the buffer + * cache or page cache. In particular it drops any buffer that it + * cannot get a lock on (with the BH_Lock state bit), any buffer that + * appears to be clean when doing a write request, and any buffer that + * appears to be up-to-date when doing read request. Further it marks + * as clean buffers that are processed for writing (the buffer cache + * wont assume that they are actually clean until the buffer gets + * unlocked). + * + * ll_rw_block sets b_end_io to simple completion handler that marks + * the buffer up-to-date (if approriate), unlocks the buffer and wakes + * any waiters. As client that needs a more interesting completion + * routine should call submit_bh() (or generic_make_request()) + * directly. + * + * Caveat: + * All of the buffers must be for the same device, and must also be + * of the current approved size for the device. */ void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]) { @@ -928,7 +1046,8 @@ if (test_and_set_bit(BH_Lock, &bh->b_state)) continue; - set_bit(BH_Req, &bh->b_state); + /* We have the buffer lock */ + bh->b_end_io = end_buffer_io_sync; switch(rw) { case WRITE: @@ -951,17 +1070,9 @@ end_io: bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); continue; - } - /* - * First step, 'identity mapping' - RAID or LVM might - * further remap this. - */ - bh->b_rdev = bh->b_dev; - bh->b_rsector = bh->b_blocknr * (bh->b_size>>9); - - generic_make_request(rw, bh); + submit_bh(rw, bh); } return; @@ -969,7 +1080,6 @@ for (i = 0; i < nr; i++) buffer_IO_error(bhs[i]); } - #ifdef CONFIG_STRAM_SWAP extern int stram_device_init (void); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/block/paride/pseudo.h linux/drivers/block/paride/pseudo.h --- v2.4.0-test11/linux/drivers/block/paride/pseudo.h Wed May 3 01:45:17 2000 +++ linux/drivers/block/paride/pseudo.h Mon Dec 11 12:58:14 2000 @@ -50,7 +50,7 @@ static spinlock_t ps_spinlock __attribute__((unused)) = SPIN_LOCK_UNLOCKED; static struct timer_list ps_timer = { function: ps_timer_int }; -static struct tq_struct ps_tq = {0,0,ps_tq_int,NULL}; +static struct tq_struct ps_tq = { routine: ps_tq_int }; static void ps_set_intr( void (*continuation)(void), int (*ready)(void), @@ -71,7 +71,7 @@ disable_hlt(); #endif ps_tq_active = 1; - queue_task(&ps_tq,&tq_scheduler); + schedule_task(&ps_tq); } if (!ps_timer_active) { @@ -114,7 +114,7 @@ #endif ps_tq_active = 1; - queue_task(&ps_tq,&tq_scheduler); + schedule_task(&ps_tq); spin_unlock_irqrestore(&ps_spinlock,flags); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c --- v2.4.0-test11/linux/drivers/block/z2ram.c Wed Jul 5 13:15:19 2000 +++ linux/drivers/block/z2ram.c Mon Nov 27 17:11:26 2000 @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -201,8 +202,6 @@ #ifdef __powerpc__ /* FIXME: ioremap doesn't build correct memory tables. */ { - extern void* vmalloc (unsigned long); - extern void vfree (void*); vfree(vmalloc (size)); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/Makefile linux/drivers/char/Makefile --- v2.4.0-test11/linux/drivers/char/Makefile Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/Makefile Mon Nov 27 17:11:26 2000 @@ -131,6 +131,9 @@ obj-$(CONFIG_SX) += sx.o generic_serial.o obj-$(CONFIG_RIO) += rio/rio.o generic_serial.o obj-$(CONFIG_SH_SCI) += sh-sci.o generic_serial.o +obj-$(CONFIG_SERIAL167) += serial167.o +obj-$(CONFIG_MVME162_SCC) += generic_serial.o vme_scc.o +obj-$(CONFIG_BVME6000_SCC) += generic_serial.o vme_scc.o ifeq ($(CONFIG_RIO),y) SUB_DIRS += rio diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/README.epca linux/drivers/char/README.epca --- v2.4.0-test11/linux/drivers/char/README.epca Fri Mar 10 10:48:47 2000 +++ linux/drivers/char/README.epca Wed Dec 6 12:06:18 2000 @@ -495,7 +495,7 @@ Programmer : Daniel Taylor Date : April 25, 1997 Description (Verbose) : Updated driver: - 1. Fixed DCD bug. (&tq_scheduler) + 1. Fixed DCD bug. (&tq scheduler) 2. Removed BH handler code, as it was only handling hangups, and not being called for that. 3. Namespace cleanup (DIGI_TIMER2 => DIGI_TIMER) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/adbmouse.c linux/drivers/char/adbmouse.c --- v2.4.0-test11/linux/drivers/char/adbmouse.c Tue Jun 20 07:25:51 2000 +++ linux/drivers/char/adbmouse.c Sun Dec 3 17:48:19 2000 @@ -53,7 +53,6 @@ extern int adb_emulate_buttons; extern int adb_button2_keycode; extern int adb_button3_keycode; -extern int console_loglevel; /* * XXX: need to figure out what ADB mouse packets mean ... diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/amigamouse.c linux/drivers/char/amigamouse.c --- v2.4.0-test11/linux/drivers/char/amigamouse.c Mon Jun 19 13:45:52 2000 +++ linux/drivers/char/amigamouse.c Mon Nov 27 17:11:26 2000 @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -185,6 +186,8 @@ { if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) return -ENODEV; + if (!request_mem_region(CUSTOM_PHYSADDR+10, 2, "amigamouse [Denise]")) + return -EBUSY; custom.joytest = 0; /* reset counters */ #if AMIGA_OLD_INT @@ -201,6 +204,7 @@ static void __exit amiga_mouse_exit(void) { unregister_busmouse(msedev); + release_mem_region(CUSTOM_PHYSADDR+10, 2); } module_init(amiga_mouse_init); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/amikeyb.c linux/drivers/char/amikeyb.c --- v2.4.0-test11/linux/drivers/char/amikeyb.c Fri Jul 14 12:20:22 2000 +++ linux/drivers/char/amikeyb.c Mon Nov 27 17:57:34 2000 @@ -12,6 +12,7 @@ * Amiga support by Hamish Macdonald */ +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #include @@ -186,7 +188,6 @@ kbd_pt_regs = NULL; - init_timer(&amikeyb_rep_timer); amikeyb_rep_timer.expires = jiffies + key_repeat_rate; add_timer(&amikeyb_rep_timer); handle_scancode(rep_scancode, 1); @@ -254,7 +255,6 @@ } else { del_timer(&amikeyb_rep_timer); rep_scancode = keycode; - init_timer(&amikeyb_rep_timer); amikeyb_rep_timer.expires = jiffies + key_repeat_delay; add_timer(&amikeyb_rep_timer); } @@ -300,6 +300,8 @@ { if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) return -EIO; + if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) + return -EBUSY; /* setup key map */ memcpy(key_maps[0], amiplain_map, sizeof(plain_map)); @@ -342,3 +344,16 @@ return( 0 ); } + +int amiga_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) +{ +#ifdef CONFIG_MAGIC_SYSRQ + /* SHIFT+ALTGR+HELP pressed? */ + if ((keycode == 0x5f) && ((shift_state & 0xff) == 3)) + *keycodep = 0xff; + else +#endif + *keycodep = keycode; + return 1; +} + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/applicom.c linux/drivers/char/applicom.c --- v2.4.0-test11/linux/drivers/char/applicom.c Wed Jul 12 21:58:42 2000 +++ linux/drivers/char/applicom.c Sun Dec 3 17:45:20 2000 @@ -63,8 +63,8 @@ #define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001 #define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002 #define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003 -#define MAX_PCI_DEVICE_NUM 3 #endif +#define MAX_PCI_DEVICE_NUM 3 static char *applicom_pci_devnames[] = { "PCI board", diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/drm/gamma_dma.c linux/drivers/char/drm/gamma_dma.c --- v2.4.0-test11/linux/drivers/char/drm/gamma_dma.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/gamma_dma.c Mon Dec 11 12:39:44 2000 @@ -651,7 +651,7 @@ dev->dma->next_queue = NULL; dev->dma->this_buffer = NULL; - dev->tq.next = NULL; + INIT_LIST_HEAD(&dev->tq.list); dev->tq.sync = 0; dev->tq.routine = gamma_dma_schedule_tq_wrapper; dev->tq.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/drm/i810_dma.c linux/drivers/char/drm/i810_dma.c --- v2.4.0-test11/linux/drivers/char/drm/i810_dma.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/i810_dma.c Mon Dec 11 12:39:44 2000 @@ -924,7 +924,7 @@ dev->dma->next_queue = NULL; dev->dma->this_buffer = NULL; - dev->tq.next = NULL; + INIT_LIST_HEAD(&dev->tq.list); dev->tq.sync = 0; dev->tq.routine = i810_dma_task_queue; dev->tq.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/drm/mga_dma.c linux/drivers/char/drm/mga_dma.c --- v2.4.0-test11/linux/drivers/char/drm/mga_dma.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/mga_dma.c Mon Dec 11 12:39:44 2000 @@ -143,7 +143,7 @@ unsigned long end; int i; - DRM_DEBUG("dispatch_status = 0x%02x\n", dev_priv->dispatch_status); + DRM_DEBUG("dispatch_status = 0x%02lx\n", dev_priv->dispatch_status); end = jiffies + (HZ*3); while(1) { if(!test_and_set_bit(MGA_IN_DISPATCH, @@ -154,7 +154,7 @@ DRM_ERROR("irqs: %d wanted %d\n", atomic_read(&dev->total_irq), atomic_read(&dma->total_lost)); - DRM_ERROR("lockup: dispatch_status = 0x%02x," + DRM_ERROR("lockup: dispatch_status = 0x%02lx," " jiffies = %lu, end = %lu\n", dev_priv->dispatch_status, jiffies, end); return; @@ -177,7 +177,7 @@ sarea_priv->dirty |= MGA_DMA_FLUSH; clear_bit(MGA_IN_DISPATCH, &dev_priv->dispatch_status); - DRM_DEBUG("exit, dispatch_status = 0x%02x\n", + DRM_DEBUG("exit, dispatch_status = 0x%02lx\n", dev_priv->dispatch_status); } @@ -818,7 +818,7 @@ dev->dma->next_buffer = NULL; dev->dma->next_queue = NULL; dev->dma->this_buffer = NULL; - dev->tq.next = NULL; + INIT_LIST_HEAD(&dev->tq.list); dev->tq.sync = 0; dev->tq.routine = mga_dma_task_queue; dev->tq.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/drm/mga_drv.c linux/drivers/char/drm/mga_drv.c --- v2.4.0-test11/linux/drivers/char/drm/mga_drv.c Sun Nov 19 18:44:06 2000 +++ linux/drivers/char/drm/mga_drv.c Sun Dec 3 17:45:21 2000 @@ -502,7 +502,7 @@ if (dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && dev->lock.pid == current->pid) { mga_reclaim_buffers(dev, priv->pid); - DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02x)\n", + DRM_INFO("Process %d dead (ctx %d, d_s = 0x%02lx)\n", current->pid, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock), dev->dev_private ? diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/drm/mga_drv.h linux/drivers/char/drm/mga_drv.h --- v2.4.0-test11/linux/drivers/char/drm/mga_drv.h Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/mga_drv.h Sun Dec 3 17:45:21 2000 @@ -38,7 +38,7 @@ #define MGA_BUF_NEEDS_OVERFLOW 3 typedef struct { - u32 buffer_status; + long buffer_status; /* long req'd for set_bit() --RR */ int num_dwords; int max_dwords; u32 *current_dma_ptr; @@ -62,7 +62,7 @@ #define MGA_IN_GETBUF 3 typedef struct _drm_mga_private { - u32 dispatch_status; + long dispatch_status; /* long req'd for set_bit() --RR */ unsigned int next_prim_age; __volatile__ unsigned int last_prim_age; int reserved_map_idx; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/epca.c linux/drivers/char/epca.c --- v2.4.0-test11/linux/drivers/char/epca.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/epca.c Wed Dec 6 12:06:18 2000 @@ -483,7 +483,9 @@ -------------------------------------------------------------------------*/ ch->event |= 1 << event; - queue_task(&ch->tqueue, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&ch->tqueue) == 0) + MOD_DEC_USE_COUNT; } /* End pc_sched_event */ @@ -3435,7 +3437,7 @@ if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { /* Begin if clear_bit */ - tty_hangup(tty); + tty_hangup(tty); /* FIXME: module removal race here - AKPM */ wake_up_interruptible(&ch->open_wait); ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); @@ -3443,7 +3445,7 @@ } } /* End EPCA_MAGIC */ - + MOD_DEC_USE_COUNT; } /* End do_softint */ /* ------------------------------------------------------------ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/esp.c linux/drivers/char/esp.c --- v2.4.0-test11/linux/drivers/char/esp.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/esp.c Wed Dec 6 12:06:18 2000 @@ -640,7 +640,9 @@ #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif - queue_task(&info->tqueue_hangup, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&info->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; } } } @@ -802,10 +804,9 @@ struct tty_struct *tty; tty = info->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); + MOD_DEC_USE_COUNT; } /* diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/isicom.c linux/drivers/char/isicom.c --- v2.4.0-test11/linux/drivers/char/isicom.c Tue Jun 20 07:32:13 2000 +++ linux/drivers/char/isicom.c Wed Dec 6 12:06:18 2000 @@ -582,9 +582,11 @@ #endif port->status &= ~ISI_DCD; if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && - (port->flags & ASYNC_CALLOUT_NOHUP))) - queue_task(&port->hangup_tq, - &tq_scheduler); + (port->flags & ASYNC_CALLOUT_NOHUP))) { + MOD_INC_USE_COUNT; + if (schedule_task(&port->hangup_tq) == 0) + MOD_DEC_USE_COUNT; + } } } else { @@ -1630,10 +1632,9 @@ struct tty_struct * tty; tty = port->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); /* FIXME: module removal race here - AKPM */ + MOD_DEC_USE_COUNT; } static void isicom_hangup(struct tty_struct * tty) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/istallion.c linux/drivers/char/istallion.c --- v2.4.0-test11/linux/drivers/char/istallion.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/istallion.c Wed Dec 6 12:06:18 2000 @@ -2363,12 +2363,18 @@ printk("stli_dohangup(portp=%x)\n", (int) arg); #endif + /* + * FIXME: There's a module removal race here: tty_hangup + * calls schedule_task which will call into this + * driver later. + */ portp = (stliport_t *) arg; - if (portp == (stliport_t *) NULL) - return; - if (portp->tty == (struct tty_struct *) NULL) - return; - tty_hangup(portp->tty); + if (portp != (stliport_t *) NULL) { + if (portp->tty != (struct tty_struct *) NULL) { + tty_hangup(portp->tty); + } + } + MOD_DEC_USE_COUNT; } /*****************************************************************************/ @@ -2999,8 +3005,11 @@ if (portp->flags & ASYNC_CHECK_CD) { if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) && (portp->flags & ASYNC_CALLOUT_NOHUP))) { - if (tty != (struct tty_struct *) NULL) - queue_task(&portp->tqhangup, &tq_scheduler); + if (tty != (struct tty_struct *) NULL) { + MOD_INC_USE_COUNT; + if (schedule_task(&portp->tqhangup) == 0) + MOD_DEC_USE_COUNT; + } } } } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/mixcomwd.c linux/drivers/char/mixcomwd.c --- v2.4.0-test11/linux/drivers/char/mixcomwd.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/mixcomwd.c Sun Dec 3 17:45:21 2000 @@ -54,7 +54,7 @@ #define FLASHCOM_WATCHDOG_OFFSET 0x4 #define FLASHCOM_ID 0x18 -static int mixcomwd_opened; +static long mixcomwd_opened; /* long req'd for setbit --RR */ static int watchdog_port; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/moxa.c linux/drivers/char/moxa.c --- v2.4.0-test11/linux/drivers/char/moxa.c Wed May 3 01:45:18 2000 +++ linux/drivers/char/moxa.c Wed Dec 6 12:06:18 2000 @@ -152,7 +152,7 @@ unsigned short closing_wait; int count; int blocked_open; - int event; + long event; /* long req'd for set_bit --RR */ int asyncflags; long session; long pgrp; @@ -540,13 +540,14 @@ struct moxa_str *ch = (struct moxa_str *) private_; struct tty_struct *tty; - if (!ch || !(tty = ch->tty)) - return; - if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) { - tty_hangup(tty); - wake_up_interruptible(&ch->open_wait); - ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); + if (ch && (tty = ch->tty)) { + if (test_and_clear_bit(MOXA_EVENT_HANGUP, &ch->event)) { + tty_hangup(tty); /* FIXME: module removal race here - AKPM */ + wake_up_interruptible(&ch->open_wait); + ch->asyncflags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE); + } } + MOD_DEC_USE_COUNT; } static int moxa_open(struct tty_struct *tty, struct file *filp) @@ -1013,7 +1014,9 @@ wake_up_interruptible(&ch->open_wait); else { set_bit(MOXA_EVENT_HANGUP, &ch->event); - queue_task(&ch->tqueue, &tq_scheduler); + MOD_DEC_USE_COUNT; + if (schedule_task(&ch->tqueue) == 0) + MOD_INC_USE_COUNT; } } } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/mxser.c linux/drivers/char/mxser.c --- v2.4.0-test11/linux/drivers/char/mxser.c Sun Nov 19 18:44:06 2000 +++ linux/drivers/char/mxser.c Wed Dec 6 12:06:18 2000 @@ -690,17 +690,18 @@ struct tty_struct *tty; tty = info->tty; - if (!tty) - return; - if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) { - if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && - tty->ldisc.write_wakeup) - (tty->ldisc.write_wakeup) (tty); - wake_up_interruptible(&tty->write_wait); - } - if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) { - tty_hangup(tty); + if (tty) { + if (test_and_clear_bit(MXSER_EVENT_TXLOW, &info->event)) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup) (tty); + wake_up_interruptible(&tty->write_wait); + } + if (test_and_clear_bit(MXSER_EVENT_HANGUP, &info->event)) { + tty_hangup(tty); /* FIXME: module removal race here - AKPM */ + } } + MOD_DEC_USE_COUNT; } /* @@ -1456,7 +1457,7 @@ if (info->xmit_cnt < WAKEUP_CHARS) { set_bit(MXSER_EVENT_TXLOW, &info->event); - queue_task(&info->tqueue, &tq_scheduler); + schedule_task(&info->tqueue); } if (info->xmit_cnt <= 0) { info->IER &= ~UART_IER_THRI; @@ -1485,7 +1486,7 @@ else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && (info->flags & ASYNC_CALLOUT_NOHUP))) set_bit(MXSER_EVENT_HANGUP, &info->event); - queue_task(&info->tqueue, &tq_scheduler); + schedule_task(&info->tqueue); } if (info->flags & ASYNC_CTS_FLOW) { @@ -1496,7 +1497,9 @@ outb(info->IER, info->base + UART_IER); set_bit(MXSER_EVENT_TXLOW, &info->event); - queue_task(&info->tqueue, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&info->tqueue) == 0) + MOD_DEC_USE_COUNT; } } else { if (!(status & UART_MSR_CTS)) { diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c --- v2.4.0-test11/linux/drivers/char/n_r3964.c Fri Jul 21 19:51:56 2000 +++ linux/drivers/char/n_r3964.c Mon Dec 11 12:57:28 2000 @@ -1157,12 +1157,12 @@ * Add 'on_timer' to timer task queue * (will be called from timer bh) */ - pInfo->bh_1.next = NULL; + INIT_LIST_HEAD(&pInfo->bh_1.list); pInfo->bh_1.sync = 0; pInfo->bh_1.routine = &on_timer_1; pInfo->bh_1.data = pInfo; - pInfo->bh_2.next = NULL; + INIT_LIST_HEAD(&pInfo->bh_2.list); pInfo->bh_2.sync = 0; pInfo->bh_2.routine = &on_timer_2; pInfo->bh_2.data = pInfo; @@ -1174,7 +1174,6 @@ static void r3964_close(struct tty_struct *tty) { - struct tq_struct *tq, *prev; struct r3964_info *pInfo=(struct r3964_info*)tty->disc_data; struct r3964_client_info *pClient, *pNext; struct r3964_message *pMsg; @@ -1187,19 +1186,12 @@ * Make sure that our task queue isn't activated. If it * is, take it out of the linked list. */ - save_flags(flags); - cli(); - - for (tq=tq_timer, prev=0; tq; prev=tq, tq=tq->next) { - if ((tq == &pInfo->bh_1) || (tq==&pInfo->bh_2)) { - if (prev) - prev->next = tq->next; - else - tq_timer = tq->next; - break; - } - } - restore_flags(flags); + spin_lock_irqsave(&tqueue_lock, flags); + if (pInfo->bh_1.sync) + list_del(&pInfo->bh_1.list); + if (pInfo->bh_2.sync) + list_del(&pInfo->bh_2.list); + spin_unlock_irqrestore(&tqueue_lock, flags); /* Remove client-structs and message queues: */ pClient=pInfo->firstClient; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/q40_keyb.c linux/drivers/char/q40_keyb.c --- v2.4.0-test11/linux/drivers/char/q40_keyb.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/q40_keyb.c Mon Nov 27 17:57:34 2000 @@ -10,10 +10,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -342,7 +344,6 @@ { unsigned char status; - disable_keyboard(); spin_lock(&kbd_controller_lock); kbd_pt_regs = regs; @@ -378,8 +379,7 @@ handle_scancode(scancode, ! keyup ); keyup=0; - mark_bh(KEYBOARD_BH); - + tasklet_schedule(&keyboard_tasklet); } else keyup=1; @@ -387,20 +387,7 @@ exit: spin_unlock(&kbd_controller_lock); master_outb(-1,KEYBOARD_UNLOCK_REG); /* keyb ints reenabled herewith */ - enable_keyboard(); -} - - - - -#ifdef CONFIG_MAGIC_SYSRQ -int kbd_is_sysrq(unsigned char keycode) -{ - return( keycode == SYSRQ_KEY ); } -#endif /* CONFIG_MAGIC_SYSRQ */ - - #define KBD_NO_DATA (-1) /* No data */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/rio/host.h linux/drivers/char/rio/host.h --- v2.4.0-test11/linux/drivers/char/rio/host.h Sat May 20 10:51:00 2000 +++ linux/drivers/char/rio/host.h Sun Dec 3 17:45:21 2000 @@ -110,7 +110,7 @@ struct UnixRup UnixRups[MAX_RUP+LINKS_PER_UNIT]; int timeout_id; /* For calling 100 ms delays */ int timeout_sem;/* For calling 100 ms delays */ - int locks; + long locks; /* long req'd for set_bit --RR */ char ____end_marker____; }; #define Control CardP->DpControl diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c --- v2.4.0-test11/linux/drivers/char/riscom8.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/riscom8.c Wed Dec 6 12:06:18 2000 @@ -77,7 +77,7 @@ #define RS_EVENT_WRITE_WAKEUP 0 -DECLARE_TASK_QUEUE(tq_riscom); +static DECLARE_TASK_QUEUE(tq_riscom); #define RISCOM_TYPE_NORMAL 1 #define RISCOM_TYPE_CALLOUT 2 @@ -146,38 +146,38 @@ */ /* Get board number from pointer */ -extern inline int board_No (struct riscom_board const * bp) +static inline int board_No (struct riscom_board const * bp) { return bp - rc_board; } /* Get port number from pointer */ -extern inline int port_No (struct riscom_port const * port) +static inline int port_No (struct riscom_port const * port) { return RC_PORT(port - rc_port); } /* Get pointer to board from pointer to port */ -extern inline struct riscom_board * port_Board(struct riscom_port const * port) +static inline struct riscom_board * port_Board(struct riscom_port const * port) { return &rc_board[RC_BOARD(port - rc_port)]; } /* Input Byte from CL CD180 register */ -extern inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg) +static inline unsigned char rc_in(struct riscom_board const * bp, unsigned short reg) { return inb(bp->base + RC_TO_ISA(reg)); } /* Output Byte to CL CD180 register */ -extern inline void rc_out(struct riscom_board const * bp, unsigned short reg, +static inline void rc_out(struct riscom_board const * bp, unsigned short reg, unsigned char val) { outb(val, bp->base + RC_TO_ISA(reg)); } /* Wait for Channel Command Register ready */ -extern inline void rc_wait_CCR(struct riscom_board const * bp) +static inline void rc_wait_CCR(struct riscom_board const * bp) { unsigned long delay; @@ -193,7 +193,7 @@ * RISCom/8 probe functions. */ -extern inline int rc_check_io_range(struct riscom_board * const bp) +static inline int rc_check_io_range(struct riscom_board * const bp) { int i; @@ -206,7 +206,7 @@ return 0; } -extern inline void rc_request_io_range(struct riscom_board * const bp) +static inline void rc_request_io_range(struct riscom_board * const bp) { int i; @@ -214,7 +214,7 @@ request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1, "RISCom/8" ); } -extern inline void rc_release_io_range(struct riscom_board * const bp) +static inline void rc_release_io_range(struct riscom_board * const bp) { int i; @@ -224,7 +224,7 @@ /* Must be called with enabled interrupts */ -extern inline void rc_long_delay(unsigned long delay) +static inline void rc_long_delay(unsigned long delay) { unsigned long i; @@ -326,7 +326,7 @@ * */ -extern inline void rc_mark_event(struct riscom_port * port, int event) +static inline void rc_mark_event(struct riscom_port * port, int event) { /* * I'm not quite happy with current scheme all serial @@ -341,7 +341,7 @@ mark_bh(RISCOM8_BH); } -extern inline struct riscom_port * rc_get_port(struct riscom_board const * bp, +static inline struct riscom_port * rc_get_port(struct riscom_board const * bp, unsigned char const * what) { unsigned char channel; @@ -359,7 +359,7 @@ return NULL; } -extern inline void rc_receive_exc(struct riscom_board const * bp) +static inline void rc_receive_exc(struct riscom_board const * bp) { struct riscom_port *port; struct tty_struct *tty; @@ -422,7 +422,7 @@ queue_task(&tty->flip.tqueue, &tq_timer); } -extern inline void rc_receive(struct riscom_board const * bp) +static inline void rc_receive(struct riscom_board const * bp) { struct riscom_port *port; struct tty_struct *tty; @@ -452,7 +452,7 @@ queue_task(&tty->flip.tqueue, &tq_timer); } -extern inline void rc_transmit(struct riscom_board const * bp) +static inline void rc_transmit(struct riscom_board const * bp) { struct riscom_port *port; struct tty_struct *tty; @@ -521,7 +521,7 @@ rc_mark_event(port, RS_EVENT_WRITE_WAKEUP); } -extern inline void rc_check_modem(struct riscom_board const * bp) +static inline void rc_check_modem(struct riscom_board const * bp) { struct riscom_port *port; struct tty_struct *tty; @@ -537,8 +537,11 @@ if (rc_in(bp, CD180_MSVR) & MSVR_CD) wake_up_interruptible(&port->open_wait); else if (!((port->flags & ASYNC_CALLOUT_ACTIVE) && - (port->flags & ASYNC_CALLOUT_NOHUP))) - queue_task(&port->tqueue_hangup, &tq_scheduler); + (port->flags & ASYNC_CALLOUT_NOHUP))) { + MOD_INC_USE_COUNT; + if (schedule_task(&port->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; + } } #ifdef RISCOM_BRAIN_DAMAGED_CTS @@ -634,7 +637,7 @@ */ /* Called with disabled interrupts */ -extern inline int rc_setup_board(struct riscom_board * bp) +static inline int rc_setup_board(struct riscom_board * bp) { int error; @@ -657,7 +660,7 @@ } /* Called with disabled interrupts */ -extern inline void rc_shutdown_board(struct riscom_board *bp) +static inline void rc_shutdown_board(struct riscom_board *bp) { if (!(bp->flags & RC_BOARD_ACTIVE)) return; @@ -1399,7 +1402,7 @@ return 0; } -extern inline void rc_send_break(struct riscom_port * port, unsigned long length) +static inline void rc_send_break(struct riscom_port * port, unsigned long length) { struct riscom_board *bp = port_Board(port); unsigned long flags; @@ -1417,7 +1420,7 @@ restore_flags(flags); } -extern inline int rc_set_serial_info(struct riscom_port * port, +static inline int rc_set_serial_info(struct riscom_port * port, struct serial_struct * newinfo) { struct serial_struct tmp; @@ -1467,7 +1470,7 @@ return 0; } -extern inline int rc_get_serial_info(struct riscom_port * port, +static inline int rc_get_serial_info(struct riscom_port * port, struct serial_struct * retinfo) { struct serial_struct tmp; @@ -1648,10 +1651,9 @@ struct tty_struct *tty; tty = port->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); /* FIXME: module removal race still here */ + MOD_DEC_USE_COUNT; } static void rc_hangup(struct tty_struct * tty) @@ -1820,7 +1822,7 @@ * addresses in this case. * */ -void __init riscom8_setup(char *str, int * ints) +static void __init riscom8_setup(char *str, int * ints) { int i; @@ -1831,12 +1833,14 @@ rc_board[i].base = 0; } } + +__setup("riscom8=", riscom8_setup); #endif /* * This routine must be called by kernel at boot time */ -int __init riscom8_init(void) +static int __init riscom8_init(void) { int i; int found = 0; @@ -1859,22 +1863,24 @@ } #ifdef MODULE -int iobase = 0; -int iobase1 = 0; -int iobase2 = 0; -int iobase3 = 0; +static int iobase; +static int iobase1; +static int iobase2; +static int iobase3; MODULE_PARM(iobase, "i"); MODULE_PARM(iobase1, "i"); MODULE_PARM(iobase2, "i"); MODULE_PARM(iobase3, "i"); +#endif /* MODULE */ /* * You can setup up to 4 boards (current value of RC_NBOARD) * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter. * */ -int init_module(void) +static int __init riscom8_init_module (void) { +#ifdef MODULE int i; if (iobase || iobase1 || iobase2 || iobase3) { @@ -1890,11 +1896,12 @@ rc_board[2].base = iobase2; if (iobase3) rc_board[3].base = iobase3; - +#endif /* MODULE */ + return riscom8_init(); } -void cleanup_module(void) +static void __exit riscom8_exit_module (void) { int i; @@ -1904,4 +1911,7 @@ rc_release_io_range(&rc_board[i]); } -#endif /* MODULE */ + +module_init(riscom8_init_module); +module_exit(riscom8_exit_module); + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/riscom8.h linux/drivers/char/riscom8.h --- v2.4.0-test11/linux/drivers/char/riscom8.h Wed May 12 13:27:37 1999 +++ linux/drivers/char/riscom8.h Mon Dec 11 12:52:13 2000 @@ -71,7 +71,7 @@ struct tty_struct * tty; int count; int blocked_open; - int event; + long event; /* long req'd for set_bit --RR */ int timeout; int close_delay; long session; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/scan_keyb.c linux/drivers/char/scan_keyb.c --- v2.4.0-test11/linux/drivers/char/scan_keyb.c Fri Aug 11 15:57:57 2000 +++ linux/drivers/char/scan_keyb.c Mon Dec 11 12:39:44 2000 @@ -120,7 +120,7 @@ void __init scan_kbd_init(void) { - task_scan_kbd.next=NULL; + INIT_LIST_HEAD(task_scan_kbd.list); task_scan_kbd.sync=0; task_scan_kbd.routine=scan_kbd; task_scan_kbd.data=NULL; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/serial.c linux/drivers/char/serial.c --- v2.4.0-test11/linux/drivers/char/serial.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/serial.c Wed Dec 6 12:06:18 2000 @@ -673,7 +673,7 @@ #if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */ tty_flip_buffer_push(tty); #else - queue_task_irq_off(&tty->flip.tqueue, &tq_timer); + queue_task(&tty->flip.tqueue, &tq_timer); #endif } @@ -3990,7 +3990,7 @@ if (dev->vendor == PCI_VENDOR_ID_PANACOM) irq_config = 0x43; if ((dev->vendor == PCI_VENDOR_ID_PLX) && - (dev->device == PCI_VENDOR_ID_PLX_ROMULUS)) { + (dev->device == PCI_DEVICE_ID_PLX_ROMULUS)) { /* * As the megawolf cards have the int pins active * high, and have 2 UART chips, both ints must be @@ -4324,7 +4324,7 @@ SPCI_FL_BASE2, 8, 460800 }, /* Megawolf Romulus PCI Serial Card, from Mike Hudson */ /* (Exoray@isys.ca) */ - { PCI_VENDOR_ID_PLX, PCI_VENDOR_ID_PLX_ROMULUS, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, 0x10b5, 0x106a, SPCI_FL_BASE2, 4, 921600, 0x20, 2, pci_plx9050_fn, 0x03 }, diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/serial167.c linux/drivers/char/serial167.c --- v2.4.0-test11/linux/drivers/char/serial167.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/serial167.c Mon Nov 27 17:11:26 2000 @@ -31,8 +31,18 @@ * Revision 1.36.1.4 1995/03/29 06:14:14 bentson * disambiguate between Cyclom-16Y and Cyclom-32Ye; * + * Changes: + * * 200 lines of changes record removed - RGH 11-10-95, starting work on * converting this to drive serial ports on mvme166 (cd2401). + * + * Arnaldo Carvalho de Melo - 2000/08/25 + * - get rid of verify_area + * - use get_user to access memory from userspace in set_threshold, + * set_default_threshold and set_timeout + * - don't use the panic function in serial167_init + * - do resource release on failure on serial167_init + * - include missing restore_flags in mvme167_serial_console_setup */ #include @@ -68,17 +78,6 @@ #include #include -#define cy_put_user put_user - -static unsigned long cy_get_user(unsigned long *addr) -{ - unsigned long result = 0; - int error = get_user (result, addr); - if (error) - printk ("serial167: cy_get_user: error == %d\n", error); - return result; -} - #define SERIAL_PARANOIA_CHECK #undef SERIAL_DEBUG_OPEN #undef SERIAL_DEBUG_THROTTLE @@ -1259,7 +1258,11 @@ if (from_user) { down(&tmp_buf_sem); - copy_from_user(tmp_buf, buf, c); + if (copy_from_user(tmp_buf, buf, c)) { + up(&tmp_buf_sem); + restore_flags(flags); + return 0; + } c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1, SERIAL_XMIT_SIZE - info->xmit_head)); memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c); @@ -1435,8 +1438,7 @@ tmp.close_delay = info->close_delay; tmp.custom_divisor = 0; /*!!!*/ tmp.hub6 = 0; /*!!!*/ - copy_to_user(retinfo,&tmp,sizeof(*retinfo)); - return 0; + return copy_to_user(retinfo,&tmp,sizeof(*retinfo)) ? -EFAULT : 0; } /* get_serial_info */ static int @@ -1449,7 +1451,8 @@ /* CP('s'); */ if (!new_info) return -EFAULT; - copy_from_user(&new_serial,new_info,sizeof(new_serial)); + if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) + return -EFAULT; old_info = *info; if (!suser()) { @@ -1503,8 +1506,7 @@ | ((status & CyDCD) ? TIOCM_CAR : 0) | ((status & CyDSR) ? TIOCM_DSR : 0) | ((status & CyCTS) ? TIOCM_CTS : 0); - cy_put_user(result,(unsigned int *) value); - return 0; + return put_user(result,(unsigned int *) value); } /* get_modem_info */ static int @@ -1514,8 +1516,10 @@ int channel; volatile unsigned char *base_addr = (u_char *)BASE_ADDR; unsigned long flags; - unsigned int arg = cy_get_user((unsigned long *) value); - + unsigned int arg; + + if (get_user(arg, (unsigned long *) value)) + return -EFAULT; channel = info->line; switch (cmd) { @@ -1612,7 +1616,8 @@ get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon) { - copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)); + if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor))) + return -EFAULT; info->mon.int_count = 0; info->mon.char_count = 0; info->mon.char_max = 0; @@ -1621,13 +1626,16 @@ } static int -set_threshold(struct cyclades_port * info, unsigned long value) +set_threshold(struct cyclades_port * info, unsigned long *arg) { volatile unsigned char *base_addr = (u_char *)BASE_ADDR; + unsigned long value; int channel; - channel = info->line; + if (get_user(value, arg)) + return -EFAULT; + channel = info->line; info->cor4 &= ~CyREC_FIFO; info->cor4 |= value & CyREC_FIFO; base_addr[CyCOR4] = info->cor4; @@ -1644,13 +1652,17 @@ channel = info->line; tmp = base_addr[CyCOR4] & CyREC_FIFO; - cy_put_user(tmp,value); - return 0; + return put_user(tmp,value); } static int -set_default_threshold(struct cyclades_port * info, unsigned long value) +set_default_threshold(struct cyclades_port * info, unsigned long *arg) { + unsigned long value; + + if (get_user(value, arg)) + return -EFAULT; + info->default_threshold = value & 0x0f; return 0; } @@ -1658,15 +1670,18 @@ static int get_default_threshold(struct cyclades_port * info, unsigned long *value) { - cy_put_user(info->default_threshold,value); - return 0; + return put_user(info->default_threshold,value); } static int -set_timeout(struct cyclades_port * info, unsigned long value) +set_timeout(struct cyclades_port * info, unsigned long *arg) { volatile unsigned char *base_addr = (u_char *)BASE_ADDR; int channel; + unsigned long value; + + if (get_user(value, arg)) + return -EFAULT; channel = info->line; @@ -1685,8 +1700,7 @@ channel = info->line; tmp = base_addr[CyRTPRL]; - cy_put_user(tmp,value); - return 0; + return put_user(tmp,value); } static int @@ -1699,15 +1713,14 @@ static int get_default_timeout(struct cyclades_port * info, unsigned long *value) { - cy_put_user(info->default_timeout,value); - return 0; + return put_user(info->default_timeout,value); } static int cy_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - int error; + unsigned long val; struct cyclades_port * info = (struct cyclades_port *)tty->driver_data; int ret_val = 0; @@ -1717,57 +1730,27 @@ switch (cmd) { case CYGETMON: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(struct cyclades_monitor)); - if (error){ - ret_val = error; - break; - } ret_val = get_mon_info(info, (struct cyclades_monitor *)arg); break; case CYGETTHRESH: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned long)); - if (error){ - ret_val = error; - break; - } ret_val = get_threshold(info, (unsigned long *)arg); break; case CYSETTHRESH: - ret_val = set_threshold(info, (unsigned long)arg); + ret_val = set_threshold(info, (unsigned long *)arg); break; case CYGETDEFTHRESH: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned long)); - if (error){ - ret_val = error; - break; - } ret_val = get_default_threshold(info, (unsigned long *)arg); break; case CYSETDEFTHRESH: - ret_val = set_default_threshold(info, (unsigned long)arg); + ret_val = set_default_threshold(info, (unsigned long *)arg); break; case CYGETTIMEOUT: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned long)); - if (error){ - ret_val = error; - break; - } ret_val = get_timeout(info, (unsigned long *)arg); break; case CYSETTIMEOUT: - ret_val = set_timeout(info, (unsigned long)arg); + ret_val = set_timeout(info, (unsigned long *)arg); break; case CYGETDEFTIMEOUT: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned long)); - if (error){ - ret_val = error; - break; - } ret_val = get_default_timeout(info, (unsigned long *)arg); break; case CYSETDEFTIMEOUT: @@ -1776,7 +1759,7 @@ case TCSBRK: /* SVID version: non-zero arg --> no break */ ret_val = tty_check_change(tty); if (ret_val) - return ret_val; + break; tty_wait_until_sent(tty,0); if (!arg) send_break(info, HZ/4); /* 1/4 second */ @@ -1784,7 +1767,7 @@ case TCSBRKP: /* support for POSIX tcsendbreak() */ ret_val = tty_check_change(tty); if (ret_val) - return ret_val; + break; tty_wait_until_sent(tty,0); send_break(info, arg ? arg*(HZ/10) : HZ/4); break; @@ -1796,46 +1779,20 @@ /* The following commands are incompletely implemented!!! */ case TIOCGSOFTCAR: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned int *)); - if (error){ - ret_val = error; - break; - } - cy_put_user(C_CLOCAL(tty) ? 1 : 0, - (unsigned long *) arg); + ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg); break; case TIOCSSOFTCAR: - error = verify_area(VERIFY_READ, (void *) arg - ,sizeof(unsigned long *)); - if (error){ - ret_val = error; - break; - } - - arg = cy_get_user((unsigned long *) arg); + ret_val = get_user(val, (unsigned long *) arg); + if (ret_val) + break; tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); + ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0)); break; case TIOCMGET: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(unsigned int *)); - if (error){ - ret_val = error; - break; - } ret_val = get_modem_info(info, (unsigned int *) arg); break; case TIOCGSERIAL: - error = verify_area(VERIFY_WRITE, (void *) arg - ,sizeof(struct serial_struct)); - if (error){ - ret_val = error; - break; - } - ret_val = get_serial_info(info, - (struct serial_struct *) arg); + ret_val = get_serial_info(info, (struct serial_struct *) arg); break; case TIOCSSERIAL: ret_val = set_serial_info(info, @@ -2288,6 +2245,7 @@ my_udelay(20000L); /* Allow time for any active o/p to complete */ if(base_addr[CyCCR] != 0x00){ + restore_flags(flags); /* printk(" chip is never idle (CCR != 0)\n"); */ return; } @@ -2296,6 +2254,7 @@ my_udelay(1000L); if(base_addr[CyGFRCR] == 0x00){ + restore_flags(flags); /* printk(" chip is not responding (GFRCR stayed 0)\n"); */ return; } @@ -2384,6 +2343,7 @@ serial167_init(void) { struct cyclades_port *info; + int ret = 0; int good_ports = 0; int port_num = 0; int index; @@ -2456,10 +2416,16 @@ cy_callout_driver.major = TTYAUX_MAJOR; cy_callout_driver.subtype = SERIAL_TYPE_CALLOUT; - if (tty_register_driver(&cy_serial_driver)) - panic("Couldn't register Cyclom serial driver\n"); - if (tty_register_driver(&cy_callout_driver)) - panic("Couldn't register Cyclom callout driver\n"); + ret = tty_register_driver(&cy_serial_driver); + if (ret) { + printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n"); + return ret; + } + ret = tty_register_driver(&cy_callout_driver); + if (ret) { + printk(KERN_ERR "Couldn't register MVME166/7 callout driver\n"); + goto cleanup_serial_driver; + } init_bh(CYCLADES_BH, do_cyclades_bh); @@ -2529,16 +2495,32 @@ #ifdef CONFIG_REMOTE_DEBUG debug_setup(); #endif - if (request_irq (MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, - "cd2401_errors", cd2401_rxerr_interrupt) || - request_irq (MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, - "cd2401_modem", cd2401_modem_interrupt) || - request_irq (MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, - "cd2401_txints", cd2401_tx_interrupt) || - request_irq (MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, - "cd2401_rxints", cd2401_rx_interrupt)) - { - panic ("Couldn't get serial IRQs"); + ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0, + "cd2401_errors", cd2401_rxerr_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_errors IRQ"); + goto cleanup_callout_driver; + } + + ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0, + "cd2401_modem", cd2401_modem_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_modem IRQ"); + goto cleanup_irq_cd2401_errors; + } + + ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0, + "cd2401_txints", cd2401_tx_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_txints IRQ"); + goto cleanup_irq_cd2401_modem; + } + + ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0, + "cd2401_rxints", cd2401_rx_interrupt); + if (ret) { + printk(KERN_ERR "Could't get cd2401_rxints IRQ"); + goto cleanup_irq_cd2401_txints; } /* Now we have registered the interrupt handlers, allow the interrupts */ @@ -2550,6 +2532,19 @@ pcc2chip[PccIMLR] = 3; /* Allow PCC2 ints above 3!? */ return 0; +cleanup_irq_cd2401_txints: + free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt); +cleanup_irq_cd2401_modem: + free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt); +cleanup_irq_cd2401_errors: + free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt); +cleanup_callout_driver: + if (tty_unregister_driver(&cy_callout_driver)) + printk(KERN_ERR "Couldn't unregister MVME166/7 callout driver\n"); +cleanup_serial_driver: + if (tty_unregister_driver(&cy_serial_driver)) + printk(KERN_ERR "Couldn't unregister MVME166/7 serial driver\n"); + return ret; } /* serial167_init */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/specialix.c linux/drivers/char/specialix.c --- v2.4.0-test11/linux/drivers/char/specialix.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/specialix.c Wed Dec 6 12:06:18 2000 @@ -834,8 +834,9 @@ #ifdef SPECIALIX_DEBUG printk ( "Sending HUP.\n"); #endif - queue_task(&port->tqueue_hangup, - &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&port->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; } else { #ifdef SPECIALIX_DEBUG printk ( "Don't need to send HUP.\n"); @@ -2121,10 +2122,9 @@ struct tty_struct *tty; tty = port->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); /* FIXME: module removal race here */ + MOD_DEC_USE_COUNT; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/stallion.c linux/drivers/char/stallion.c --- v2.4.0-test11/linux/drivers/char/stallion.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/stallion.c Wed Dec 6 12:06:18 2000 @@ -2231,11 +2231,11 @@ #endif if (portp == (stlport_t *) NULL) - return; + goto out; tty = portp->tty; if (tty == (struct tty_struct *) NULL) - return; + goto out; lock_kernel(); if (test_bit(ASYI_TXLOW, &portp->istate)) { @@ -2254,12 +2254,14 @@ if (portp->flags & ASYNC_CHECK_CD) { if (! ((portp->flags & ASYNC_CALLOUT_ACTIVE) && (portp->flags & ASYNC_CALLOUT_NOHUP))) { - tty_hangup(tty); + tty_hangup(tty); /* FIXME: module removal race here - AKPM */ } } } } unlock_kernel(); +out: + MOD_DEC_USE_COUNT; } /*****************************************************************************/ @@ -4108,7 +4110,9 @@ if ((len == 0) || ((len < STL_TXBUFLOW) && (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { set_bit(ASYI_TXLOW, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&portp->tqueue) == 0) + MOD_DEC_USE_COUNT; } if (len == 0) { @@ -4288,7 +4292,9 @@ misr = inb(ioaddr + EREG_DATA); if (misr & MISR_DCD) { set_bit(ASYI_DCDCHANGE, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&portp->tqueue) == 0) + MOD_DEC_USE_COUNT; portp->stats.modem++; } @@ -5085,7 +5091,9 @@ if ((len == 0) || ((len < STL_TXBUFLOW) && (test_bit(ASYI_TXLOW, &portp->istate) == 0))) { set_bit(ASYI_TXLOW, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&portp->tqueue) == 0) + MOD_DEC_USE_COUNT; } if (len == 0) { @@ -5302,7 +5310,9 @@ ipr = stl_sc26198getreg(portp, IPR); if (ipr & IPR_DCDCHANGE) { set_bit(ASYI_DCDCHANGE, &portp->istate); - queue_task(&portp->tqueue, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&portp->tqueue) == 0) + MOD_DEC_USE_COUNT; portp->stats.modem++; } break; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/sx.h linux/drivers/char/sx.h --- v2.4.0-test11/linux/drivers/char/sx.h Sun Mar 12 19:18:55 2000 +++ linux/drivers/char/sx.h Mon Dec 11 13:38:29 2000 @@ -31,7 +31,7 @@ int c_dcd; struct sx_board *board; int line; - int locks; + long locks; }; struct sx_board { diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c --- v2.4.0-test11/linux/drivers/char/sysrq.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/sysrq.c Sun Dec 3 17:48:19 2000 @@ -27,7 +27,6 @@ extern void wakeup_bdflush(int); extern void reset_vc(unsigned int); -extern int console_loglevel; extern struct list_head super_blocks; /* Whether we react on sysrq keys or just ignore them */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c --- v2.4.0-test11/linux/drivers/char/tpqic02.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/tpqic02.c Wed Dec 6 11:46:39 2000 @@ -760,7 +760,7 @@ static int get_status(volatile struct tpstatus *stp) { int stat = rdstatus((char *) stp, TPSTATSIZE, QCMD_RD_STAT); -#if defined(i386) || defined(i486) +#ifdef __i386__ byte_swap_w(&(stp->dec)); byte_swap_w(&(stp->urc)); #else diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c --- v2.4.0-test11/linux/drivers/char/tty_io.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/tty_io.c Sun Dec 10 08:44:52 2000 @@ -425,11 +425,9 @@ }; /* - * This can be called through the "tq_scheduler" - * task-list. That is process synchronous, but - * doesn't hold any locks, so we need to make - * sure we have the appropriate locks for what - * we're doing.. + * This can be called by the "eventd" kernel thread. That is process synchronous, + * but doesn't hold any locks, so we need to make sure we have the appropriate + * locks for what we're doing.. */ void do_tty_hangup(void *data) { @@ -541,7 +539,7 @@ printk("%s hangup...\n", tty_name(tty, buf)); #endif - queue_task(&tty->tq_hangup, &tq_scheduler); + schedule_task(&tty->tq_hangup); } void tty_vhangup(struct tty_struct * tty) @@ -1264,7 +1262,7 @@ * Make sure that the tty's task queue isn't activated. */ run_task_queue(&tq_timer); - run_task_queue(&tq_scheduler); + flush_scheduled_tasks(); /* * The release_mem function takes care of the details of clearing diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/vme_scc.c linux/drivers/char/vme_scc.c --- v2.4.0-test11/linux/drivers/char/vme_scc.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/vme_scc.c Mon Nov 27 17:11:26 2000 @@ -48,7 +48,7 @@ #include #endif -#include "generic_serial.h" +#include #include "scc.h" @@ -75,7 +75,7 @@ static void scc_enable_rx_interrupts(void * ptr); static int scc_get_CD(void * ptr); static void scc_shutdown_port(void * ptr); -static void scc_set_real_termios(void *ptr); +static int scc_set_real_termios(void *ptr); static void scc_hungup(void *ptr); static void scc_close(void *ptr); static int scc_chars_in_buffer(void * ptr); @@ -688,7 +688,7 @@ } -static void scc_set_real_termios (void *ptr) +static int scc_set_real_termios (void *ptr) { /* the SCC has char sizes 5,7,6,8 in that order! */ static int chsize_map[4] = { 0, 2, 1, 3 }; @@ -697,12 +697,12 @@ struct scc_port *port = ptr; SCC_ACCESS_INIT(port); - if (!port->gs.tty || !port->gs.tty->termios) return; + if (!port->gs.tty || !port->gs.tty->termios) return 0; channel = port->channel; if (channel == CHANNEL_A) - return; /* Settings controlled by boot PROM */ + return 0; /* Settings controlled by boot PROM */ cflag = port->gs.tty->termios->c_cflag; baud = port->gs.baud; @@ -714,13 +714,13 @@ cli(); SCCmod(TX_CTRL_REG, ~TCR_DTR, 0); restore_flags(flags); - return; + return 0; } else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) || (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) || (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) { printk("SCC: Bad speed requested, %d\n", baud); - return; + return 0; } if (cflag & CLOCAL) @@ -769,6 +769,8 @@ SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB); restore_flags(flags); + + return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/char/vt.c linux/drivers/char/vt.c --- v2.4.0-test11/linux/drivers/char/vt.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/vt.c Mon Dec 11 13:45:42 2000 @@ -62,7 +62,7 @@ */ unsigned char keyboard_type = KB_101; -#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on); #endif @@ -472,7 +472,7 @@ ucval = keyboard_type; goto setchar; -#if !defined(__alpha__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) +#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__) /* * These cannot be implemented on any machine that implements * ioperm() in user level (such as Alpha PCs). diff -u --recursive --new-file v2.4.0-test11/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c --- v2.4.0-test11/linux/drivers/i2o/i2o_lan.c Mon Jun 19 13:30:56 2000 +++ linux/drivers/i2o/i2o_lan.c Mon Dec 11 12:39:44 2000 @@ -112,8 +112,10 @@ }; static int lan_context; -static struct tq_struct i2o_post_buckets_task = { - 0, 0, (void (*)(void *))i2o_lan_receive_post, (void *) 0 +DECLARE_TASK_QUEUE(i2o_post_buckets_task); +struct tq_struct run_i2o_post_buckets_task = { + routine: (void (*)(void *)) run_task_queue, + data: (void *) 0 }; /* Functions to handle message failures and transaction errors: @@ -379,8 +381,8 @@ /* If DDM has already consumed bucket_thresh buckets, post new ones */ if (atomic_read(&priv->buckets_out) <= priv->max_buckets_out - priv->bucket_thresh) { - i2o_post_buckets_task.data = (void *)dev; - queue_task(&i2o_post_buckets_task, &tq_immediate); + run_i2o_post_buckets_task.data = (void *)dev; + queue_task(&run_i2o_post_buckets_task, &tq_immediate); mark_bh(IMMEDIATE_BH); } @@ -846,6 +848,7 @@ } priv->send_active = 0; spin_unlock_irq(&priv->tx_lock); + MOD_DEC_USE_COUNT; } #ifdef CONFIG_NET_FC @@ -900,7 +903,9 @@ if ((priv->tx_batch_mode & 0x01) && !priv->send_active) { priv->send_active = 1; - queue_task(&priv->i2o_batch_send_task, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&priv->i2o_batch_send_task) == 0) + MOD_DEC_USE_COUNT; } } else { /* Add new SGL element to the previous message frame */ @@ -986,7 +991,9 @@ if ((priv->tx_batch_mode & 0x01) && !priv->send_active) { priv->send_active = 1; - queue_task(&priv->i2o_batch_send_task, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&priv->i2o_batch_send_task) == 0) + MOD_DEC_USE_COUNT; } } else { /* Add new SGL element to the previous message frame */ @@ -1396,7 +1403,7 @@ atomic_set(&priv->tx_out, 0); priv->tx_count = 0; - priv->i2o_batch_send_task.next = NULL; + INIT_LIST_HEAD(&priv->i2o_batch_send_task.list); priv->i2o_batch_send_task.sync = 0; priv->i2o_batch_send_task.routine = (void *)i2o_lan_batch_send; priv->i2o_batch_send_task.data = (void *)dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ide/buddha.c linux/drivers/ide/buddha.c --- v2.4.0-test11/linux/drivers/ide/buddha.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/ide/buddha.c Mon Nov 27 17:57:34 2000 @@ -43,7 +43,7 @@ #define BUDDHA_BASE2 0xa00 #define BUDDHA_BASE3 0xc00 -static const u_int __init buddha_bases[CATWEASEL_NUM_HWIFS] = { +static const u_int buddha_bases[CATWEASEL_NUM_HWIFS] __initdata = { BUDDHA_BASE1, BUDDHA_BASE2, BUDDHA_BASE3 }; @@ -62,7 +62,7 @@ #define BUDDHA_STATUS 0x1e /* see status-bits */ #define BUDDHA_CONTROL 0x11a -static int __init buddha_offsets[IDE_NR_PORTS] = { +static int buddha_offsets[IDE_NR_PORTS] __initdata = { BUDDHA_DATA, BUDDHA_ERROR, BUDDHA_NSECTOR, BUDDHA_SECTOR, BUDDHA_LCYL, BUDDHA_HCYL, BUDDHA_SELECT, BUDDHA_STATUS, BUDDHA_CONTROL }; @@ -76,7 +76,7 @@ #define BUDDHA_IRQ2 0xf40 /* interrupt */ #define BUDDHA_IRQ3 0xf80 -static const int __init buddha_irqports[CATWEASEL_NUM_HWIFS] = { +static const int buddha_irqports[CATWEASEL_NUM_HWIFS] __initdata = { BUDDHA_IRQ1, BUDDHA_IRQ2, BUDDHA_IRQ3 }; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ide/gayle.c linux/drivers/ide/gayle.c --- v2.4.0-test11/linux/drivers/ide/gayle.c Tue Jun 20 07:52:36 2000 +++ linux/drivers/ide/gayle.c Mon Nov 27 17:57:34 2000 @@ -17,8 +17,10 @@ #include #include +#include #include #include +#include /* @@ -42,7 +44,7 @@ #define GAYLE_STATUS 0x1e /* see status-bits */ #define GAYLE_CONTROL 0x101a -static int __init gayle_offsets[IDE_NR_PORTS] = { +static int gayle_offsets[IDE_NR_PORTS] __initdata = { GAYLE_DATA, GAYLE_ERROR, GAYLE_NSECTOR, GAYLE_SECTOR, GAYLE_LCYL, GAYLE_HCYL, GAYLE_SELECT, GAYLE_STATUS, -1, -1 }; @@ -87,7 +89,7 @@ unsigned char ch; ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) + if (!(ch & GAYLE_IRQ_IDE)) return 0; return 1; } @@ -97,10 +99,10 @@ unsigned char ch; ch = inb(hwif->io_ports[IDE_IRQ_OFFSET]); - if (!(ch & 0x80)) + if (!(ch & GAYLE_IRQ_IDE)) return 0; (void)inb(hwif->io_ports[IDE_STATUS_OFFSET]); - outb(0x7c | (ch & 0x03), hwif->io_ports[IDE_IRQ_OFFSET]); + outb(0x7c, hwif->io_ports[IDE_IRQ_OFFSET]); return 1; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c --- v2.4.0-test11/linux/drivers/ide/ide-cd.c Tue Sep 5 13:46:15 2000 +++ linux/drivers/ide/ide-cd.c Wed Nov 29 11:26:39 2000 @@ -1841,9 +1841,9 @@ memset(&pc, 0, sizeof (pc)); pc.sense = &sense; - pc.c[0] = GPCMD_PLAY_AUDIO_10; - put_unaligned(cpu_to_be32(lba_start), (unsigned int *) &pc.c[2]); - put_unaligned(cpu_to_be16(lba_end - lba_start), (unsigned int *) &pc.c[7]); + pc.c[0] = GPCMD_PLAY_AUDIO_MSF; + lba_to_msf(lba_start, &pc.c[3], &pc.c[4], &pc.c[5]); + lba_to_msf(lba_end-1, &pc.c[6], &pc.c[7], &pc.c[8]); return cdrom_queue_packet_command(drive, &pc); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ide/ide.c linux/drivers/ide/ide.c --- v2.4.0-test11/linux/drivers/ide/ide.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/ide/ide.c Wed Dec 6 12:06:19 2000 @@ -1324,7 +1324,7 @@ mod_timer(&hwgroup->timer, sleep); /* we purposely leave hwgroup->busy==1 while sleeping */ } else { - /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */ + /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_disk? */ ide_release_lock(&ide_lock); /* for atari only */ hwgroup->busy = 0; } @@ -3241,6 +3241,12 @@ macide_init(); } #endif /* CONFIG_BLK_DEV_MAC_IDE */ +#ifdef CONFIG_BLK_DEV_Q40IDE + { + extern void q40ide_init(void); + q40ide_init(); + } +#endif /* CONFIG_BLK_DEV_Q40IDE */ #ifdef CONFIG_BLK_DEV_BUDDHA { extern void buddha_init(void); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ide/q40ide.c linux/drivers/ide/q40ide.c --- v2.4.0-test11/linux/drivers/ide/q40ide.c Wed Mar 22 17:18:44 2000 +++ linux/drivers/ide/q40ide.c Tue Dec 5 12:43:47 2000 @@ -1,18 +1,12 @@ /* * linux/drivers/ide/q40ide.c -- Q40 I/O port IDE Driver * - * original file created 12 Jul 1997 by Geert Uytterhoeven + * (c) Richard Zidlicky * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * - * RZ: - * almost identical with pcide.c, maybe we can merge it later. - * Differences: - * max 2 HWIFS for now - * translate portaddresses to q40 native addresses (not yet...) instead rely on in/out[bw] - * address translation * */ @@ -28,7 +22,7 @@ * Bases of the IDE interfaces */ -#define PCIDE_NUM_HWIFS 2 +#define Q40IDE_NUM_HWIFS 2 #define PCIDE_BASE1 0x1f0 #define PCIDE_BASE2 0x170 @@ -37,7 +31,7 @@ #define PCIDE_BASE5 0x1e0 #define PCIDE_BASE6 0x160 -static const q40ide_ioreg_t pcide_bases[PCIDE_NUM_HWIFS] = { +static const q40ide_ioreg_t pcide_bases[Q40IDE_NUM_HWIFS] = { PCIDE_BASE1, PCIDE_BASE2, /* PCIDE_BASE3, PCIDE_BASE4 , PCIDE_BASE5, PCIDE_BASE6 */ }; @@ -58,7 +52,7 @@ PCIDE_REG(CMD) }; -int q40ide_default_irq(q40ide_ioreg_t base) +static int q40ide_default_irq(q40ide_ioreg_t base) { switch (base) { case 0x1f0: return 14; @@ -69,41 +63,26 @@ } } -void q40_ide_init_hwif_ports (q40ide_ioreg_t *p, q40ide_ioreg_t base, int *irq) -{ - q40ide_ioreg_t port = base; - int i = 8; - - while (i--) - *p++ = port++; - *p++ = base + 0x206; - if (irq != NULL) - *irq = 0; -} /* - * Probe for PC IDE interfaces + * Probe for Q40 IDE interfaces */ -int q40ide_probe_hwif(int index, ide_hwif_t *hwif) +void q40ide_init(void) { - static int pcide_index[PCIDE_NUM_HWIFS] = { 0, }; int i; if (!MACH_IS_Q40) - return 0; + return ; - for (i = 0; i < PCIDE_NUM_HWIFS; i++) { - if (!pcide_index[i]) { - /*printk("ide%d: Q40 IDE interface\n", index);*/ - pcide_index[i] = index+1; - } - if (pcide_index[i] == index+1) { - ide_setup_ports(hwif,(ide_ioreg_t) pcide_bases[i], pcide_offsets, 0, /*q40_ack_intr???*/ NULL); - hwif->irq = ide_default_irq((ide_ioreg_t)pcide_bases[i]); /*q40_ide_irq[i]; */ /* 14 */ - return 1; - } + for (i = 0; i < Q40IDE_NUM_HWIFS; i++) { + hw_regs_t hw; + + ide_setup_ports(&hw,(ide_ioreg_t) pcide_bases[i], (int *)pcide_offsets, + pcide_bases[i]+0x206, + 0, NULL, q40ide_default_irq(pcide_bases[i])); + ide_register_hw(&hw, NULL); } - return 0; } + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ieee1394/guid.c linux/drivers/ieee1394/guid.c --- v2.4.0-test11/linux/drivers/ieee1394/guid.c Wed Jul 5 13:03:56 2000 +++ linux/drivers/ieee1394/guid.c Mon Dec 11 12:39:44 2000 @@ -163,7 +163,7 @@ return; } - greq->tq.next = NULL; + INIT_LIST_HEAD(&greq->tq.list); greq->tq.sync = 0; greq->tq.routine = (void (*)(void*))pkt_complete; greq->tq.data = greq; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ieee1394/ieee1394_types.h linux/drivers/ieee1394/ieee1394_types.h --- v2.4.0-test11/linux/drivers/ieee1394/ieee1394_types.h Sun Oct 8 10:50:17 2000 +++ linux/drivers/ieee1394/ieee1394_types.h Mon Dec 11 13:20:17 2000 @@ -10,186 +10,12 @@ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0) - -#include -#define DECLARE_WAITQUEUE(name, task) struct wait_queue name = { task, NULL } - -typedef struct wait_queue *wait_queue_head_t; -typedef struct wait_queue wait_queue_t; - -inline static void init_waitqueue_head(wait_queue_head_t *wh) -{ - *wh = NULL; -} - -inline static void init_waitqueue_entry(wait_queue_t *wq, struct task_struct *p) -{ - wq->task = p; - wq->next = NULL; -} - -static __inline__ void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -#define __constant_cpu_to_be32(x) __constant_htonl((x)) - -#define set_current_state(state_value) \ - do { current->state = (state_value); } while (0) - - -#include -/* Pure 2^n version of get_order */ -extern __inline__ int get_order(unsigned long size) -{ - int order; - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} - -#include -#include -inline static int pci_enable_device(struct pci_dev *dev) -{ - u16 cmd; - pci_read_config_word(dev, PCI_COMMAND, &cmd); - pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY); - return 0; -} - -#define PCI_DMA_BIDIRECTIONAL 0 -#define PCI_DMA_TODEVICE 1 -#define PCI_DMA_FROMDEVICE 2 -#define PCI_DMA_NONE 3 -#define PCI_ROM_RESOURCE 6 -#define pci_resource_start(dev, bar) ((bar) == PCI_ROM_RESOURCE \ - ? (dev)->rom_address \ - : (dev)->base_address[(bar)]) -#define BUG() *(int *)0 = 0 - -#include -typedef u32 dma_addr_t; - -extern inline int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask) -{ - return 1; -} - -extern inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); - if (ret) { - memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); - } - return ret; -} - -extern inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} - -extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); - return virt_to_bus(ptr); -} - -extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); -} - -#include -extern inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); - return nents; -} - -extern inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, - int nents, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); -} - -extern inline void pci_dma_sync_single(struct pci_dev *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); -} - -extern inline void pci_dma_sync_sg(struct pci_dev *hwdev, - struct scatterlist *sg, - int nelems, int direction) -{ - if (direction == PCI_DMA_NONE) - BUG(); -} - - -#ifndef _LINUX_DEVFS_FS_KERNEL_H -typedef struct devfs_entry * devfs_handle_t; -#define DEVFS_FL_NONE 0 - -static inline devfs_handle_t devfs_register (devfs_handle_t dir, - const char *name, - unsigned int flags, - unsigned int major, - unsigned int minor, - umode_t mode, - void *ops, void *info) -{ - return NULL; -} -static inline void devfs_unregister (devfs_handle_t de) -{ - return; -} -static inline int devfs_register_chrdev (unsigned int major, const char *name, - struct file_operations *fops) -{ - return register_chrdev (major, name, fops); -} -static inline int devfs_unregister_chrdev (unsigned int major,const char *name) -{ - return unregister_chrdev (major, name); -} -#endif /* _LINUX_DEVFS_FS_KERNEL_H */ - - -#define V22_COMPAT_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -#define V22_COMPAT_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -#define OWNER_THIS_MODULE - -#else /* Linux version < 2.3 */ - +#include "linux22compat.h" +#else #define V22_COMPAT_MOD_INC_USE_COUNT do {} while (0) #define V22_COMPAT_MOD_DEC_USE_COUNT do {} while (0) #define OWNER_THIS_MODULE owner: THIS_MODULE, - -#endif /* Linux version < 2.3 */ - - +#endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18) #include diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c --- v2.4.0-test11/linux/drivers/ieee1394/ohci1394.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/ieee1394/ohci1394.c Mon Dec 11 12:39:44 2000 @@ -1585,7 +1585,7 @@ /* initialize bottom handler */ d->task.sync = 0; - d->task.next = NULL; + INIT_LIST_HEAD(&d->task.list); d->task.routine = dma_rcv_bh; d->task.data = (void*)d; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c --- v2.4.0-test11/linux/drivers/ieee1394/pcilynx.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/ieee1394/pcilynx.c Tue Nov 28 21:45:16 2000 @@ -1457,9 +1457,9 @@ switch (lynx->state) { case have_intr: + reg_write(lynx, PCI_INT_ENABLE, 0); free_irq(lynx->dev->irq, lynx); case have_iomappings: - reg_write(lynx, PCI_INT_ENABLE, 0); reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET); iounmap(lynx->registers); iounmap(lynx->local_rom); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/ieee1394/raw1394.c linux/drivers/ieee1394/raw1394.c --- v2.4.0-test11/linux/drivers/ieee1394/raw1394.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/ieee1394/raw1394.c Tue Nov 28 21:45:16 2000 @@ -786,6 +786,10 @@ req->req.length = 0; queue_task(&req->tq, &packet->complete_tq); + spin_lock_irq(&fi->reqlists_lock); + list_add_tail(&req->list, &fi->req_pending); + spin_unlock_irq(&fi->reqlists_lock); + if (!hpsb_send_packet(packet)) { req->req.error = RAW1394_ERROR_SEND_ERROR; queue_complete_req(req); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/Makefile linux/drivers/isdn/avmb1/Makefile --- v2.4.0-test11/linux/drivers/isdn/avmb1/Makefile Sun Nov 19 18:44:07 2000 +++ linux/drivers/isdn/avmb1/Makefile Mon Nov 27 16:53:43 2000 @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.21 2000/11/01 14:05:02 calle Exp $ +# $Id: Makefile,v 1.22 2000/11/23 20:45:14 kai Exp $ # # Makefile for the CAPI and AVM-B1 device drivers. # @@ -11,6 +11,10 @@ # parent makes.. # # $Log: Makefile,v $ +# Revision 1.22 2000/11/23 20:45:14 kai +# fixed module_init/exit stuff +# Note: compiled-in kernel doesn't work pre 2.2.18 anymore. +# # Revision 1.21 2000/11/01 14:05:02 calle # - use module_init/module_exit from linux/init.h. # - all static struct variables are initialized with "membername:" now. @@ -150,19 +154,19 @@ OX_OBJS += kcapi.o O_OBJS += capi.o ifdef CONFIG_ISDN_CAPIFS - OX_OBJS += capifs.o + OX_OBJS += capifs.o endif ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - O_OBJS += b1isa.o + O_OBJS += b1isa.o endif ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - O_OBJS += b1pci.o + O_OBJS += b1pci.o endif ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - O_OBJS += t1isa.o + O_OBJS += t1isa.o endif ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - OX_OBJS += b1pcmcia.o + OX_OBJS += b1pcmcia.o ifeq ($(CONFIG_HOTPLUG),y) ifneq ($(CONFIG_PCMCIA),n) M_OBJS += avm_cs.o @@ -170,44 +174,44 @@ endif endif ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - O_OBJS += t1pci.o + O_OBJS += t1pci.o endif ifdef CONFIG_ISDN_DRV_AVMB1_C4 - O_OBJS += c4.o + O_OBJS += c4.o endif OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o else ifeq ($(CONFIG_ISDN_CAPI),m) - O_TARGET += kernelcapi.o - OX_OBJS += kcapi.o - M_OBJS += capi.o kernelcapi.o - ifdef CONFIG_ISDN_CAPIFS - MX_OBJS += capifs.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - M_OBJS += b1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - M_OBJS += b1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - M_OBJS += t1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - MX_OBJS += b1pcmcia.o + O_TARGET += kernelcapi.o + OX_OBJS += kcapi.o + M_OBJS += capi.o kernelcapi.o + ifdef CONFIG_ISDN_CAPIFS + MX_OBJS += capifs.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA + M_OBJS += b1isa.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI + M_OBJS += b1pci.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA + M_OBJS += t1isa.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA + MX_OBJS += b1pcmcia.o ifeq ($(CONFIG_HOTPLUG),y) ifneq ($(CONFIG_PCMCIA),n) - M_OBJS += avm_cs.o + M_OBJS += avm_cs.o endif endif - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - M_OBJS += t1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_C4 - M_OBJS += c4.o - endif - MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI + M_OBJS += t1pci.o + endif + ifdef CONFIG_ISDN_DRV_AVMB1_C4 + M_OBJS += c4.o + endif + MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o endif endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/avm_cs.c linux/drivers/isdn/avmb1/avm_cs.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/avm_cs.c Tue Jul 18 16:52:34 2000 +++ linux/drivers/isdn/avmb1/avm_cs.c Mon Nov 27 16:53:43 2000 @@ -145,9 +145,7 @@ /* The io structure describes IO port mapping */ link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.NumPorts2 = 16; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; - link->io.IOAddrLines = 5; + link->io.NumPorts2 = 0; /* Interrupt setup */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; @@ -329,9 +327,10 @@ link->conf.ConfigIndex = cf->index; link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; + link->io.NumPorts2 = 0; printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1); + link->io.BasePort1+link->io.NumPorts1-1); i = CardServices(RequestIO, link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } @@ -504,7 +503,7 @@ /*====================================================================*/ -int init_module(void) +static int __init avmcs_init(void) { servinfo_t serv; CardServices(GetCardServicesInfo, &serv); @@ -517,7 +516,7 @@ return 0; } -void cleanup_module(void) +static void __exit avmcs_exit(void) { unregister_pccard_driver(&dev_info); while (dev_list != NULL) { @@ -526,3 +525,6 @@ avmcs_detach(dev_list); } } + +module_init(avmcs_init); +module_exit(avmcs_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/b1.c Sun Nov 19 18:44:07 2000 +++ linux/drivers/isdn/avmb1/b1.c Tue Nov 28 21:43:13 2000 @@ -1,11 +1,26 @@ /* - * $Id: b1.c,v 1.16 2000/08/04 15:36:31 calle Exp $ + * $Id: b1.c,v 1.20 2000/11/23 20:45:14 kai Exp $ * * Common module for AVM B1 cards. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1.c,v $ + * Revision 1.20 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.19 2000/11/19 17:02:47 kai + * compatibility cleanup - part 3 + * + * Revision 1.18 2000/11/19 17:01:53 kai + * compatibility cleanup - part 2 + * + * Revision 1.17 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.16 2000/08/04 15:36:31 calle * copied wrong from file to file :-( * @@ -94,6 +109,7 @@ #include #include #include +#include #include #include #include "capilli.h" @@ -101,7 +117,7 @@ #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.16 $"; +static char *revision = "$Revision: 1.20 $"; /* ------------------------------------------------------------- */ @@ -728,12 +744,7 @@ EXPORT_SYMBOL(b1ctl_read_proc); -#ifdef MODULE -#define b1_init init_module -void cleanup_module(void); -#endif - -int b1_init(void) +static int __init b1_init(void) { char *p; char rev[10]; @@ -750,8 +761,9 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit b1_exit(void) { } -#endif + +module_init(b1_init); +module_exit(b1_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/b1capi.c linux/drivers/isdn/avmb1/b1capi.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/b1capi.c Sun May 23 10:03:41 1999 +++ linux/drivers/isdn/avmb1/b1capi.c Wed Dec 6 12:06:18 2000 @@ -468,6 +468,7 @@ for (contr=1; VALID_CARD(contr); contr++) if (test_and_clear_bit(contr, ¬ify_down_set)) notify_down(contr); + MOD_DEC_USE_COUNT; } /* -------- card ready callback ------------------------------- */ @@ -508,7 +509,9 @@ } set_bit(CARDNR(card), ¬ify_up_set); - queue_task(&tq_state_notify, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&tq_state_notify) == 0) + MOD_DEC_USE_COUNT; flag = ((__u8 *)(profp->manu))[1]; switch (flag) { @@ -568,7 +571,9 @@ } } set_bit(CARDNR(card), ¬ify_down_set); - queue_task(&tq_state_notify, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&tq_state_notify) == 0) + MOD_DEC_USE_COUNT; printk(KERN_NOTICE "b1capi: card %d down.\n", CARDNR(card)); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/b1dma.c Sun Nov 19 18:44:07 2000 +++ linux/drivers/isdn/avmb1/b1dma.c Tue Nov 28 21:43:13 2000 @@ -1,11 +1,17 @@ /* - * $Id: b1dma.c,v 1.9 2000/11/01 14:05:02 calle Exp $ + * $Id: b1dma.c,v 1.11 2000/11/19 17:02:47 kai Exp $ * * Common module for AVM B1 cards that support dma with AMCC * * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1dma.c,v $ + * Revision 1.11 2000/11/19 17:02:47 kai + * compatibility cleanup - part 3 + * + * Revision 1.10 2000/11/19 17:01:53 kai + * compatibility cleanup - part 2 + * * Revision 1.9 2000/11/01 14:05:02 calle * - use module_init/module_exit from linux/init.h. * - all static struct variables are initialized with "membername:" now. @@ -48,6 +54,7 @@ #include #include #include +#include #include #include #include "capilli.h" @@ -55,7 +62,7 @@ #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.9 $"; +static char *revision = "$Revision: 1.11 $"; /* ------------------------------------------------------------- */ @@ -978,11 +985,6 @@ EXPORT_SYMBOL(b1dma_send_message); EXPORT_SYMBOL(b1dmactl_read_proc); -#ifdef MODULE -#define b1dma_init init_module -void cleanup_module(void); -#endif - int b1dma_init(void) { char *p; @@ -1000,8 +1002,9 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +void b1dma_exit(void) { } -#endif + +module_init(b1dma_init); +module_exit(b1dma_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/b1isa.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/b1isa.c Tue Nov 28 21:43:13 2000 @@ -1,11 +1,20 @@ /* - * $Id: b1isa.c,v 1.8 2000/04/03 13:29:24 calle Exp $ + * $Id: b1isa.c,v 1.10 2000/11/23 20:45:14 kai Exp $ * * Module for AVM B1 ISA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1isa.c,v $ + * Revision 1.10 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.9 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.8 2000/04/03 13:29:24 calle * make Tim Waugh happy (module unload races in 2.3.99-pre3). * no real problem there, but now it is much cleaner ... @@ -67,13 +76,14 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.8 $"; +static char *revision = "$Revision: 1.10 $"; /* ------------------------------------------------------------- */ @@ -260,12 +270,7 @@ add_card: b1isa_add_card, }; -#ifdef MODULE -#define b1isa_init init_module -void cleanup_module(void); -#endif - -int b1isa_init(void) +static int __init b1isa_init(void) { struct capi_driver *driver = &b1isa_driver; char *p; @@ -292,9 +297,10 @@ return retval; } -#ifdef MODULE -void cleanup_module(void) +static void __exit b1isa_exit(void) { detach_capi_driver(&b1isa_driver); } -#endif + +module_init(b1isa_init); +module_exit(b1isa_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/b1pci.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/b1pci.c Tue Nov 28 21:44:41 2000 @@ -1,11 +1,30 @@ /* - * $Id: b1pci.c,v 1.27 2000/08/08 09:24:19 calle Exp $ + * $Id: b1pci.c,v 1.29.6.1 2000/11/28 12:02:45 kai Exp $ * * Module for AVM B1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pci.c,v $ + * Revision 1.29.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.29.2.2 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.29.2.1 2000/11/26 17:14:19 kai + * fix device ids + * also needs patches to include/linux/pci_ids.h + * + * Revision 1.29 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.28 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.27 2000/08/08 09:24:19 calle * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI * @@ -94,25 +113,22 @@ #include #include #include +#include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.27 $"; +static char *revision = "$Revision: 1.29.6.1 $"; /* ------------------------------------------------------------- */ -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif - -#ifndef PCI_DEVICE_ID_AVM_B1 -#define PCI_DEVICE_ID_AVM_B1 0x700 -#endif - -/* ------------------------------------------------------------- */ +static struct pci_device_id b1pci_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl); MODULE_AUTHOR("Carsten Paeth "); /* ------------------------------------------------------------- */ @@ -481,11 +497,6 @@ #endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ -#ifdef MODULE -#define b1pci_init init_module -void cleanup_module(void); -#endif - static int ncards = 0; static int add_card(struct pci_dev *dev) @@ -548,7 +559,7 @@ return retval; } -int b1pci_init(void) +static int __init b1pci_init(void) { struct capi_driver *driver = &b1pci_driver; #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 @@ -640,12 +651,13 @@ #endif } -#ifdef MODULE -void cleanup_module(void) +static void __exit b1pci_exit(void) { detach_capi_driver(&b1pci_driver); #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 detach_capi_driver(&b1pciv4_driver); #endif } -#endif + +module_init(b1pci_init); +module_exit(b1pci_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/b1pcmcia.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/b1pcmcia.c Tue Nov 28 21:43:13 2000 @@ -1,11 +1,20 @@ /* - * $Id: b1pcmcia.c,v 1.10 2000/05/06 00:52:36 kai Exp $ + * $Id: b1pcmcia.c,v 1.12 2000/11/23 20:45:14 kai Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: b1pcmcia.c,v $ + * Revision 1.12 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.11 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.10 2000/05/06 00:52:36 kai * merged changes from kernel tree * fixed timer and net_device->name breakage @@ -75,6 +84,7 @@ #include #include #include +#include #include #include #include @@ -83,7 +93,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.10 $"; +static char *revision = "$Revision: 1.12 $"; /* ------------------------------------------------------------- */ @@ -300,12 +310,7 @@ /* ------------------------------------------------------------- */ -#ifdef MODULE -#define b1pcmcia_init init_module -void cleanup_module(void); -#endif - -int b1pcmcia_init(void) +static int __init b1pcmcia_init(void) { struct capi_driver *driver = &b1pcmcia_driver; char *p; @@ -332,9 +337,10 @@ return retval; } -#ifdef MODULE -void cleanup_module(void) +static void __exit b1pcmcia_exit(void) { detach_capi_driver(&b1pcmcia_driver); } -#endif + +module_init(b1pcmcia_init); +module_exit(b1pcmcia_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/c4.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/c4.c Tue Nov 28 21:44:41 2000 @@ -1,11 +1,28 @@ /* - * $Id: c4.c,v 1.18 2000/11/01 14:05:02 calle Exp $ + * $Id: c4.c,v 1.20.6.1 2000/11/28 12:02:45 kai Exp $ * * Module for AVM C4 card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: c4.c,v $ + * Revision 1.20.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.20.2.2 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.20.2.1 2000/11/26 17:14:19 kai + * fix device ids + * also needs patches to include/linux/pci_ids.h + * + * Revision 1.20 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.19 2000/11/19 17:02:47 kai + * compatibility cleanup - part 3 + * * Revision 1.18 2000/11/01 14:05:02 calle * - use module_init/module_exit from linux/init.h. * - all static struct variables are initialized with "membername:" now. @@ -80,6 +97,7 @@ #include #include #include +#include #include #include #include @@ -88,35 +106,22 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.18 $"; +static char *revision = "$Revision: 1.20.6.1 $"; #undef CONFIG_C4_DEBUG #undef CONFIG_C4_POLLDEBUG /* ------------------------------------------------------------- */ -#ifndef PCI_VENDOR_ID_DEC -#define PCI_VENDOR_ID_DEC 0x1011 -#endif +static int suppress_pollack; -#ifndef PCI_DEVICE_ID_DEC_21285 -#define PCI_DEVICE_ID_DEC_21285 0x1065 -#endif - -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif - -#ifndef PCI_DEVICE_ID_AVM_C4 -#define PCI_DEVICE_ID_AVM_C4 0x0800 -#endif - -/* ------------------------------------------------------------- */ - -static int suppress_pollack = 0; +static struct pci_device_id c4_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4 }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, c4_pci_tbl); MODULE_AUTHOR("Carsten Paeth "); - MODULE_PARM(suppress_pollack, "0-1i"); /* ------------------------------------------------------------- */ @@ -1327,15 +1332,9 @@ }; -#ifdef MODULE -#define c4_init init_module -void cleanup_module(void); -#endif - - static int ncards = 0; -int c4_init(void) +static int __init c4_init(void) { struct capi_driver *driver = &c4_driver; struct pci_dev *dev = NULL; @@ -1419,9 +1418,10 @@ #endif } -#ifdef MODULE -void cleanup_module(void) +static void __exit c4_exit(void) { detach_capi_driver(&c4_driver); } -#endif + +module_init(c4_init); +module_exit(c4_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/capi.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/capi.c Tue Dec 5 12:43:47 2000 @@ -1,11 +1,32 @@ /* - * $Id: capi.c,v 1.39 2000/07/24 13:42:50 calle Exp $ + * $Id: capi.c,v 1.44 2000/11/25 17:00:59 kai Exp $ * * CAPI 2.0 Interface for Linux * * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capi.c,v $ + * Revision 1.44 2000/11/25 17:00:59 kai + * compatibility cleanup - final part for the time being + * + * Revision 1.43 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.42 2000/11/19 17:03:55 kai + * compatibility cleanup - part 5 + * + * Revision 1.41 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.40 2000/10/24 15:15:04 calle + * Workaround: pppd calls restoretty before reseting the ldisc and + * ldisc "ppp_sync" didn't support this. So we call n_tty_ioctl + * in the driver ioctl function. (remember: driver ioctl function is + * only called if ldisc ioctl function did not handle the call) + * * Revision 1.39 2000/07/24 13:42:50 calle * - lock_kernel/unlock_kernel for _release functions. (from 2.4) * @@ -211,8 +232,8 @@ #include #include #include -#include #include +#include #include "capiutil.h" #include "capicmd.h" #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE @@ -220,7 +241,7 @@ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include -static char *revision = "$Revision: 1.39 $"; +static char *revision = "$Revision: 1.44 $"; MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)"); @@ -1667,7 +1688,13 @@ int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg) { - return -ENOIOCTLCMD; + int error = 0; + switch (cmd) { + default: + error = n_tty_ioctl (tty, file, cmd, arg); + break; + } + return error; } void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old) @@ -1960,7 +1987,7 @@ /* -------- init function and module interface ---------------------- */ -static void alloc_exit(void) +static void __exit alloc_exit(void) { if (capidev_cachep) { (void)kmem_cache_destroy(capidev_cachep); @@ -2060,7 +2087,7 @@ static char rev[10]; -int __init capi_init(void) +static int __init capi_init(void) { char *p; @@ -2173,8 +2200,5 @@ printk(KERN_NOTICE "capi: Rev%s: unloaded\n", rev); } -#ifdef MODULE module_init(capi_init); -#endif module_exit(capi_exit); - diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/capidev.h linux/drivers/isdn/avmb1/capidev.h --- v2.4.0-test11/linux/drivers/isdn/avmb1/capidev.h Thu Mar 23 08:38:57 2000 +++ linux/drivers/isdn/avmb1/capidev.h Mon Nov 27 16:53:43 2000 @@ -1,11 +1,14 @@ /* - * $Id: capidev.h,v 1.5 2000/03/03 15:50:42 calle Exp $ + * $Id: capidev.h,v 1.6 2000/11/25 17:00:59 kai Exp $ * * CAPI 2.0 Interface for Linux * * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidev.h,v $ + * Revision 1.6 2000/11/25 17:00:59 kai + * compatibility cleanup - final part for the time being + * * Revision 1.5 2000/03/03 15:50:42 calle * - kernel CAPI: * - Changed parameter "param" in capi_signal from __u32 to void *. diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/capidrv.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/capidrv.c Mon Nov 27 16:53:43 2000 @@ -1,11 +1,23 @@ /* - * $Id: capidrv.c,v 1.36 2000/06/26 15:13:41 keil Exp $ + * $Id: capidrv.c,v 1.39 2000/11/23 20:45:14 kai Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capidrv.c,v $ + * Revision 1.39 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.38 2000/11/14 08:43:07 calle + * Bugfix for v110. Connectparamters where setup for sync ... + * + * Revision 1.37 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.36 2000/06/26 15:13:41 keil * features should be or'ed * @@ -207,7 +219,7 @@ #include "capicmd.h" #include "capidrv.h" -static char *revision = "$Revision: 1.36 $"; +static char *revision = "$Revision: 1.39 $"; static int debugmode = 0; MODULE_AUTHOR("Carsten Paeth "); @@ -2468,7 +2480,7 @@ callback: lower_callback }; -int __init capidrv_init(void) +static int __init capidrv_init(void) { struct capi_register_params rparam; capi_profile profile; @@ -2550,8 +2562,5 @@ printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); } -#ifdef MODULE module_init(capidrv_init); -#endif module_exit(capidrv_exit); - diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/capifs.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/capifs.c Tue Nov 28 21:44:41 2000 @@ -1,11 +1,32 @@ /* - * $Id: capifs.c,v 1.10 2000/10/12 10:12:35 calle Exp $ + * $Id: capifs.c,v 1.14.6.1 2000/11/28 12:02:45 kai Exp $ * * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) * * Heavily based on devpts filesystem from H. Peter Anvin * * $Log: capifs.c,v $ + * Revision 1.14.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.14.2.1 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.14 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.13 2000/11/18 16:17:25 kai + * change from 2.4 tree + * + * Revision 1.12 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.11 2000/10/24 15:08:47 calle + * Too much includes. + * * Revision 1.10 2000/10/12 10:12:35 calle * Bugfix: second iput(inode) on umount, destroies a foreign inode. * @@ -72,7 +93,7 @@ MODULE_AUTHOR("Carsten Paeth "); -static char *revision = "$Revision: 1.10 $"; +static char *revision = "$Revision: 1.14.6.1 $"; struct capifs_ncci { struct inode *inode; @@ -558,7 +579,7 @@ } } -int __init capifs_init(void) +static int __init capifs_init(void) { char rev[10]; char *p; @@ -587,7 +608,7 @@ return 0; } -void capifs_exit(void) +static void __exit capifs_exit(void) { unregister_filesystem(&capifs_fs_type); } @@ -595,16 +616,5 @@ EXPORT_SYMBOL(capifs_new_ncci); EXPORT_SYMBOL(capifs_free_ncci); -#ifdef MODULE - -int init_module(void) -{ - return capifs_init(); -} - -void cleanup_module(void) -{ - capifs_exit(); -} - -#endif +module_init(capifs_init); +module_exit(capifs_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/capiutil.c linux/drivers/isdn/avmb1/capiutil.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/capiutil.c Thu Mar 23 08:38:57 2000 +++ linux/drivers/isdn/avmb1/capiutil.c Tue Nov 28 21:43:13 2000 @@ -1,5 +1,5 @@ /* - * $Id: capiutil.c,v 1.11 2000/03/03 15:50:42 calle Exp $ + * $Id: capiutil.c,v 1.13 2000/11/23 20:45:14 kai Exp $ * * CAPI 2.0 convert capi message to capi message struct * @@ -7,6 +7,15 @@ * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: capiutil.c,v $ + * Revision 1.13 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.12 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.11 2000/03/03 15:50:42 calle * - kernel CAPI: * - Changed parameter "param" in capi_signal from __u32 to void *. @@ -81,6 +90,7 @@ #include #include #include +#include #include #include @@ -978,7 +988,6 @@ return buf; } - EXPORT_SYMBOL(capi_cmsg2message); EXPORT_SYMBOL(capi_message2cmsg); EXPORT_SYMBOL(capi_cmsg_header); @@ -987,15 +996,14 @@ EXPORT_SYMBOL(capi_message2str); EXPORT_SYMBOL(capi_info2str); -#ifdef MODULE - -int init_module(void) -{ - return 0; +static int __init capiutil_init(void) +{ + return 0; } -void cleanup_module(void) +static void __exit capiutil_exit(void) { } -#endif +module_init(capiutil_init); +module_exit(capiutil_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/kcapi.c Mon Jul 24 18:48:49 2000 +++ linux/drivers/isdn/avmb1/kcapi.c Wed Dec 6 12:06:18 2000 @@ -1,11 +1,23 @@ /* - * $Id: kcapi.c,v 1.18 2000/07/20 10:22:27 calle Exp $ + * $Id: kcapi.c,v 1.21 2000/11/23 20:45:14 kai Exp $ * * Kernel CAPI 2.0 Module * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: kcapi.c,v $ + * Revision 1.21 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.20 2000/11/19 17:01:53 kai + * compatibility cleanup - part 2 + * + * Revision 1.19 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.18 2000/07/20 10:22:27 calle * - Made procfs function cleaner and removed variable "begin". * @@ -18,7 +30,7 @@ * Revision 1.15 2000/04/06 15:01:25 calle * Bugfix: crash in capidrv.c when reseting a capi controller. * - changed code order on remove of controller. - * - using tq_schedule for notifier in kcapi.c. + * - using tq schedule for notifier in kcapi.c. * - now using spin_lock_irqsave() and spin_unlock_irqrestore(). * strange: sometimes even MP hang on unload of isdn.o ... * @@ -110,6 +122,7 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" @@ -118,7 +131,7 @@ #include #endif -static char *revision = "$Revision: 1.18 $"; +static char *revision = "$Revision: 1.21 $"; /* ------------------------------------------------------------- */ @@ -617,7 +630,9 @@ * of devices. Devices can only removed in * user process, not in bh. */ - queue_task(&tq_state_notify, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&tq_state_notify) == 0) + MOD_DEC_USE_COUNT; return 0; } @@ -713,6 +728,7 @@ kfree(np); MOD_DEC_USE_COUNT; } + MOD_DEC_USE_COUNT; } /* -------- NCCI Handling ------------------------------------- */ @@ -1724,36 +1740,11 @@ EXPORT_SYMBOL(attach_capi_driver); EXPORT_SYMBOL(detach_capi_driver); -#ifndef MODULE -#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA -extern int b1isa_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI -extern int b1pci_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA -extern int t1isa_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA -extern int b1pcmcia_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI -extern int t1pci_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_C4 -extern int c4_init(void); -#endif -#endif - /* * init / exit functions */ -#ifdef MODULE -#define kcapi_init init_module -#endif - -int kcapi_init(void) +static int __init kcapi_init(void) { char *p; char rev[10]; @@ -1761,7 +1752,6 @@ MOD_INC_USE_COUNT; skb_queue_head_init(&recv_queue); - /* init_bh(CAPI_BH, do_capi_bh); */ tq_state_notify.routine = notify_handler; tq_state_notify.data = 0; @@ -1782,31 +1772,12 @@ printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev); #else printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - (void)b1isa_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - (void)b1pci_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - (void)t1isa_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - (void)b1pcmcia_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - (void)t1pci_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_C4 - (void)c4_init(); -#endif #endif MOD_DEC_USE_COUNT; return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit kcapi_exit(void) { char rev[10]; char *p; @@ -1822,4 +1793,6 @@ proc_capi_exit(); printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev); } -#endif + +module_init(kcapi_init); +module_exit(kcapi_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/t1isa.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/t1isa.c Tue Nov 28 21:43:13 2000 @@ -1,11 +1,15 @@ /* - * $Id: t1isa.c,v 1.15 2000/11/01 14:05:02 calle Exp $ + * $Id: t1isa.c,v 1.16 2000/11/23 20:45:14 kai Exp $ * * Module for AVM T1 HEMA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1isa.c,v $ + * Revision 1.16 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * * Revision 1.15 2000/11/01 14:05:02 calle * - use module_init/module_exit from linux/init.h. * - all static struct variables are initialized with "membername:" now. @@ -100,7 +104,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.15 $"; +static char *revision = "$Revision: 1.16 $"; /* ------------------------------------------------------------- */ @@ -613,12 +617,7 @@ add_card: t1isa_add_card, }; -#ifdef MODULE -#define t1isa_init init_module -void cleanup_module(void); -#endif - -int t1isa_init(void) +static int __init t1isa_init(void) { struct capi_driver *driver = &t1isa_driver; char *p; @@ -646,9 +645,10 @@ return retval; } -#ifdef MODULE -void cleanup_module(void) +static void __exit t1isa_exit(void) { detach_capi_driver(&t1isa_driver); } -#endif + +module_init(t1isa_init); +module_exit(t1isa_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c --- v2.4.0-test11/linux/drivers/isdn/avmb1/t1pci.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/avmb1/t1pci.c Tue Nov 28 21:44:41 2000 @@ -1,11 +1,30 @@ /* - * $Id: t1pci.c,v 1.11 2000/08/08 09:24:19 calle Exp $ + * $Id: t1pci.c,v 1.13.6.1 2000/11/28 12:02:45 kai Exp $ * * Module for AVM T1 PCI-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1pci.c,v $ + * Revision 1.13.6.1 2000/11/28 12:02:45 kai + * MODULE_DEVICE_TABLE for 2.4 + * + * Revision 1.13.2.2 2000/11/26 17:47:53 kai + * added PCI_DEV_TABLE for 2.4 + * + * Revision 1.13.2.1 2000/11/26 17:14:19 kai + * fix device ids + * also needs patches to include/linux/pci_ids.h + * + * Revision 1.13 2000/11/23 20:45:14 kai + * fixed module_init/exit stuff + * Note: compiled-in kernel doesn't work pre 2.2.18 anymore. + * + * Revision 1.12 2000/11/01 14:05:02 calle + * - use module_init/module_exit from linux/init.h. + * - all static struct variables are initialized with "membername:" now. + * - avm_cs.c, let it work with newer pcmcia-cs. + * * Revision 1.11 2000/08/08 09:24:19 calle * calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI * @@ -62,29 +81,26 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.11 $"; +static char *revision = "$Revision: 1.13.6.1 $"; #undef CONFIG_T1PCI_DEBUG #undef CONFIG_T1PCI_POLLDEBUG /* ------------------------------------------------------------- */ -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif - -#ifndef PCI_DEVICE_ID_AVM_T1 -#define PCI_DEVICE_ID_AVM_T1 0x1200 -#endif - -/* ------------------------------------------------------------- */ +static struct pci_device_id t1pci_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl); MODULE_AUTHOR("Carsten Paeth "); /* ------------------------------------------------------------- */ @@ -275,14 +291,9 @@ add_card: 0, /* no add_card function */ }; -#ifdef MODULE -#define t1pci_init init_module -void cleanup_module(void); -#endif - static int ncards = 0; -int t1pci_init(void) +static int __init t1pci_init(void) { struct capi_driver *driver = &t1pci_driver; struct pci_dev *dev = NULL; @@ -320,7 +331,7 @@ struct capicardparams param; param.port = pci_resource_start(dev, 1); - param.irq = dev->irq; + param.irq = dev->irq; param.membase = pci_resource_start(dev, 0); retval = pci_enable_device (dev); @@ -364,9 +375,10 @@ #endif } -#ifdef MODULE -void cleanup_module(void) +static void __exit t1pci_exit(void) { detach_capi_driver(&t1pci_driver); } -#endif + +module_init(t1pci_init); +module_exit(t1pci_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c --- v2.4.0-test11/linux/drivers/isdn/divert/divert_procfs.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/divert/divert_procfs.c Mon Nov 27 16:53:43 2000 @@ -1,5 +1,5 @@ /* - * $Id: divert_procfs.c,v 1.10 2000/11/13 22:51:47 kai Exp $ + * $Id: divert_procfs.c,v 1.11 2000/11/25 17:01:00 kai Exp $ * * Filesystem handling for the diversion supplementary services. * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/amd7930.c linux/drivers/isdn/hisax/amd7930.c --- v2.4.0-test11/linux/drivers/isdn/hisax/amd7930.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/amd7930.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: amd7930.c,v 1.4 2000/06/26 08:59:12 keil Exp $ +/* $Id: amd7930.c,v 1.5 2000/11/24 17:05:37 kai Exp $ * * HiSax ISDN driver - chip specific routines for AMD 7930 * @@ -94,7 +94,7 @@ #include "rawhdlc.h" #include -static const char *amd7930_revision = "$Revision: 1.4 $"; +static const char *amd7930_revision = "$Revision: 1.5 $"; #define RCV_BUFSIZE 1024 /* Size of raw receive buffer in bytes */ #define RCV_BUFBLKS 4 /* Number of blocks to divide buffer into @@ -734,8 +734,8 @@ return(0); } -__initfunc(int -setup_amd7930(struct IsdnCard *card)) +int __init +setup_amd7930(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/arcofi.c linux/drivers/isdn/hisax/arcofi.c --- v2.4.0-test11/linux/drivers/isdn/hisax/arcofi.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/arcofi.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: arcofi.c,v 1.11 2000/06/26 08:59:12 keil Exp $ +/* $Id: arcofi.c,v 1.12 2000/11/25 17:01:00 kai Exp $ * * arcofi.c Ansteuerung ARCOFI 2165 * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/asuscom.c linux/drivers/isdn/hisax/asuscom.c --- v2.4.0-test11/linux/drivers/isdn/hisax/asuscom.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/asuscom.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: asuscom.c,v 1.10 2000/06/26 08:59:12 keil Exp $ +/* $Id: asuscom.c,v 1.11 2000/11/24 17:05:37 kai Exp $ * * asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * @@ -11,6 +11,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "ipac.h" @@ -19,7 +20,7 @@ extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.10 $"; +const char *Asuscom_revision = "$Revision: 1.11 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -306,8 +307,8 @@ return(0); } -__initfunc(int -setup_asuscom(struct IsdnCard *card)) +int __init +setup_asuscom(struct IsdnCard *card) { int bytecnt; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/avm_a1.c linux/drivers/isdn/hisax/avm_a1.c --- v2.4.0-test11/linux/drivers/isdn/hisax/avm_a1.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/avm_a1.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: avm_a1.c,v 2.12 2000/06/26 08:59:12 keil Exp $ +/* $Id: avm_a1.c,v 2.13 2000/11/24 17:05:37 kai Exp $ * * avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards * @@ -8,13 +8,14 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -static const char *avm_revision = "$Revision: 2.12 $"; +static const char *avm_revision = "$Revision: 2.13 $"; #define AVM_A1_STAT_ISAC 0x01 #define AVM_A1_STAT_HSCX 0x02 @@ -171,8 +172,8 @@ return(0); } -__initfunc(int -setup_avm_a1(struct IsdnCard *card)) +int __init +setup_avm_a1(struct IsdnCard *card) { u_char val; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/avm_a1p.c linux/drivers/isdn/hisax/avm_a1p.c --- v2.4.0-test11/linux/drivers/isdn/hisax/avm_a1p.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/avm_a1p.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: avm_a1p.c,v 2.6 2000/06/26 08:59:12 keil Exp $ +/* $Id: avm_a1p.c,v 2.7 2000/11/24 17:05:37 kai Exp $ * * avm_a1p.c low level stuff for the following AVM cards: * A1 PCMCIA @@ -10,6 +10,7 @@ * This file is (c) under GNU PUBLIC LICENSE */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" @@ -52,7 +53,7 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static const char *avm_revision = "$Revision: 2.6 $"; +static const char *avm_revision = "$Revision: 2.7 $"; static inline u_char ReadISAC(struct IsdnCardState *cs, u_char offset) @@ -244,8 +245,8 @@ return 0; } -__initfunc(int -setup_avm_a1_pcmcia(struct IsdnCard *card)) +int __devinit +setup_avm_a1_pcmcia(struct IsdnCard *card) { u_char model, vers; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/avm_pci.c linux/drivers/isdn/hisax/avm_pci.c --- v2.4.0-test11/linux/drivers/isdn/hisax/avm_pci.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/hisax/avm_pci.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.18 2000/08/20 07:34:04 keil Exp $ +/* $Id: avm_pci.c,v 1.22.6.2 2000/11/29 16:00:14 kai Exp $ * * avm_pci.c low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * Thanks to AVM, Berlin for informations @@ -10,6 +10,7 @@ */ #define __NO_VERSION__ #include +#include #include "hisax.h" #include "isac.h" #include "isdnl1.h" @@ -17,18 +18,11 @@ #include extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.18 $"; +static const char *avm_pci_rev = "$Revision: 1.22.6.2 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif -#ifndef PCI_DEVICE_ID_AVM_FRITZ -#define PCI_DEVICE_ID_AVM_FRITZ 0xa00 -#endif - #define HDLC_FIFO 0x0 #define HDLC_STATUS 0x4 @@ -649,8 +643,8 @@ return (0); } -HISAX_INITFUNC(void -clear_pending_hdlc_ints(struct IsdnCardState *cs)) +void __init +clear_pending_hdlc_ints(struct IsdnCardState *cs) { u_int val; @@ -679,8 +673,8 @@ } } -HISAX_INITFUNC(void -inithdlc(struct IsdnCardState *cs)) +void __init +inithdlc(struct IsdnCardState *cs) { cs->bcs[0].BC_SetStack = setstack_hdlc; cs->bcs[1].BC_SetStack = setstack_hdlc; @@ -764,10 +758,10 @@ return(0); } -static struct pci_dev *dev_avm __initdata = NULL; +static struct pci_dev *dev_avm __initdata = NULL; -__initfunc(int -setup_avm_pcipnp(struct IsdnCard *card)) +int __init +setup_avm_pcipnp(struct IsdnCard *card) { u_int val, ver; struct IsdnCardState *cs = card->cs; @@ -788,7 +782,7 @@ return(0); } if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, - PCI_DEVICE_ID_AVM_FRITZ, dev_avm))) { + PCI_DEVICE_ID_AVM_A1, dev_avm))) { cs->irq = dev_avm->irq; if (!cs->irq) { printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/bkm_a4t.c linux/drivers/isdn/hisax/bkm_a4t.c --- v2.4.0-test11/linux/drivers/isdn/hisax/bkm_a4t.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/hisax/bkm_a4t.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: bkm_a4t.c,v 1.11 2000/06/26 08:59:12 keil Exp $ +/* $Id: bkm_a4t.c,v 1.13.6.2 2000/11/29 16:00:14 kai Exp $ * bkm_a4t.c low level stuff for T-Berkom A4T * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -13,6 +13,7 @@ #define __NO_VERSION__ #include +#include #include "hisax.h" #include "isac.h" #include "hscx.h" @@ -23,7 +24,7 @@ extern const char *CardType[]; -const char *bkm_a4t_revision = "$Revision: 1.11 $"; +const char *bkm_a4t_revision = "$Revision: 1.13.6.2 $"; static inline u_char @@ -265,8 +266,8 @@ static struct pci_dev *dev_a4t __initdata = NULL; -__initfunc(int - setup_bkm_a4t(struct IsdnCard *card)) +int __init +setup_bkm_a4t(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -294,7 +295,7 @@ sub_vendor = dev_a4t->subsystem_vendor; sub_sys = dev_a4t->subsystem_device; - if ((sub_sys == A4T_SUBSYS_ID) && (sub_vendor == A4T_SUBVEN_ID)) { + if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { if (pci_enable_device(dev_a4t)) return(0); found = 1; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/bkm_a8.c linux/drivers/isdn/hisax/bkm_a8.c --- v2.4.0-test11/linux/drivers/isdn/hisax/bkm_a8.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/hisax/bkm_a8.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: bkm_a8.c,v 1.12 2000/06/26 08:59:12 keil Exp $ +/* $Id: bkm_a8.c,v 1.14.6.2 2000/11/29 16:00:14 kai Exp $ * bkm_a8.c low level stuff for Scitel Quadro (4*S0, passive) * derived from the original file sedlbauer.c * derived from the original file niccy.c @@ -12,6 +12,7 @@ #define __NO_VERSION__ #include +#include #include "hisax.h" #include "isac.h" #include "ipac.h" @@ -26,7 +27,7 @@ extern const char *CardType[]; -const char sct_quadro_revision[] = "$Revision: 1.12 $"; +const char sct_quadro_revision[] = "$Revision: 1.14.6.2 $"; static const char *sct_quadro_subtypes[] = { @@ -268,8 +269,8 @@ return (0); } -__initfunc(int -sct_alloc_io(u_int adr, u_int len)) +int __init +sct_alloc_io(u_int adr, u_int len) { if (check_region(adr, len)) { printk(KERN_WARNING @@ -291,8 +292,8 @@ #endif /* CONFIG_PCI */ -__initfunc(int -setup_sct_quadro(struct IsdnCard *card)) +int __init +setup_sct_quadro(struct IsdnCard *card) { #if CONFIG_PCI struct IsdnCardState *cs = card->cs; @@ -316,8 +317,8 @@ CardType[card->typ]); return (0); } - if ((cs->subtyp != SCT_1) && ((sub_sys_id != SCT_SUBSYS_ID) || - (sub_vendor_id != SCT_SUBVEN_ID))) + if ((cs->subtyp != SCT_1) && ((sub_sys_id != PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) || + (sub_vendor_id != PCI_VENDOR_ID_BERKOM))) return (0); if (cs->subtyp == SCT_1) { if (!pci_present()) { @@ -329,8 +330,8 @@ sub_vendor_id = dev_a8->subsystem_vendor; sub_sys_id = dev_a8->subsystem_device; - if ((sub_sys_id == SCT_SUBSYS_ID) && - (sub_vendor_id == SCT_SUBVEN_ID)) { + if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) && + (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) { if (pci_enable_device(dev_a8)) return(0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/bkm_ax.h linux/drivers/isdn/hisax/bkm_ax.h --- v2.4.0-test11/linux/drivers/isdn/hisax/bkm_ax.h Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/hisax/bkm_ax.h Tue Nov 28 21:44:41 2000 @@ -1,4 +1,4 @@ -/* $Id: bkm_ax.h,v 1.4 2000/06/26 08:59:12 keil Exp $ +/* $Id: bkm_ax.h,v 1.5.6.1 2000/11/28 12:02:46 kai Exp $ * bkm_ax.h low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive) * * Author Roland Klabunde (R.Klabunde@Berkom.de) @@ -16,27 +16,6 @@ #define SCT_3 3 #define SCT_4 4 #define BKM_A4T 5 - - -/* A4T */ -#ifndef PCI_VENDOR_ID_ZORAN -#define PCI_VENDOR_ID_ZORAN 0x11DE -#endif -#ifndef PCI_DEVICE_ID_ZORAN_36120 -#define PCI_DEVICE_ID_ZORAN_36120 0x6120 -#endif -#define A4T_SUBVEN_ID 0x0871 -#define A4T_SUBSYS_ID 0xFFA4 -/* Scitel Quadro */ -#ifndef PCI_VENDOR_ID_PLX -#define PCI_VENDOR_ID_PLX 0x10B5 -#endif -#ifndef PCI_DEVICE_ID_PLX_9050 -#define PCI_DEVICE_ID_PLX_9050 0x9050 -#endif -#define SCT_SUBVEN_ID 0x0871 -#define SCT_SUBSYS_ID 0xFFA8 - #define PLX_ADDR_PLX 0x14 /* Addr PLX configuration */ #define PLX_ADDR_ISAC 0x18 /* Addr ISAC */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/callc.c linux/drivers/isdn/hisax/callc.c --- v2.4.0-test11/linux/drivers/isdn/hisax/callc.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/hisax/callc.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.47 2000/06/26 08:59:12 keil Exp $ +/* $Id: callc.c,v 2.51 2000/11/24 17:05:37 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -11,8 +11,8 @@ * Fritz Elfert * */ - #define __NO_VERSION__ +#include #include "hisax.h" #include "../avmb1/capicmd.h" /* this should be moved in a common place */ @@ -20,7 +20,7 @@ #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module)) #endif /* MODULE */ -const char *lli_revision = "$Revision: 2.47 $"; +const char *lli_revision = "$Revision: 2.51 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -30,10 +30,8 @@ static int init_b_st(struct Channel *chanp, int incoming); static void release_b_st(struct Channel *chanp); -static struct Fsm callcfsm = -{NULL, 0, 0, NULL, NULL}; - -static int chancount = 0; +static struct Fsm callcfsm; +static int chancount; /* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */ #define ALERT_REJECT 0 @@ -782,7 +780,7 @@ } /* *INDENT-OFF* */ -static struct FsmNode fnlist[] HISAX_INITDATA = +static struct FsmNode fnlist[] __initdata = { {ST_NULL, EV_DIAL, lli_prep_dialout}, {ST_NULL, EV_RESUME, lli_resume}, @@ -852,8 +850,8 @@ #define FNCOUNT (sizeof(fnlist)/sizeof(struct FsmNode)) -HISAX_INITFUNC(void -CallcNew(void)) +void __init +CallcNew(void) { callcfsm.state_count = STATE_COUNT; callcfsm.event_count = EVENT_COUNT; @@ -880,6 +878,7 @@ releasestack_isdnl2(st); break; case (ISDN_PROTO_L2_HDLC): + case (ISDN_PROTO_L2_HDLC_56K): case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): @@ -1273,6 +1272,9 @@ case (ISDN_PROTO_L2_HDLC): st->l1.mode = L1_MODE_HDLC; break; + case (ISDN_PROTO_L2_HDLC_56K): + st->l1.mode = L1_MODE_HDLC_56K; + break; case (ISDN_PROTO_L2_TRANS): st->l1.mode = L1_MODE_TRANS; break; @@ -1309,6 +1311,7 @@ st->l2.debug = chanp->debug & 64; break; case (ISDN_PROTO_L2_HDLC): + case (ISDN_PROTO_L2_HDLC_56K): case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c --- v2.4.0-test11/linux/drivers/isdn/hisax/config.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hisax/config.c Mon Dec 11 12:39:45 2000 @@ -1,4 +1,4 @@ -/* $Id: config.c,v 2.50 2000/07/04 10:24:32 keil Exp $ +/* $Id: config.c,v 2.57.6.3 2000/11/29 17:48:59 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -11,6 +11,7 @@ #include #include #include +#include #include "hisax.h" #include #include @@ -66,6 +67,7 @@ * 36 Winbond 6692 PCI none * 37 HFC 2BDS0 S+/SP p0=irq p1=iobase * 38 Travers Technologies NETspider-U PCI card + * 39 HFC 2BDS0-SP PCMCIA p0=irq p1=iobase * * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1 * @@ -81,7 +83,7 @@ "AMD 7930", "NICCY", "S0Box", "AVM A1 (PCMCIA)", "AVM Fritz PnP/PCI", "Sedlbauer Speed Fax +", "Siemens I-Surf", "Acer P10", "HST Saphir", "Telekom A4T", "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692", - "HFC 2BDS0 SX", "NETspider-U", + "HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA", }; void HiSax_closecard(int cardnr); @@ -221,6 +223,8 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_HFC_SX #define DEFAULT_CFG {5,0x2E0,0,0} +int hfc_init_pcmcia(void*, int, int*, int); +EXPORT_SYMBOL(hfc_init_pcmcia); #endif @@ -336,18 +340,14 @@ EMPTY_CARD, }; -static char HiSaxID[64] HISAX_INITDATA = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \ -"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" \ -"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -char *HiSax_id HISAX_INITDATA = HiSaxID; +static char HiSaxID[64] __devinitdata = { 0, }; + +char *HiSax_id __devinitdata = HiSaxID; #ifdef MODULE /* Variables for insmod */ -static int type[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; -static int protocol[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; -static int io[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; +static int type[8] __devinitdata = { 0, }; +static int protocol[8] __devinitdata = { 0, }; +static int io[8] __devinitdata = { 0, }; #undef IO0_IO1 #ifdef CONFIG_HISAX_16_3 #define IO0_IO1 @@ -357,16 +357,12 @@ #define IO0_IO1 #endif #ifdef IO0_IO1 -static int io0[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; -static int io1[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; -#endif -static int irq[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; -static int mem[] HISAX_INITDATA = -{0, 0, 0, 0, 0, 0, 0, 0}; -static char *id HISAX_INITDATA = HiSaxID; +static int io0[8] __devinitdata = { 0, }; +static int io1[8] __devinitdata = { 0, }; +#endif +static int irq[8] __devinitdata = { 0, }; +static int mem[8] __devinitdata = { 0, }; +static char *id __devinitdata = HiSaxID; MODULE_AUTHOR("Karsten Keil"); MODULE_PARM(type, "1-8i"); @@ -389,8 +385,8 @@ extern char *lli_revision; extern char *tei_revision; -HISAX_INITFUNC(char * -HiSax_getrev(const char *revision)) +char * +HiSax_getrev(const char *revision) { char *rev; char *p; @@ -404,8 +400,8 @@ return rev; } -HISAX_INITFUNC(void -HiSaxVersion(void)) +void __init +HiSaxVersion(void) { char tmp[64]; @@ -440,9 +436,7 @@ MOD_INC_USE_COUNT; } -#ifdef MODULE -#define HiSax_init init_module -#else +#ifndef MODULE #define MAX_ARG (HISAX_MAX_CARDS*5) static int __init HiSax_setup(char *line) @@ -863,7 +857,8 @@ ll_unload(csta); } -HISAX_INITFUNC(static int init_card(struct IsdnCardState *cs)) +static int __devinit +init_card(struct IsdnCardState *cs) { int irq_cnt, cnt = 3; long flags; @@ -910,8 +905,8 @@ return(3); } -HISAX_INITFUNC(static int -checkcard(int cardnr, char *id, int *busy_flag)) +static int __devinit +checkcard(int cardnr, char *id, int *busy_flag) { long flags; int ret = 0; @@ -973,6 +968,7 @@ cs->iif.features = ISDN_FEATURE_L2_X75I | ISDN_FEATURE_L2_HDLC | + ISDN_FEATURE_L2_HDLC_56K | ISDN_FEATURE_L2_TRANS | ISDN_FEATURE_L3_TRANS | #ifdef CONFIG_HISAX_1TR6 @@ -1184,7 +1180,7 @@ cs->tx_skb = NULL; cs->tx_cnt = 0; cs->event = 0; - cs->tqueue.next = 0; + INIT_LIST_HEAD(&cs->tqueue.list); cs->tqueue.sync = 0; cs->tqueue.data = cs; @@ -1208,8 +1204,8 @@ return (1); } -HISAX_INITFUNC(void -HiSax_shiftcards(int idx)) +void __devinit +HiSax_shiftcards(int idx) { int i; @@ -1217,8 +1213,8 @@ memcpy(&cards[i], &cards[i + 1], sizeof(cards[i])); } -HISAX_INITFUNC(int -HiSax_inithardware(int *busy_flag)) +int __devinit +HiSax_inithardware(int *busy_flag) { int foundcards = 0; int i = 0; @@ -1302,7 +1298,7 @@ printk(KERN_DEBUG "HiSax: HiSax_reportcard address 0x%lX\n", (ulong) & HiSax_reportcard); printk(KERN_DEBUG "HiSax: cs 0x%lX\n", (ulong) cs); - printk(KERN_DEBUG "HiSax: HW_Flags %x bc0 flg %x bc1 flg %x\n", + printk(KERN_DEBUG "HiSax: HW_Flags %lx bc0 flg %lx bc1 flg %lx\n", cs->HW_Flags, cs->bcs[0].Flag, cs->bcs[1].Flag); printk(KERN_DEBUG "HiSax: bcs 0 mode %d ch%d\n", cs->bcs[0].mode, cs->bcs[0].channel); @@ -1331,21 +1327,22 @@ #endif } - -__initfunc(int -HiSax_init(void)) +int __init +HiSax_init(void) { int i,j; + int nzproto = 0; + + HiSaxVersion(); + CallcNew(); + Isdnl3New(); + Isdnl2New(); + TeiNew(); + Isdnl1New(); #ifdef MODULE - int nzproto = 0; if (!type[0]) { /* We 'll register drivers later, but init basic functions*/ - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); - Isdnl1New(); return 0; } #ifdef CONFIG_HISAX_ELSA @@ -1366,9 +1363,14 @@ return 0; } #endif +#ifdef CONFIG_HISAX_HFC_SX + if (type[0] == ISDN_CTYPE_HFC_SP_PCMCIA) { + /* we have to export and return in this case */ + return 0; + } +#endif #endif nrcards = 0; - HiSaxVersion(); #ifdef MODULE if (id) /* If id= string used */ HiSax_id = id; @@ -1430,6 +1432,7 @@ case ISDN_CTYPE_HSTSAPHIR: case ISDN_CTYPE_GAZEL: case ISDN_CTYPE_HFC_SX: + case ISDN_CTYPE_HFC_SP_PCMCIA: cards[j].para[0] = irq[i]; cards[j].para[1] = io[i]; break; @@ -1469,7 +1472,6 @@ } if (!nzproto) { printk(KERN_WARNING "HiSax: Warning - no protocol specified\n"); - printk(KERN_WARNING "HiSax: Note! module load syntax has changed.\n"); printk(KERN_WARNING "HiSax: using protocol %s\n", DEFAULT_PROTO_NAME); } #endif @@ -1483,15 +1485,8 @@ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); - Isdnl1New(); if (HiSax_inithardware(NULL)) { /* Install only, if at least one card found */ -#ifdef MODULE -#endif /* MODULE */ return (0); } else { Isdnl1Free(); @@ -1504,6 +1499,8 @@ } #ifdef MODULE +int init_module(void) { return HiSax_init(); } + void cleanup_module(void) { @@ -1529,10 +1526,49 @@ { #ifdef MODULE int i; + + nrcards = 0; + /* Initialize all structs, even though we only accept + two pcmcia cards + */ + for (i = 0; i < HISAX_MAX_CARDS; i++) { + cards[i].para[0] = irq[i]; + cards[i].para[1] = io[i]; + cards[i].typ = type[i]; + if (protocol[i]) { + cards[i].protocol = protocol[i]; + } + } + cards[0].para[0] = pcm_irq; + cards[0].para[1] = (int)pcm_iob; + cards[0].protocol = prot; + cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA; + + if (!HiSax_id) + HiSax_id = HiSaxID; + if (!HiSaxID[0]) + strcpy(HiSaxID, "HiSax"); + for (i = 0; i < HISAX_MAX_CARDS; i++) + if (cards[i].typ > 0) + nrcards++; + printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", + nrcards, (nrcards > 1) ? "s" : ""); + + HiSax_inithardware(busy_flag); + printk(KERN_NOTICE "HiSax: module installed\n"); +#endif + return (0); +} +#endif + +#ifdef CONFIG_HISAX_HFC_SX +int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) +{ +#ifdef MODULE + int i; int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1548,7 +1584,7 @@ cards[0].para[0] = pcm_irq; cards[0].para[1] = (int)pcm_iob; cards[0].protocol = prot; - cards[0].typ = 10; + cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA; nzproto = 1; if (!HiSax_id) @@ -1561,11 +1597,6 @@ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - Isdnl1New(); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1581,7 +1612,6 @@ int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1610,11 +1640,6 @@ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - Isdnl1New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1630,7 +1655,6 @@ int nzproto = 0; nrcards = 0; - HiSaxVersion(); /* Initialize all structs, even though we only accept two pcmcia cards */ @@ -1659,11 +1683,6 @@ printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", nrcards, (nrcards > 1) ? "s" : ""); - Isdnl1New(); - CallcNew(); - Isdnl3New(); - Isdnl2New(); - TeiNew(); HiSax_inithardware(busy_flag); printk(KERN_NOTICE "HiSax: module installed\n"); #endif @@ -1671,7 +1690,7 @@ } #endif -int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) +int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) { u_char ids[16]; int ret = -1; @@ -1688,3 +1707,66 @@ nrcards++; return (ret); } + +static struct pci_device_id hisax_pci_tbl[] __initdata = { +#ifdef CONFIG_HISAX_FRTIZPCI + {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_FRITZ, PCI_ANY_ID, PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_DIEHLDIVA + {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_ELSA + {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, PCI_ANY_ID, PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_GAZEL + {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R685, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_R753, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_DJINN_ITOO, PCI_ANY_ID, PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_QUADRO + {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_ANY_ID, PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_NICCY + {PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, PCI_ANY_ID,PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_SEDLBAUER + {PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_100, PCI_ANY_ID,PCI_ANY_ID}, +#endif +#if defined(CONFIG_HISAX_NETJET) || defined(CONFIG_HISAX_NETJET_U) + {PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, PCI_ANY_ID,PCI_ANY_ID}, +#endif +#if defined(CONFIG_HISAX_TELESPCI) || defined(CONFIG_HISAX_SCT_QUADRO) + {PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, PCI_ANY_ID,PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_W6692 + {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, PCI_ANY_ID,PCI_ANY_ID}, + {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_ANY_ID,PCI_ANY_ID}, +#endif +#ifdef CONFIG_HISAX_HFC_PCI + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A, PCI_ANY_ID, PCI_ANY_ID}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A, PCI_ANY_ID, PCI_ANY_ID}, +#endif + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, hisax_pci_tbl); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/diva.c linux/drivers/isdn/hisax/diva.c --- v2.4.0-test11/linux/drivers/isdn/hisax/diva.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/diva.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.21 2000/06/26 08:59:12 keil Exp $ +/* $Id: diva.c,v 1.25.6.2 2000/11/29 16:00:14 kai Exp $ * * diva.c low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -13,6 +13,7 @@ */ #define __NO_VERSION__ +#include #include #include "hisax.h" #include "isac.h" @@ -23,7 +24,7 @@ extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.21 $"; +const char *Diva_revision = "$Revision: 1.25.6.2 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -46,20 +47,6 @@ #define DIVA_IPAC_ISA 3 #define DIVA_IPAC_PCI 4 -/* PCI stuff */ -#ifndef PCI_VENDOR_ID_EICON -#define PCI_VENDOR_ID_EICON 0x1133 -#endif -#ifndef PCI_DEVICE_ID_EICON_DIVA20 -#define PCI_DEVICE_ID_EICON_DIVA20 0xe002 -#endif -#ifndef PCI_DEVICE_ID_EICON_DIVA20_U -#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004 -#endif -#ifndef PCI_DEVICE_ID_EICON_DIVA201 -#define PCI_DEVICE_ID_EICON_DIVA201 0xe005 -#endif - /* CTRL (Read) */ #define DIVA_IRQ_STAT 0x01 #define DIVA_EEPROM_SDA 0x02 @@ -833,12 +820,12 @@ return(0); } -static struct pci_dev *dev_diva __initdata = NULL; -static struct pci_dev *dev_diva_u __initdata = NULL; -static struct pci_dev *dev_diva201 __initdata = NULL; +static struct pci_dev *dev_diva __initdata = NULL; +static struct pci_dev *dev_diva_u __initdata = NULL; +static struct pci_dev *dev_diva201 __initdata = NULL; -__initfunc(int -setup_diva(struct IsdnCard *card)) +int __init +setup_diva(struct IsdnCard *card) { int bytecnt; u_char val; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/elsa.c linux/drivers/isdn/hisax/elsa.c --- v2.4.0-test11/linux/drivers/isdn/hisax/elsa.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/elsa.c Tue Nov 28 21:44:41 2000 @@ -1,4 +1,4 @@ -/* $Id: elsa.c,v 2.23 2000/06/26 08:59:12 keil Exp $ +/* $Id: elsa.c,v 2.26.6.1 2000/11/28 12:02:46 kai Exp $ * * elsa.c low level stuff for Elsa isdn cards * @@ -16,6 +16,7 @@ */ #define __NO_VERSION__ +#include #include #include "hisax.h" #include "arcofi.h" @@ -29,7 +30,7 @@ extern const char *CardType[]; -const char *Elsa_revision = "$Revision: 2.23 $"; +const char *Elsa_revision = "$Revision: 2.26.6.1 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", @@ -66,15 +67,6 @@ #define ELSA_PCMCIA_IPAC 11 /* PCI stuff */ -#ifndef PCI_VENDOR_ID_ELSA -#define PCI_VENDOR_ID_ELSA 0x1048 -#endif -#ifndef PCI_DEVICE_ID_ELSA_MIRCOLINK -#define PCI_DEVICE_ID_ELSA_MIRCOLINK 0x1000 -#endif -#ifndef PCI_DEVICE_ID_ELSA_QS3000 -#define PCI_DEVICE_ID_ELSA_QS3000 0x3000 -#endif #define ELSA_PCI_IRQ_MASK 0x04 /* ITAC Registeradressen (only Microlink PC) */ @@ -865,10 +857,10 @@ return (CARD_portlist[i]); } -static struct pci_dev *dev_qs1000 __initdata = NULL; -static struct pci_dev *dev_qs3000 __initdata = NULL; +static struct pci_dev *dev_qs1000 __devinitdata = NULL; +static struct pci_dev *dev_qs3000 __devinitdata = NULL; -int +int __devinit setup_elsa(struct IsdnCard *card) { long flags; @@ -990,7 +982,7 @@ } cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, - PCI_DEVICE_ID_ELSA_MIRCOLINK, dev_qs1000))) { + PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { if (pci_enable_device(dev_qs1000)) return(0); cs->subtyp = ELSA_QS1000PCI; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/elsa_ser.c linux/drivers/isdn/hisax/elsa_ser.c --- v2.4.0-test11/linux/drivers/isdn/hisax/elsa_ser.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/elsa_ser.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: elsa_ser.c,v 2.9 2000/06/26 08:59:12 keil Exp $ +/* $Id: elsa_ser.c,v 2.10 2000/11/19 17:02:47 kai Exp $ * * stuff for the serial modem on ELSA cards * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/fsm.c linux/drivers/isdn/hisax/fsm.c --- v2.4.0-test11/linux/drivers/isdn/hisax/fsm.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/fsm.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: fsm.c,v 1.13 2000/06/26 08:59:12 keil Exp $ +/* $Id: fsm.c,v 1.14 2000/11/24 17:05:37 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -10,13 +10,13 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #define FSM_TIMER_DEBUG 0 -HISAX_INITFUNC(void -FsmNew(struct Fsm *fsm, - struct FsmNode *fnlist, int fncount)) +void __init +FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount) { int i; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/gazel.c linux/drivers/isdn/hisax/gazel.c --- v2.4.0-test11/linux/drivers/isdn/hisax/gazel.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/gazel.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: gazel.c,v 2.8 2000/06/26 08:59:12 keil Exp $ +/* $Id: gazel.c,v 2.11.6.2 2000/11/29 16:00:14 kai Exp $ * * gazel.c low level stuff for Gazel isdn cards * @@ -9,6 +9,7 @@ * */ #include +#include #define __NO_VERSION__ #include "hisax.h" #include "isac.h" @@ -18,27 +19,13 @@ #include extern const char *CardType[]; -const char *gazel_revision = "$Revision: 2.8 $"; +const char *gazel_revision = "$Revision: 2.11.6.2 $"; #define R647 1 #define R685 2 #define R753 3 #define R742 4 -/* Gazel R685 stuff */ -#ifndef PCI_VENDOR_ID_PLX -#define PCI_VENDOR_ID_PLX 0x10b5 -#endif -#ifndef PCI_DEVICE_ID_PLX_R685 -#define PCI_DEVICE_ID_PLX_R685 0x1030 -#endif -#ifndef PCI_DEVICE_ID_PLX_R753 -#define PCI_DEVICE_ID_PLX_R753 0x1152 -#endif -#ifndef PCI_DEVICE_ID_PLX_DJINN_ITOO -#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151 -#endif - #define PLX_CNTRL 0x50 /* registre de controle PLX */ #define RESET_GAZEL 0x4 #define RESET_9050 0x40000000 @@ -645,8 +632,8 @@ return (0); } -__initfunc(int - setup_gazel(struct IsdnCard *card)) +int __init +setup_gazel(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hfc_2bds0.c linux/drivers/isdn/hisax/hfc_2bds0.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hfc_2bds0.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/hfc_2bds0.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.13 2000/06/26 08:59:12 keil Exp $ +/* $Id: hfc_2bds0.c,v 1.15 2000/11/24 17:05:37 kai Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -8,6 +8,7 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "hfc_2bds0.h" #include "isdnl1.h" @@ -1104,8 +1105,8 @@ { } -__initfunc(unsigned int -*init_send_hfcd(int cnt)) +unsigned int __init +*init_send_hfcd(int cnt) { int i, *send; @@ -1119,8 +1120,8 @@ return(send); } -__initfunc(void -init2bds0(struct IsdnCardState *cs)) +void __init +init2bds0(struct IsdnCardState *cs) { cs->setstack_d = setstack_hfcd; cs->dbusytimer.function = (void *) hfc_dbusy_timer; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hfc_2bs0.c linux/drivers/isdn/hisax/hfc_2bs0.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hfc_2bs0.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/hfc_2bs0.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.15 2000/07/26 20:46:47 keil Exp $ +/* $Id: hfc_2bs0.c,v 1.17 2000/11/24 17:05:37 kai Exp $ * * specific routines for CCD's HFC 2BS0 * @@ -9,6 +9,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "hfc_2bs0.h" #include "isac.h" @@ -570,8 +571,8 @@ return (0); } -__initfunc(void -init_send(struct BCState *bcs)) +void __init +init_send(struct BCState *bcs) { int i; @@ -584,8 +585,8 @@ bcs->hw.hfc.send[i] = 0x1fff; } -__initfunc(void -inithfc(struct IsdnCardState *cs)) +void __init +inithfc(struct IsdnCardState *cs) { init_send(&cs->bcs[0]); init_send(&cs->bcs[1]); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hfc_pci.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hisax/hfc_pci.c Tue Nov 28 21:44:41 2000 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.31 2000/08/20 07:32:55 keil Exp $ +/* $Id: hfc_pci.c,v 1.34.6.2 2000/11/28 12:02:46 kai Exp $ * hfc_pci.c low level driver for CCD´s hfc-pci based cards * @@ -24,6 +24,7 @@ * */ +#include #include #define __NO_VERSION__ #include "hisax.h" @@ -31,11 +32,10 @@ #include "isdnl1.h" #include #include -#include extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.31 $"; +static const char *hfcpci_revision = "$Revision: 1.34.6.2 $"; /* table entry in the PCI devices list */ typedef struct { @@ -51,25 +51,25 @@ static const PCI_ENTRY id_list[] = { - {0x1397, 0x2BD0, "CCD/Billion/Asuscom", "2BD0"}, - {0x1397, 0xB000, "Billion", "B000"}, - {0x1397, 0xB006, "Billion", "B006"}, - {0x1397, 0xB007, "Billion", "B007"}, - {0x1397, 0xB008, "Billion", "B008"}, - {0x1397, 0xB009, "Billion", "B009"}, - {0x1397, 0xB00A, "Billion", "B00A"}, - {0x1397, 0xB00B, "Billion", "B00B"}, - {0x1397, 0xB00C, "Billion", "B00C"}, - {0x1043, 0x0675, "Asuscom/Askey", "675"}, - {0x0871, 0xFFA2, "German telekom", "T-Concept"}, - {0x0871, 0xFFA1, "German telekom", "A1T"}, - {0x1051, 0x0100, "Motorola MC145575", "MC145575"}, - {0x1397, 0xB100, "Seyeon", "B100"}, - {0x15B0, 0x2BD0, "Zoltrix", "2BD0"}, - {0x114F, 0x70,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"}, - {0x114F, 0x71,"Digi International", "Digi DataFire Micro V (Europe)"}, - {0x114F, 0x72,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, - {0x114F, 0x73,"Digi International", "Digi DataFire Micro V (North America)"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"}, + {PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"}, + {PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"}, + {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"}, + {PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"}, + {PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"}, + {PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E,"Digi International", "Digi DataFire Micro V IOM2 (Europe)"}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E,"Digi International", "Digi DataFire Micro V (Europe)"}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A,"Digi International", "Digi DataFire Micro V IOM2 (North America)"}, + {PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A,"Digi International", "Digi DataFire Micro V (North America)"}, {0, 0, NULL, NULL}, }; @@ -1571,8 +1571,8 @@ /********************************/ /* called for card init message */ /********************************/ -__initfunc(void - inithfcpci(struct IsdnCardState *cs)) +void __init +inithfcpci(struct IsdnCardState *cs) { cs->setstack_d = setstack_hfcpci; cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hfc_sx.c linux/drivers/isdn/hisax/hfc_sx.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hfc_sx.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/hfc_sx.c Tue Nov 28 21:43:13 2000 @@ -1,4 +1,4 @@ -/* $Id: hfc_sx.c,v 1.6 2000/06/26 08:59:13 keil Exp $ +/* $Id: hfc_sx.c,v 1.9 2000/11/24 17:05:37 kai Exp $ * hfc_sx.c low level driver for CCD´s hfc-s+/sp based cards * @@ -24,6 +24,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "hfc_sx.h" #include "isdnl1.h" @@ -31,7 +32,7 @@ extern const char *CardType[]; -static const char *hfcsx_revision = "$Revision: 1.6 $"; +static const char *hfcsx_revision = "$Revision: 1.9 $"; /***************************************/ /* IRQ-table for CCDs demo board */ @@ -1415,8 +1416,8 @@ /********************************/ /* called for card init message */ /********************************/ -__initfunc(void - inithfcsx(struct IsdnCardState *cs)) +void __devinit +inithfcsx(struct IsdnCardState *cs) { cs->setstack_d = setstack_hfcsx; cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; @@ -1472,8 +1473,8 @@ -__initfunc(int - setup_hfcsx(struct IsdnCard *card)) +int __devinit +setup_hfcsx(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; @@ -1486,7 +1487,8 @@ cs->hw.hfcsx.int_s1 = 0; cs->dc.hfcsx.ph_state = 0; cs->hw.hfcsx.fifo = 255; - if (cs->typ == ISDN_CTYPE_HFC_SX) { + if ((cs->typ == ISDN_CTYPE_HFC_SX) || + (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) { if ((!cs->hw.hfcsx.base) || check_region((cs->hw.hfcsx.base), 2)) { printk(KERN_WARNING diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hfcscard.c linux/drivers/isdn/hisax/hfcscard.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hfcscard.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/hfcscard.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hfcscard.c,v 1.7 2000/06/26 08:59:13 keil Exp $ +/* $Id: hfcscard.c,v 1.8 2000/11/24 17:05:37 kai Exp $ * * hfcscard.c low level stuff for hfcs based cards (Teles3c, ACER P10) * @@ -9,13 +9,14 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "hfc_2bds0.h" #include "isdnl1.h" extern const char *CardType[]; -static const char *hfcs_revision = "$Revision: 1.7 $"; +static const char *hfcs_revision = "$Revision: 1.8 $"; static void hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) @@ -136,8 +137,8 @@ return(0); } -__initfunc(int -setup_hfcs(struct IsdnCard *card)) +int __init +setup_hfcs(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h --- v2.4.0-test11/linux/drivers/isdn/hisax/hisax.h Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/hisax.h Mon Dec 11 13:20:27 2000 @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 2.48 2000/07/04 10:24:32 keil Exp $ +/* $Id: hisax.h,v 2.52 2000/11/25 17:01:00 kai Exp $ * * Basic declarations, defines and prototypes * @@ -202,7 +202,7 @@ void *hardware; struct BCState *bcs; struct PStack **stlistp; - int Flags; + long Flags; struct FsmInst l1m; struct FsmTimer timer; void (*l1l2) (struct PStack *, int, void *); @@ -241,7 +241,7 @@ int tei; int sap; int maxlen; - unsigned int flag; + unsigned long flag; unsigned int vs, va, vr; int rc; unsigned int window; @@ -366,7 +366,7 @@ }; struct isar_reg { - unsigned int Flags; + unsigned long Flags; volatile u_char bstat; volatile u_char iis; volatile u_char cmsb; @@ -476,6 +476,7 @@ #define L1_MODE_TRANS 1 #define L1_MODE_HDLC 2 #define L1_MODE_EXTRN 3 +#define L1_MODE_HDLC_56K 4 #define L1_MODE_MODEM 7 #define L1_MODE_V32 8 #define L1_MODE_FAX 9 @@ -483,7 +484,7 @@ struct BCState { int channel; int mode; - int Flag; + long Flag; /* long req'd for set_bit --RR */ struct IsdnCardState *cs; int tx_cnt; /* B-Channel transmit counter */ struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ @@ -528,7 +529,8 @@ int data_open; struct l3_process *proc; setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ - int Flags; /* for remembering action done in l4 */ + long Flags; /* for remembering action done in l4 */ + /* long req'd for set_bit --RR */ int leased; }; @@ -865,7 +867,7 @@ int protocol; unsigned int irq; unsigned long irq_flags; - int HW_Flags; + long HW_Flags; int *busy_flag; int chanlimit; /* limited number of B-chans to use */ int logecho; /* log echo if supported by card */ @@ -932,7 +934,7 @@ int rcvidx; struct sk_buff *tx_skb; int tx_cnt; - int event; + long event; struct tq_struct tqueue; struct timer_list dbusytimer; #ifdef ERROR_STATISTIC @@ -987,24 +989,14 @@ #define ISDN_CTYPE_W6692 36 #define ISDN_CTYPE_HFC_SX 37 #define ISDN_CTYPE_NETJET_U 38 -#define ISDN_CTYPE_COUNT 38 +#define ISDN_CTYPE_HFC_SP_PCMCIA 39 +#define ISDN_CTYPE_COUNT 39 #ifdef ISDN_CHIP_ISAC #undef ISDN_CHIP_ISAC #endif -#ifndef __initfunc -#define __initfunc(__arginit) __arginit -#endif - -#ifndef __initdata -#define __initdata -#endif - -#define HISAX_INITFUNC(__arginit) __initfunc(__arginit) -#define HISAX_INITDATA __initdata - #ifdef CONFIG_HISAX_16_0 #define CARD_TELES0 1 #ifndef ISDN_CHIP_ISAC @@ -1064,10 +1056,6 @@ #ifndef ISDN_CHIP_ISAC #define ISDN_CHIP_ISAC 1 #endif -#undef HISAX_INITFUNC -#define HISAX_INITFUNC(__arginit) __arginit -#undef HISAX_INITDATA -#define HISAX_INITDATA #else #define CARD_ELSA 0 #endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hscx.c linux/drivers/isdn/hisax/hscx.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hscx.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/hscx.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hscx.c,v 1.19 2000/06/26 08:59:13 keil Exp $ +/* $Id: hscx.c,v 1.21 2000/11/24 17:05:37 kai Exp $ * * hscx.c HSCX specific routines * @@ -9,18 +9,19 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "hscx.h" #include "isac.h" #include "isdnl1.h" #include -static char *HSCXVer[] HISAX_INITDATA = +static char *HSCXVer[] __initdata = {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; -HISAX_INITFUNC(int -HscxVersion(struct IsdnCardState *cs, char *s)) +int __init +HscxVersion(struct IsdnCardState *cs, char *s) { int verA, verB; @@ -218,8 +219,8 @@ return (0); } -HISAX_INITFUNC(void -clear_pending_hscx_ints(struct IsdnCardState *cs)) +void __init +clear_pending_hscx_ints(struct IsdnCardState *cs) { int val, eval; @@ -244,8 +245,8 @@ cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF); } -HISAX_INITFUNC(void -inithscx(struct IsdnCardState *cs)) +void __init +inithscx(struct IsdnCardState *cs) { cs->bcs[0].BC_SetStack = setstack_hscx; cs->bcs[1].BC_SetStack = setstack_hscx; @@ -261,8 +262,8 @@ modehscx(cs->bcs + 1, 0, 0); } -HISAX_INITFUNC(void -inithscxisac(struct IsdnCardState *cs, int part)) +void __init +inithscxisac(struct IsdnCardState *cs, int part) { if (part & 1) { clear_pending_isac_ints(cs); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/hscx_irq.c linux/drivers/isdn/hisax/hscx_irq.c --- v2.4.0-test11/linux/drivers/isdn/hisax/hscx_irq.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/hscx_irq.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hscx_irq.c,v 1.15 2000/06/26 08:59:13 keil Exp $ +/* $Id: hscx_irq.c,v 1.16 2000/11/19 17:02:47 kai Exp $ * * hscx_irq.c low level b-channel stuff for Siemens HSCX * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/icc.c linux/drivers/isdn/hisax/icc.c --- v2.4.0-test11/linux/drivers/isdn/hisax/icc.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/icc.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -// $Id: icc.c,v 1.3 2000/08/20 07:34:04 keil Exp $ +// $Id: icc.c,v 1.5 2000/11/24 17:05:37 kai Exp $ //----------------------------------------------------------------------------- // // ICC specific routines @@ -15,6 +15,7 @@ //----------------------------------------------------------------------------- #define __NO_VERSION__ +#include #include "hisax.h" #include "icc.h" // #include "arcofi.h" @@ -24,7 +25,7 @@ #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 0 -static char *ICCVer[] HISAX_INITDATA = +static char *ICCVer[] __initdata = {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"}; void @@ -622,8 +623,8 @@ } } -HISAX_INITFUNC(void -initicc(struct IsdnCardState *cs)) +void __init +initicc(struct IsdnCardState *cs) { cs->tqueue.routine = (void *) (void *) icc_bh; cs->setstack_d = setstack_icc; @@ -659,8 +660,8 @@ ph_command(cs, ICC_CMD_DI); } -HISAX_INITFUNC(void -clear_pending_icc_ints(struct IsdnCardState *cs)) +void __init +clear_pending_icc_ints(struct IsdnCardState *cs) { int val, eval; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/isac.c linux/drivers/isdn/hisax/isac.c --- v2.4.0-test11/linux/drivers/isdn/hisax/isac.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/isac.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isac.c,v 1.26 2000/06/26 08:59:13 keil Exp $ +/* $Id: isac.c,v 1.28 2000/11/24 17:05:37 kai Exp $ * * isac.c ISAC specific routines * @@ -15,11 +15,12 @@ #include "arcofi.h" #include "isdnl1.h" #include +#include #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 1 -static char *ISACVer[] HISAX_INITDATA = +static char *ISACVer[] __devinitdata = {"2086/2186 V1.1", "2085 B1", "2085 B2", "2085 V2.3"}; @@ -620,8 +621,8 @@ } } -HISAX_INITFUNC(void -initisac(struct IsdnCardState *cs)) +void __devinit +initisac(struct IsdnCardState *cs) { cs->tqueue.routine = (void *) (void *) isac_bh; cs->setstack_d = setstack_isac; @@ -656,8 +657,8 @@ cs->writeisac(cs, ISAC_MASK, 0x0); } -HISAX_INITFUNC(void -clear_pending_isac_ints(struct IsdnCardState *cs)) +void __devinit +clear_pending_isac_ints(struct IsdnCardState *cs) { int val, eval; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/isar.c linux/drivers/isdn/hisax/isar.c --- v2.4.0-test11/linux/drivers/isdn/hisax/isar.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/isar.c Mon Nov 27 16:56:09 2000 @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.15 2000/06/26 08:59:13 keil Exp $ +/* $Id: isar.c,v 1.17 2000/11/24 17:05:37 kai Exp $ * * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -9,6 +9,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isar.h" #include "isdnl1.h" @@ -1782,8 +1783,8 @@ return(0); } -HISAX_INITFUNC(void -initisar(struct IsdnCardState *cs)) +void __devinit +initisar(struct IsdnCardState *cs) { cs->bcs[0].BC_SetStack = setstack_isar; cs->bcs[1].BC_SetStack = setstack_isar; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/isdnl1.c linux/drivers/isdn/hisax/isdnl1.c --- v2.4.0-test11/linux/drivers/isdn/hisax/isdnl1.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/isdnl1.c Mon Dec 11 12:39:45 2000 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.c,v 2.39 2000/06/26 08:59:13 keil Exp $ +/* $Id: isdnl1.c,v 2.41 2000/11/24 17:05:37 kai Exp $ * * isdnl1.c common low level stuff for Siemens Chipsetbased isdn cards * based on the teles driver from Jan den Ouden @@ -15,21 +15,17 @@ * */ -const char *l1_revision = "$Revision: 2.39 $"; +const char *l1_revision = "$Revision: 2.41 $"; #define __NO_VERSION__ +#include #include "hisax.h" #include "isdnl1.h" #define TIMER3_VALUE 7000 -static -struct Fsm l1fsm_b = -{NULL, 0, 0, NULL, NULL}; - -static -struct Fsm l1fsm_s = -{NULL, 0, 0, NULL, NULL}; +static struct Fsm l1fsm_b; +static struct Fsm l1fsm_s; enum { ST_L1_F2, @@ -347,7 +343,7 @@ bcs->cs = cs; bcs->channel = bc; - bcs->tqueue.next = 0; + INIT_LIST_HEAD(&bcs->tqueue.list); bcs->tqueue.sync = 0; bcs->tqueue.routine = (void *) (void *) BChannel_bh; bcs->tqueue.data = bcs; @@ -584,7 +580,7 @@ } } -static struct FsmNode L1SFnList[] HISAX_INITDATA = +static struct FsmNode L1SFnList[] __initdata = { {ST_L1_F3, EV_PH_ACTIVATE, l1_activate_s}, {ST_L1_F6, EV_PH_ACTIVATE, l1_activate_no}, @@ -669,7 +665,7 @@ st->l1.l1hw(st, HW_INFO1 | REQUEST, NULL); } -static struct FsmNode L1UFnList[] HISAX_INITDATA = +static struct FsmNode L1UFnList[] __initdata = { {ST_L1_RESET, EV_DEACT_IND, l1_deact_req_u}, {ST_L1_DEACT, EV_DEACT_IND, l1_deact_req_u}, @@ -731,7 +727,7 @@ st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); } -static struct FsmNode L1BFnList[] HISAX_INITDATA = +static struct FsmNode L1BFnList[] __initdata = { {ST_L1_NULL, EV_PH_ACTIVATE, l1b_activate}, {ST_L1_WAIT_ACT, EV_TIMER_ACT, l1b_timer_act}, @@ -741,7 +737,8 @@ #define L1B_FN_COUNT (sizeof(L1BFnList)/sizeof(struct FsmNode)) -HISAX_INITFUNC(void Isdnl1New(void)) +void __init +Isdnl1New(void) { #ifdef HISAX_UINTERFACE l1fsm_u.state_count = L1U_STATE_COUNT; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/isdnl2.c linux/drivers/isdn/hisax/isdnl2.c --- v2.4.0-test11/linux/drivers/isdn/hisax/isdnl2.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/isdnl2.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isdnl2.c,v 2.23 2000/06/26 08:59:13 keil Exp $ +/* $Id: isdnl2.c,v 2.25 2000/11/24 17:05:38 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -12,16 +12,15 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.23 $"; +const char *l2_revision = "$Revision: 2.25 $"; static void l2m_debug(struct FsmInst *fi, char *fmt, ...); -static -struct Fsm l2fsm = -{NULL, 0, 0, NULL, NULL}; +static struct Fsm l2fsm; enum { ST_L2_1, @@ -1535,7 +1534,7 @@ test_and_clear_bit(FLG_L3_INIT, &st->l2.flag); } -static struct FsmNode L2FnList[] HISAX_INITDATA = +static struct FsmNode L2FnList[] __initdata = { {ST_L2_1, EV_L2_DL_ESTABLISH_REQ, l2_mdl_assign}, {ST_L2_2, EV_L2_DL_ESTABLISH_REQ, l2_go_st3}, @@ -1832,8 +1831,8 @@ { } -HISAX_INITFUNC(void -Isdnl2New(void)) +void __init +Isdnl2New(void) { l2fsm.state_count = L2_STATE_COUNT; l2fsm.event_count = L2_EVENT_COUNT; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/isdnl3.c linux/drivers/isdn/hisax/isdnl3.c --- v2.4.0-test11/linux/drivers/isdn/hisax/isdnl3.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/isdnl3.c Tue Nov 28 21:43:13 2000 @@ -1,4 +1,4 @@ -/* $Id: isdnl3.c,v 2.14 2000/06/26 08:59:13 keil Exp $ +/* $Id: isdnl3.c,v 2.17 2000/11/24 17:05:38 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -11,16 +11,16 @@ * Fritz Elfert * */ + #define __NO_VERSION__ +#include #include "hisax.h" #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 2.14 $"; +const char *l3_revision = "$Revision: 2.17 $"; -static -struct Fsm l3fsm = -{NULL, 0, 0, NULL, NULL}; +static struct Fsm l3fsm; enum { ST_L3_LC_REL, @@ -303,7 +303,10 @@ if (!skb_queue_len(&p->st->l3.squeue)) { if (p->debug) l3_debug(p->st, "release_l3_process: release link"); - FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); + if (p->st->protocol != ISDN_PTYPE_NI1) + FsmEvent(&p->st->l3.l3m, EV_RELEASE_REQ, NULL); + else + FsmEvent(&p->st->l3.l3m, EV_RELEASE_IND, NULL); } else { if (p->debug) l3_debug(p->st, "release_l3_process: not release link"); @@ -483,6 +486,18 @@ } static void +lc_start_delay_check(struct FsmInst *fi, int event, void *arg) +/* 20/09/00 - GE timer not user for NI-1 as layer 2 should stay up */ +{ + struct PStack *st = fi->userdata; + + FsmChangeState(fi, ST_L3_LC_REL_DELAY); + /* 19/09/00 - GE timer not user for NI-1 */ + if (st->protocol != ISDN_PTYPE_NI1) + FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 50); +} + +static void lc_release_req(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -521,7 +536,7 @@ /* *INDENT-OFF* */ -static struct FsmNode L3FnList[] HISAX_INITDATA = +static struct FsmNode L3FnList[] __initdata = { {ST_L3_LC_REL, EV_ESTABLISH_REQ, lc_activate}, {ST_L3_LC_REL, EV_ESTABLISH_IND, lc_connect}, @@ -530,7 +545,7 @@ {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_REQ, lc_start_delay}, {ST_L3_LC_ESTAB_WAIT, EV_RELEASE_IND, lc_release_ind}, {ST_L3_LC_ESTAB, EV_RELEASE_IND, lc_release_ind}, - {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay}, + {ST_L3_LC_ESTAB, EV_RELEASE_REQ, lc_start_delay_check}, {ST_L3_LC_REL_DELAY, EV_RELEASE_IND, lc_release_ind}, {ST_L3_LC_REL_DELAY, EV_ESTABLISH_REQ, lc_connected}, {ST_L3_LC_REL_DELAY, EV_TIMEOUT, lc_release_req}, @@ -576,8 +591,8 @@ } } -HISAX_INITFUNC(void -Isdnl3New(void)) +void __init +Isdnl3New(void) { l3fsm.state_count = L3_STATE_COUNT; l3fsm.event_count = L3_EVENT_COUNT; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/isurf.c linux/drivers/isdn/hisax/isurf.c --- v2.4.0-test11/linux/drivers/isdn/hisax/isurf.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/isurf.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isurf.c,v 1.9 2000/06/26 08:59:13 keil Exp $ +/* $Id: isurf.c,v 1.10 2000/11/24 17:05:38 kai Exp $ * * isurf.c low level stuff for Siemens I-Surf/I-Talk cards * @@ -9,6 +9,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "isar.h" @@ -16,7 +17,7 @@ extern const char *CardType[]; -static const char *ISurf_revision = "$Revision: 1.9 $"; +static const char *ISurf_revision = "$Revision: 1.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -190,8 +191,8 @@ return(isar_auxcmd(cs, ic)); } -__initfunc(int -setup_isurf(struct IsdnCard *card)) +int __init +setup_isurf(struct IsdnCard *card) { int ver; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/ix1_micro.c linux/drivers/isdn/hisax/ix1_micro.c --- v2.4.0-test11/linux/drivers/isdn/hisax/ix1_micro.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/ix1_micro.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: ix1_micro.c,v 2.9 2000/06/26 08:59:13 keil Exp $ +/* $Id: ix1_micro.c,v 2.10 2000/11/24 17:05:38 kai Exp $ * * ix1_micro.c low level stuff for ITK ix1-micro Rev.2 isdn cards * derived from the original file teles3.c from Karsten Keil @@ -43,13 +43,14 @@ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -const char *ix1_revision = "$Revision: 2.9 $"; +const char *ix1_revision = "$Revision: 2.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -243,8 +244,8 @@ } -__initfunc(int -setup_ix1micro(struct IsdnCard *card)) +int __init +setup_ix1micro(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/jade.c linux/drivers/isdn/hisax/jade.c --- v2.4.0-test11/linux/drivers/isdn/hisax/jade.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/jade.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: jade.c,v 1.4 2000/06/26 08:59:14 keil Exp $ +/* $Id: jade.c,v 1.6 2000/11/24 17:05:38 kai Exp $ * * jade.c JADE stuff (derived from original hscx.c) * @@ -10,6 +10,7 @@ #define __NO_VERSION__ +#include #include "hisax.h" #include "hscx.h" #include "jade.h" @@ -17,8 +18,8 @@ #include -HISAX_INITFUNC(int -JadeVersion(struct IsdnCardState *cs, char *s)) +int __init +JadeVersion(struct IsdnCardState *cs, char *s) { int ver,i; int to = 50; @@ -262,8 +263,8 @@ return (0); } -HISAX_INITFUNC(void -clear_pending_jade_ints(struct IsdnCardState *cs)) +void __init +clear_pending_jade_ints(struct IsdnCardState *cs) { int val; char tmp[64]; @@ -288,8 +289,8 @@ cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8); } -HISAX_INITFUNC(void -initjade(struct IsdnCardState *cs)) +void __init +initjade(struct IsdnCardState *cs) { cs->bcs[0].BC_SetStack = setstack_jade; cs->bcs[1].BC_SetStack = setstack_jade; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/jade_irq.c linux/drivers/isdn/hisax/jade_irq.c --- v2.4.0-test11/linux/drivers/isdn/hisax/jade_irq.c Sun Aug 6 12:43:41 2000 +++ linux/drivers/isdn/hisax/jade_irq.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: jade_irq.c,v 1.4 2000/06/26 08:59:14 keil Exp $ +/* $Id: jade_irq.c,v 1.5 2000/11/19 17:02:48 kai Exp $ * * jade_irq.c Low level JADE IRQ stuff (derived from original hscx_irq.c) * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/l3_1tr6.c linux/drivers/isdn/hisax/l3_1tr6.c --- v2.4.0-test11/linux/drivers/isdn/hisax/l3_1tr6.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/l3_1tr6.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: l3_1tr6.c,v 2.12 2000/08/20 07:31:30 keil Exp $ +/* $Id: l3_1tr6.c,v 2.13 2000/11/19 17:02:48 kai Exp $ * * German 1TR6 D-channel protocol * @@ -17,7 +17,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *l3_1tr6_revision = "$Revision: 2.12 $"; +const char *l3_1tr6_revision = "$Revision: 2.13 $"; #define MsgHead(ptr, cref, mty, dis) \ *ptr++ = dis; \ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/l3dss1.c linux/drivers/isdn/hisax/l3dss1.c --- v2.4.0-test11/linux/drivers/isdn/hisax/l3dss1.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/l3dss1.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: l3dss1.c,v 2.29 2000/06/26 08:59:14 keil Exp $ +/* $Id: l3dss1.c,v 2.30 2000/11/19 17:02:48 kai Exp $ * * EURO/DSS1 D-channel protocol * @@ -22,7 +22,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.29 $"; +const char *dss1_revision = "$Revision: 2.30 $"; #define EXT_BEARER_CAPS 1 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/l3ni1.c linux/drivers/isdn/hisax/l3ni1.c --- v2.4.0-test11/linux/drivers/isdn/hisax/l3ni1.c Tue Aug 22 09:06:31 2000 +++ linux/drivers/isdn/hisax/l3ni1.c Tue Dec 5 12:43:47 2000 @@ -1,20 +1,24 @@ -// $Id: l3ni1.c,v 2.3 2000/06/26 08:59:14 keil Exp $ +// $Id: l3ni1.c,v 2.5 2000/11/19 17:02:48 kai Exp $ +// //----------------------------------------------------------------------------- // // NI1 D-channel protocol // -// Author Matt Henderson & Guy Ellis - Traverse Tecnologies Pty Ltd -// www.traverse.com.au +// Authors: +// Matt Henderson & Guy Ellis - Traverse Tecnologies Pty Ltd +// www.traverse.com.au // // 2000.6.6 Initial implementation of routines for US NI1 // Layer 3 protocol based on the EURO/DSS1 D-channel protocol -// driver written by Karsten Keil et al. Thanks also for the -// code provided by Ragnar Paulson and Will Scales. +// driver written by Karsten Keil et al. +// NI-1 Hall of Fame - Thanks to.... +// Ragnar Paulson - for some handy code fragments +// Will Scales - beta tester extraordinaire +// Brett Whittacre - beta tester and remote devel system in Vegas // // This file is (c) under GNU PUBLIC LICENSE // //----------------------------------------------------------------------------- - #define __NO_VERSION__ #include "hisax.h" #include "isdnl3.h" @@ -22,7 +26,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *ni1_revision = "$Revision: 2.3 $"; +const char *ni1_revision = "$Revision: 2.5 $"; #define EXT_BEARER_CAPS 1 @@ -443,6 +447,27 @@ } static void +l3ni1_message_plus_chid(struct l3_process *pc, u_char mt) +/* sends an l3 messages plus channel id - added GE 05/09/00 */ +{ + struct sk_buff *skb; + u_char tmp[16]; + u_char *p = tmp; + u_char chid; + + chid = (u_char)(pc->para.bchannel & 0x03) | 0x88; + MsgHead(p, pc->callref, mt); + *p++ = IE_CHANNEL_ID; + *p++ = 0x01; + *p++ = chid; + + if (!(skb = l3_alloc_skb(7))) + return; + memcpy(skb_put(skb, 7), tmp, 7); + l3_msg(pc->st, DL_DATA | REQUEST, skb); +} + +static void l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause) { struct sk_buff *skb; @@ -1175,9 +1200,9 @@ case 1: /* Telephony */ *p++ = IE_BEARER; *p++ = 0x3; /* Length */ - *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ + *p++ = 0x90; /* 3.1khz Audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ - *p++ = 0xa3; /* A-Law Audio */ + *p++ = 0xa2; /* u-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ @@ -1240,7 +1265,7 @@ *p++ = 0x3; /* Length */ *p++ = 0x90; /* Coding Std. CCITT, 3.1 kHz audio */ *p++ = 0x90; /* Circuit-Mode 64kbps */ - *p++ = 0xa3; /* A-Law Audio */ + *p++ = 0xa2; /* u-Law Audio */ break; case 5: /* Datatransmission 64k, BTX */ case 7: /* Datatransmission 64k */ @@ -1641,7 +1666,9 @@ return; } newl3state(pc, 8); - l3ni1_message(pc, MT_CONNECT); + if (pc->debug & L3_DEB_WARN) + l3_debug(pc->st, "D-chan connect for waiting call"); + l3ni1_message_plus_chid(pc, MT_CONNECT); /* GE 05/09/00 */ L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T313, CC_T313); } @@ -2544,6 +2571,7 @@ up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); + up = up->next; } p = tmp; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/l3ni1.h linux/drivers/isdn/hisax/l3ni1.h --- v2.4.0-test11/linux/drivers/isdn/hisax/l3ni1.h Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/l3ni1.h Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -// $Id: l3ni1.h,v 2.2 2000/06/26 08:59:14 keil Exp $ +// $Id: l3ni1.h,v 2.3 2000/11/16 13:50:43 keil Exp $ //----------------------------------------------------------------------------- // // NI1 D-channel protocol @@ -11,6 +11,7 @@ // driver written by Karsten Keil et al. Thanks also for the // code provided by Ragnar Paulson. // +// // This file is (c) under GNU PUBLIC LICENSE // //----------------------------------------------------------------------------- @@ -29,7 +30,7 @@ #define T313 4000 #define T318 4000 #define T319 4000 -#define TSPID 2000 +#define TSPID 5000 /* was 2000 - Guy Ellis */ /* * Message-Types diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/mic.c linux/drivers/isdn/hisax/mic.c --- v2.4.0-test11/linux/drivers/isdn/hisax/mic.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/mic.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: mic.c,v 1.9 2000/06/26 08:59:14 keil Exp $ +/* $Id: mic.c,v 1.10 2000/11/24 17:05:38 kai Exp $ * * mic.c low level stuff for mic cards * @@ -11,6 +11,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" @@ -18,7 +19,7 @@ extern const char *CardType[]; -const char *mic_revision = "$Revision: 1.9 $"; +const char *mic_revision = "$Revision: 1.10 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -198,8 +199,8 @@ return(0); } -__initfunc(int -setup_mic(struct IsdnCard *card)) +int __init +setup_mic(struct IsdnCard *card) { int bytecnt; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c --- v2.4.0-test11/linux/drivers/isdn/hisax/netjet.c Tue Aug 22 09:06:31 2000 +++ linux/drivers/isdn/hisax/netjet.c Tue Dec 5 12:43:47 2000 @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.20 2000/06/26 08:59:14 keil Exp $ +/* $Id: netjet.c,v 1.24 2000/11/24 17:05:38 kai Exp $ * * netjet.c low level stuff for Traverse Technologie NETJet ISDN cards * @@ -11,6 +11,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" @@ -28,7 +29,7 @@ #define virt_to_bus (u_int) #endif -const char *NETjet_revision = "$Revision: 1.20 $"; +const char *NETjet_revision = "$Revision: 1.24 $"; /* Interface functions */ @@ -161,7 +162,8 @@ break; case (L1_MODE_TRANS): break; - case (L1_MODE_HDLC): + case (L1_MODE_HDLC_56K): + case (L1_MODE_HDLC): fill_mem(bcs, bcs->hw.tiger.send, NETJET_DMA_TXSIZE, bc, 0xff); bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH; @@ -176,7 +178,8 @@ cs->hw.njet.dmactrl = 1; byteout(cs->hw.njet.base + NETJET_DMACTRL, cs->hw.njet.dmactrl); - byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x3f); + byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x0f); + /* was 0x3f now 0x0f for TJ300 and TJ320 GE 13/07/00 */ } bcs->hw.tiger.sendp = bcs->hw.tiger.send; bcs->hw.tiger.free = NETJET_DMA_TXSIZE; @@ -214,6 +217,8 @@ } } +// macro for 64k + #define MAKE_RAW_BYTE for (j=0; j<8; j++) { \ bitcnt++;\ s_val >>= 1;\ @@ -242,6 +247,7 @@ } static int make_raw_data(struct BCState *bcs) { +// this make_raw is for 64k register u_int i,s_cnt=0; register u_char j; register u_char val; @@ -297,6 +303,113 @@ return(0); } +// macro for 56k + +#define MAKE_RAW_BYTE_56K for (j=0; j<8; j++) { \ + bitcnt++;\ + s_val >>= 1;\ + if (val & 1) {\ + s_one++;\ + s_val |= 0x80;\ + } else {\ + s_one = 0;\ + s_val &= 0x7f;\ + }\ + if (bitcnt==7) {\ + s_val >>= 1;\ + s_val |= 0x80;\ + bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ + bitcnt = 0;\ + }\ + if (s_one == 5) {\ + s_val >>= 1;\ + s_val &= 0x7f;\ + bitcnt++;\ + s_one = 0;\ + }\ + if (bitcnt==7) {\ + s_val >>= 1;\ + s_val |= 0x80;\ + bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ + bitcnt = 0;\ + }\ + val >>= 1;\ + } + +static int make_raw_data_56k(struct BCState *bcs) { +// this make_raw is for 56k + register u_int i,s_cnt=0; + register u_char j; + register u_char val; + register u_char s_one = 0; + register u_char s_val = 0; + register u_char bitcnt = 0; + u_int fcs; + + if (!bcs->tx_skb) { + debugl1(bcs->cs, "tiger make_raw_56k: NULL skb"); + return(1); + } + val = HDLC_FLAG_VALUE; + for (j=0; j<8; j++) { + bitcnt++; + s_val >>= 1; + if (val & 1) + s_val |= 0x80; + else + s_val &= 0x7f; + if (bitcnt==7) { + s_val >>= 1; + s_val |= 0x80; + bcs->hw.tiger.sendbuf[s_cnt++] = s_val; + bitcnt = 0; + } + val >>= 1; + }; + fcs = PPP_INITFCS; + for (i=0; itx_skb->len; i++) { + val = bcs->tx_skb->data[i]; + fcs = PPP_FCS (fcs, val); + MAKE_RAW_BYTE_56K; + } + fcs ^= 0xffff; + val = fcs & 0xff; + MAKE_RAW_BYTE_56K; + val = (fcs>>8) & 0xff; + MAKE_RAW_BYTE_56K; + val = HDLC_FLAG_VALUE; + for (j=0; j<8; j++) { + bitcnt++; + s_val >>= 1; + if (val & 1) + s_val |= 0x80; + else + s_val &= 0x7f; + if (bitcnt==7) { + s_val >>= 1; + s_val |= 0x80; + bcs->hw.tiger.sendbuf[s_cnt++] = s_val; + bitcnt = 0; + } + val >>= 1; + } + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d", + bcs->tx_skb->len, s_cnt, bitcnt); + if (bitcnt) { + while (8>bitcnt++) { + s_val >>= 1; + s_val |= 0x80; + } + bcs->hw.tiger.sendbuf[s_cnt++] = s_val; + bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix + } + bcs->hw.tiger.sendcnt = s_cnt; + bcs->tx_cnt -= bcs->tx_skb->len; + bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf; + return(0); +} + static void got_frame(struct BCState *bcs, int count) { struct sk_buff *skb; @@ -326,20 +439,30 @@ register u_char r_val = bcs->hw.tiger.r_val; register u_int bitcnt = bcs->hw.tiger.r_bitcnt; u_int *p = buf; - + int bits; + u_char mask; + + if (bcs->mode == L1_MODE_HDLC) { // it's 64k + mask = 0xff; + bits = 8; + } + else { // it's 56K + mask = 0x7f; + bits = 7; + }; for (i=0;ichannel ? ((*p>>8) & 0xff) : (*p & 0xff); p++; if (p > pend) p = bcs->hw.tiger.rec; - if (val == 0xff) { + if ((val & mask) == mask) { state = HDLC_ZERO_SEARCH; bcs->hw.tiger.r_tot++; bitcnt = 0; r_one = 0; continue; } - for (j=0;j<8;j++) { + for (j=0;jbcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1; else p = cs->bcs[0].hw.tiger.rec + cnt - 1; - if (cs->bcs[0].mode == L1_MODE_HDLC) + if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K)) read_raw(cs->bcs, p, cnt); - if (cs->bcs[1].mode == L1_MODE_HDLC) + + if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K)) read_raw(cs->bcs + 1, p, cnt); cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_READ; } @@ -526,8 +650,14 @@ bcs->Flag); if (test_and_set_bit(BC_FLG_BUSY, &bcs->Flag)) return; - if (make_raw_data(bcs)) - return; + if (bcs->mode == L1_MODE_HDLC) { // it's 64k + if (make_raw_data(bcs)) + return; + } + else { // it's 56k + if (make_raw_data_56k(bcs)) + return; + }; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger fill_dma2: c%d %4x", bcs->channel, bcs->Flag); @@ -682,9 +812,9 @@ p = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1; else p = cs->bcs[0].hw.tiger.send + cnt - 1; - if (cs->bcs[0].mode == L1_MODE_HDLC) + if ((cs->bcs[0].mode == L1_MODE_HDLC) || (cs->bcs[0].mode == L1_MODE_HDLC_56K)) write_raw(cs->bcs, p, cnt); - if (cs->bcs[1].mode == L1_MODE_HDLC) + if ((cs->bcs[1].mode == L1_MODE_HDLC) || (cs->bcs[1].mode == L1_MODE_HDLC_56K)) write_raw(cs->bcs + 1, p, cnt); cs->hw.njet.irqstat0 &= ~NETJET_IRQM0_WRITE; } @@ -807,8 +937,8 @@ } -__initfunc(void -inittiger(struct IsdnCardState *cs)) +void __init +inittiger(struct IsdnCardState *cs) { if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int), GFP_KERNEL | GFP_DMA))) { diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/netjet.h linux/drivers/isdn/hisax/netjet.h --- v2.4.0-test11/linux/drivers/isdn/hisax/netjet.h Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/netjet.h Tue Nov 28 21:44:41 2000 @@ -1,4 +1,4 @@ -// $Id: netjet.h,v 2.3 2000/06/26 08:59:14 keil Exp $ +// $Id: netjet.h,v 2.5.6.1 2000/11/28 12:02:46 kai Exp $ //----------------------------------------------------------------------------- // // NETjet common header file @@ -15,13 +15,6 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -/* PCI stuff */ -#ifndef PCI_VENDOR_ID_TIGERJET -#define PCI_VENDOR_ID_TIGERJET 0xe159 -#endif -#ifndef PCI_DEVICE_ID_TIGERJET_300 -#define PCI_DEVICE_ID_TIGERJET_300 0x0001 -#endif #define NETJET_CTRL 0x00 #define NETJET_DMACTRL 0x01 #define NETJET_AUXCTRL 0x02 @@ -72,6 +65,6 @@ void netjet_fill_dma(struct BCState *bcs); void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs); -__initfunc(void inittiger(struct IsdnCardState *cs)); +void inittiger(struct IsdnCardState *cs); void release_io_netjet(struct IsdnCardState *cs); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/niccy.c linux/drivers/isdn/hisax/niccy.c --- v2.4.0-test11/linux/drivers/isdn/hisax/niccy.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/niccy.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: niccy.c,v 1.12 2000/06/26 08:59:14 keil Exp $ +/* $Id: niccy.c,v 1.15.6.2 2000/11/29 16:00:14 kai Exp $ * * niccy.c low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and * compatible (SAGEM cybermodem) @@ -14,6 +14,7 @@ #define __NO_VERSION__ #include +#include #include "hisax.h" #include "isac.h" #include "hscx.h" @@ -21,7 +22,7 @@ #include extern const char *CardType[]; -const char *niccy_revision = "$Revision: 1.12 $"; +const char *niccy_revision = "$Revision: 1.15.6.2 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -38,12 +39,6 @@ #define NICCY_PCI 2 /* PCI stuff */ -#ifndef PCI_VENDOR_ID_SATSAGEM -#define PCI_VENDOR_ID_SATSAGEM 0x1267 -#endif -#ifndef PCI_DEVICE_ID_SATSAGEM_NICCY -#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016 -#endif #define PCI_IRQ_CTRL_REG 0x38 #define PCI_IRQ_ENABLE 0x1f00 #define PCI_IRQ_DISABLE 0xff0000 @@ -240,10 +235,10 @@ return(0); } -static struct pci_dev *niccy_dev __initdata = NULL; +static struct pci_dev *niccy_dev __initdata = NULL; -__initfunc(int -setup_niccy(struct IsdnCard *card)) +int __init +setup_niccy(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/nj_s.c linux/drivers/isdn/hisax/nj_s.c --- v2.4.0-test11/linux/drivers/isdn/hisax/nj_s.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hisax/nj_s.c Wed Nov 29 10:12:29 2000 @@ -1,9 +1,11 @@ -// $Id: nj_s.c,v 2.3 2000/06/26 08:59:14 keil Exp $ +// $Id: nj_s.c,v 2.7.6.1 2000/11/29 16:00:14 kai Exp $ // // This file is (c) under GNU PUBLIC LICENSE // + #define __NO_VERSION__ #include +#include #include "hisax.h" #include "isac.h" #include "isdnl1.h" @@ -12,7 +14,7 @@ #include #include "netjet.h" -const char *NETjet_S_revision = "$Revision: 2.3 $"; +const char *NETjet_S_revision = "$Revision: 2.7.6.1 $"; static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) { @@ -47,28 +49,37 @@ } save_flags(flags); cli(); - if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) { + /* start new code 13/07/00 GE */ + /* set bits in sval to indicate which page is free */ + if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) + /* the 2nd write page is free */ + sval = 0x08; + else /* the 1st write page is free */ + sval = 0x04; + if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) + /* the 2nd read page is free */ + sval = sval | 0x02; + else /* the 1st read page is free */ + sval = sval | 0x01; + if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { restore_flags(flags); return; } cs->hw.njet.irqstat0 = sval; restore_flags(flags); -/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d", - sval, - bytein(cs->hw.njet.base + NETJET_DMACTRL), - bytein(cs->hw.njet.base + NETJET_IRQMASK0), - inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), - inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), - bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); -*/ -/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30; -*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0); -/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0); -*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) + /* we have a read dma int */ read_tiger(cs); - if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) + /* we have a write dma int */ write_tiger(cs); + /* end new code 13/07/00 GE */ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else restore_flags(flags); @@ -93,7 +104,8 @@ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ + /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ @@ -128,17 +140,16 @@ return(0); } -static struct pci_dev *dev_netjet __initdata = NULL; +static struct pci_dev *dev_netjet __initdata = NULL; -__initfunc(int -setup_netjet_s(struct IsdnCard *card)) +int __init +setup_netjet_s(struct IsdnCard *card) { int bytecnt; struct IsdnCardState *cs = card->cs; char tmp[64]; long flags; -#if CONFIG_PCI -#endif + #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/nj_u.c linux/drivers/isdn/hisax/nj_u.c --- v2.4.0-test11/linux/drivers/isdn/hisax/nj_u.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hisax/nj_u.c Wed Nov 29 10:12:29 2000 @@ -1,10 +1,12 @@ -/* $Id: nj_u.c,v 2.4 2000/06/26 11:42:16 keil Exp $ +/* $Id: nj_u.c,v 2.8.6.1 2000/11/29 16:00:14 kai Exp $ * * This file is (c) under GNU PUBLIC LICENSE * */ + #define __NO_VERSION__ #include +#include #include "hisax.h" #include "icc.h" #include "isdnl1.h" @@ -13,7 +15,7 @@ #include #include "netjet.h" -const char *NETjet_U_revision = "$Revision: 2.4 $"; +const char *NETjet_U_revision = "$Revision: 2.8.6.1 $"; static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) { @@ -48,28 +50,37 @@ } save_flags(flags); cli(); - if ((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT0))) { + /* start new code 13/07/00 GE */ + /* set bits in sval to indicate which page is free */ + if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) + /* the 2nd write page is free */ + sval = 0x08; + else /* the 1st write page is free */ + sval = 0x04; + if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < + inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) + /* the 2nd read page is free */ + sval = sval | 0x02; + else /* the 1st read page is free */ + sval = sval | 0x01; + if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + { if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { restore_flags(flags); return; } cs->hw.njet.irqstat0 = sval; restore_flags(flags); -/* debugl1(cs, "tiger: ist0 %x %x %x %x/%x pulse=%d", - sval, - bytein(cs->hw.njet.base + NETJET_DMACTRL), - bytein(cs->hw.njet.base + NETJET_IRQMASK0), - inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), - inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), - bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); -*/ -/* cs->hw.njet.irqmask0 = ((0x0f & cs->hw.njet.irqstat0) ^ 0x0f) | 0x30; -*/ byteout(cs->hw.njet.base + NETJET_IRQSTAT0, cs->hw.njet.irqstat0); -/* byteout(cs->hw.njet.base + NETJET_IRQMASK0, cs->hw.njet.irqmask0); -*/ if (cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) + /* we have a read dma int */ read_tiger(cs); - if (cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) + if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_WRITE) != + (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) + /* we have a write dma int */ write_tiger(cs); + /* end new code 13/07/00 GE */ test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } else restore_flags(flags); @@ -94,7 +105,8 @@ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ + /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); set_current_state(TASK_UNINTERRUPTIBLE); schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ @@ -130,10 +142,10 @@ return(0); } -static struct pci_dev *dev_netjet __initdata = NULL; +static struct pci_dev *dev_netjet __initdata = NULL; -__initfunc(int -setup_netjet_u(struct IsdnCard *card)) +int __init +setup_netjet_u(struct IsdnCard *card) { int bytecnt; struct IsdnCardState *cs = card->cs; @@ -155,7 +167,7 @@ for ( ;; ) { if (!pci_present()) { - printk(KERN_ERR "NETspider-U: no PCI bus present\n"); + printk(KERN_ERR "Netjet: no PCI bus present\n"); return(0); } if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, @@ -241,7 +253,7 @@ cs->hw.njet.base + bytecnt); return (0); } else { - request_region(cs->hw.njet.base, bytecnt, "netjet-u isdn"); + request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn"); } reset_netjet_u(cs); cs->readisac = &NETjet_ReadIC; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/s0box.c linux/drivers/isdn/hisax/s0box.c --- v2.4.0-test11/linux/drivers/isdn/hisax/s0box.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/s0box.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: s0box.c,v 2.3 2000/06/26 08:59:14 keil Exp $ +/* $Id: s0box.c,v 2.4 2000/11/24 17:05:38 kai Exp $ * * s0box.c low level stuff for Creatix S0BOX * @@ -8,13 +8,14 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -const char *s0box_revision = "$Revision: 2.3 $"; +const char *s0box_revision = "$Revision: 2.4 $"; static inline void writereg(unsigned int padr, signed int addr, u_char off, u_char val) { @@ -213,8 +214,8 @@ return(0); } -__initfunc(int -setup_s0box(struct IsdnCard *card)) +int __init +setup_s0box(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/saphir.c linux/drivers/isdn/hisax/saphir.c --- v2.4.0-test11/linux/drivers/isdn/hisax/saphir.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/saphir.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: saphir.c,v 1.7 2000/06/26 08:59:14 keil Exp $ +/* $Id: saphir.c,v 1.8 2000/11/24 17:05:38 kai Exp $ * * saphir.c low level stuff for HST Saphir 1 * @@ -12,13 +12,14 @@ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -static char *saphir_rev = "$Revision: 1.7 $"; +static char *saphir_rev = "$Revision: 1.8 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -253,8 +254,8 @@ } -__initfunc(int -setup_saphir(struct IsdnCard *card)) +int __init +setup_saphir(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/sedlbauer.c linux/drivers/isdn/hisax/sedlbauer.c --- v2.4.0-test11/linux/drivers/isdn/hisax/sedlbauer.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/sedlbauer.c Wed Nov 29 10:35:15 2000 @@ -1,4 +1,4 @@ -/* $Id: sedlbauer.c,v 1.23 2000/06/26 08:59:14 keil Exp $ +/* $Id: sedlbauer.c,v 1.25.6.2 2000/11/29 17:48:59 kai Exp $ * * sedlbauer.c low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), @@ -40,6 +40,7 @@ */ #define __NO_VERSION__ +#include #include #include "hisax.h" #include "isac.h" @@ -51,19 +52,13 @@ extern const char *CardType[]; -const char *Sedlbauer_revision = "$Revision: 1.23 $"; +const char *Sedlbauer_revision = "$Revision: 1.25.6.2 $"; const char *Sedlbauer_Types[] = {"None", "speed card/win", "speed star", "speed fax+", "speed win II / ISDN PC/104", "speed star II", "speed pci", "speed fax+ pyramid", "speed fax+ pci"}; -#ifndef PCI_VENDOR_ID_TIGERJET -#define PCI_VENDOR_ID_TIGERJET 0xe159 -#endif -#ifndef PCI_DEVICE_ID_TIGERJET_100 -#define PCI_DEVICE_ID_TIGERJET_100 0x0002 -#endif #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51 #define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53 #define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54 @@ -534,10 +529,10 @@ return(0); } -static struct pci_dev *dev_sedl __initdata = NULL; +static struct pci_dev *dev_sedl __devinitdata = NULL; -__initfunc(int -setup_sedlbauer(struct IsdnCard *card)) +int __devinit +setup_sedlbauer(struct IsdnCard *card) { int bytecnt, ver, val; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/sportster.c linux/drivers/isdn/hisax/sportster.c --- v2.4.0-test11/linux/drivers/isdn/hisax/sportster.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/sportster.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: sportster.c,v 1.13 2000/06/26 08:59:14 keil Exp $ +/* $Id: sportster.c,v 1.14 2000/11/24 17:05:38 kai Exp $ * * sportster.c low level stuff for USR Sportster internal TA * @@ -10,13 +10,14 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.13 $"; +const char *sportster_revision = "$Revision: 1.14 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -181,8 +182,8 @@ return(0); } -__initfunc(int -get_io_range(struct IsdnCardState *cs)) +static int __init +get_io_range(struct IsdnCardState *cs) { int i, j, adr; @@ -207,8 +208,8 @@ } } -__initfunc(int -setup_sportster(struct IsdnCard *card)) +int __init +setup_sportster(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/tei.c linux/drivers/isdn/hisax/tei.c --- v2.4.0-test11/linux/drivers/isdn/hisax/tei.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/tei.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: tei.c,v 2.15 2000/06/26 08:59:14 keil Exp $ +/* $Id: tei.c,v 2.17 2000/11/24 17:05:38 kai Exp $ * * Author Karsten Keil (keil@isdn4linux.de) * based on the teles driver from Jan den Ouden @@ -14,9 +14,10 @@ #define __NO_VERSION__ #include "hisax.h" #include "isdnl2.h" +#include #include -const char *tei_revision = "$Revision: 2.15 $"; +const char *tei_revision = "$Revision: 2.17 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 @@ -28,9 +29,7 @@ #define TEI_ENTITY_ID 0xf -static -struct Fsm teifsm = -{NULL, 0, 0, NULL, NULL}; +static struct Fsm teifsm; void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb); @@ -430,7 +429,7 @@ } } -static struct FsmNode TeiFnList[] HISAX_INITDATA = +static struct FsmNode TeiFnList[] __initdata = { {ST_TEI_NOP, EV_IDREQ, tei_id_request}, {ST_TEI_NOP, EV_ASSIGN, tei_id_test_dup}, @@ -447,8 +446,8 @@ #define TEI_FN_COUNT (sizeof(TeiFnList)/sizeof(struct FsmNode)) -HISAX_INITFUNC(void -TeiNew(void)) +void __init +TeiNew(void) { teifsm.state_count = TEI_STATE_COUNT; teifsm.event_count = TEI_EVENT_COUNT; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/teleint.c linux/drivers/isdn/hisax/teleint.c --- v2.4.0-test11/linux/drivers/isdn/hisax/teleint.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/teleint.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: teleint.c,v 1.13 2000/06/26 08:59:14 keil Exp $ +/* $Id: teleint.c,v 1.14 2000/11/24 17:05:38 kai Exp $ * * teleint.c low level stuff for TeleInt isdn cards * @@ -9,6 +9,7 @@ */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hfc_2bs0.h" @@ -16,7 +17,7 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.13 $"; +const char *TeleInt_revision = "$Revision: 1.14 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -260,8 +261,8 @@ return(0); } -__initfunc(int -setup_TeleInt(struct IsdnCard *card)) +int __init +setup_TeleInt(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/teles0.c linux/drivers/isdn/hisax/teles0.c --- v2.4.0-test11/linux/drivers/isdn/hisax/teles0.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/teles0.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: teles0.c,v 2.12 2000/06/26 08:59:14 keil Exp $ +/* $Id: teles0.c,v 2.13 2000/11/24 17:05:38 kai Exp $ * * teles0.c low level stuff for Teles Memory IO isdn cards * based on the teles driver from Jan den Ouden @@ -13,6 +13,7 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isdnl1.h" #include "isac.h" @@ -20,7 +21,7 @@ extern const char *CardType[]; -const char *teles0_revision = "$Revision: 2.12 $"; +const char *teles0_revision = "$Revision: 2.13 $"; #define TELES_IOMEM_SIZE 0x400 #define byteout(addr,val) outb(val,addr) @@ -260,8 +261,8 @@ return(0); } -__initfunc(int -setup_teles0(struct IsdnCard *card)) +int __init +setup_teles0(struct IsdnCard *card) { u_char val; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c --- v2.4.0-test11/linux/drivers/isdn/hisax/teles3.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/hisax/teles3.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: teles3.c,v 2.16 2000/06/26 08:59:15 keil Exp $ +/* $Id: teles3.c,v 2.17 2000/11/24 17:05:38 kai Exp $ * * teles3.c low level stuff for Teles 16.3 & PNP isdn cards * @@ -14,13 +14,14 @@ * */ #define __NO_VERSION__ +#include #include "hisax.h" #include "isac.h" #include "hscx.h" #include "isdnl1.h" extern const char *CardType[]; -const char *teles3_revision = "$Revision: 2.16 $"; +const char *teles3_revision = "$Revision: 2.17 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -253,8 +254,8 @@ return(0); } -__initfunc(int -setup_teles3(struct IsdnCard *card)) +int __devinit +setup_teles3(struct IsdnCard *card) { u_char val; struct IsdnCardState *cs = card->cs; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/telespci.c linux/drivers/isdn/hisax/telespci.c --- v2.4.0-test11/linux/drivers/isdn/hisax/telespci.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/telespci.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: telespci.c,v 2.13 2000/06/26 08:59:15 keil Exp $ +/* $Id: telespci.c,v 2.16.6.2 2000/11/29 16:00:14 kai Exp $ * * telespci.c low level stuff for Teles PCI isdn cards * @@ -9,6 +9,7 @@ * */ #define __NO_VERSION__ +#include #include #include "hisax.h" #include "isac.h" @@ -17,7 +18,7 @@ #include extern const char *CardType[]; -const char *telespci_revision = "$Revision: 2.13 $"; +const char *telespci_revision = "$Revision: 2.16.6.2 $"; #define ZORAN_PO_RQ_PEN 0x02000000 #define ZORAN_PO_WR 0x00800000 @@ -27,12 +28,6 @@ #define ZORAN_PO_GREG1 0x00010000 #define ZORAN_PO_DMASK 0xFF -#ifndef PCI_VENDOR_ID_ZORAN -#define PCI_VENDOR_ID_ZORAN 0x11DE -#endif -#ifndef PCI_DEVICE_ID_ZORAN_36120 -#define PCI_DEVICE_ID_ZORAN_36120 0x6120 -#endif #define WRITE_ADDR_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG0) #define READ_DATA_ISAC (ZORAN_PO_GID0 | ZORAN_PO_GREG1) #define WRITE_DATA_ISAC (ZORAN_PO_WR | ZORAN_PO_GID0 | ZORAN_PO_GREG1) @@ -280,10 +275,10 @@ return(0); } -static struct pci_dev *dev_tel __initdata = NULL; +static struct pci_dev *dev_tel __initdata = NULL; -__initfunc(int -setup_telespci(struct IsdnCard *card)) +int __init +setup_telespci(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hisax/w6692.c linux/drivers/isdn/hisax/w6692.c --- v2.4.0-test11/linux/drivers/isdn/hisax/w6692.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hisax/w6692.c Wed Nov 29 10:12:29 2000 @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.8 2000/09/07 20:33:30 werner Exp $ +/* $Id: w6692.c,v 1.12.6.2 2000/11/29 16:00:14 kai Exp $ * * w6692.c Winbond W6692 specific routines * @@ -10,6 +10,7 @@ */ #include +#include #define __NO_VERSION__ #include "hisax.h" #include "w6692.h" @@ -17,18 +18,6 @@ #include #include -#ifndef PCI_VENDOR_ID_ASUSCOM -#define PCI_VENDOR_ID_ASUSCOM 0x675 -#endif -#ifndef PCI_DEVICE_ID_ASUSCOM_TA1 -#define PCI_DEVICE_ID_ASUSCOM_TA1 0x1702 -#endif -#ifndef PCI_VENDOR_ID_WINBOND2 -#define PCI_VENDOR_ID_WINBOND2 0x1050 -#endif -#ifndef PCI_DEVICE_ID_WINBOND_6692 -#define PCI_DEVICE_ID_WINBOND_6692 0x6692 -#endif /* table entry in the PCI devices list */ typedef struct { int vendor_id; @@ -39,18 +28,18 @@ static const PCI_ENTRY id_list[] = { - {PCI_VENDOR_ID_ASUSCOM, PCI_DEVICE_ID_ASUSCOM_TA1, "AsusCom", "TA XXX"}, - {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND_6692, "Winbond", "W6692"}, + {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"}, + {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"}, {0, 0, NULL, NULL} }; extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.8 $"; +const char *w6692_revision = "$Revision: 1.12.6.2 $"; #define DBUSY_TIMER_VALUE 80 -static char *W6692Ver[] HISAX_INITDATA = +static char *W6692Ver[] __initdata = {"W6692 V00", "W6692 V01", "W6692 V10", "W6692 V11"}; @@ -869,7 +858,7 @@ return (0); } -HISAX_INITFUNC(void initW6692(struct IsdnCardState *cs, int part)) +void __init initW6692(struct IsdnCardState *cs, int part) { if (part & 1) { cs->tqueue.routine = (void *) (void *) W6692_bh; @@ -966,11 +955,12 @@ return (0); } -static int id_idx = 0; +static int id_idx ; static struct pci_dev *dev_w6692 __initdata = NULL; -__initfunc(int setup_w6692(struct IsdnCard *card)) +int __init +setup_w6692(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; char tmp[64]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hysdn/boardergo.c linux/drivers/isdn/hysdn/boardergo.c --- v2.4.0-test11/linux/drivers/isdn/hysdn/boardergo.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hysdn/boardergo.c Mon Dec 11 12:39:45 2000 @@ -1,4 +1,4 @@ -/* $Id: boardergo.c,v 1.4 2000/11/13 22:51:47 kai Exp $ +/* $Id: boardergo.c,v 1.5 2000/11/22 17:13:13 kai Exp $ * Linux driver for HYSDN cards, specific routines for ergo type boards. * @@ -458,7 +458,7 @@ card->writebootseq = ergo_writebootseq; card->waitpofready = ergo_waitpofready; card->set_errlog_state = ergo_set_errlog_state; - card->irq_queue.next = 0; + INIT_LIST_HEAD(&card->irq_queue.list); card->irq_queue.sync = 0; card->irq_queue.data = card; /* init task queue for interrupt */ card->irq_queue.routine = (void *) (void *) ergo_irq_bh; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hysdn/hycapi.c linux/drivers/isdn/hysdn/hycapi.c --- v2.4.0-test11/linux/drivers/isdn/hysdn/hycapi.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hysdn/hycapi.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hycapi.c,v 1.7 2000/11/13 22:51:47 kai Exp $ +/* $Id: hycapi.c,v 1.8 2000/11/22 17:13:13 kai Exp $ * * Linux driver for HYSDN cards, CAPI2.0-Interface. * written by Ulrich Albrecht (u.albrecht@hypercope.de) for Hypercope GmbH @@ -41,7 +41,7 @@ #include "hysdn_defs.h" #include -static char hycapi_revision[]="$Revision: 1.7 $"; +static char hycapi_revision[]="$Revision: 1.8 $"; typedef struct _hycapi_appl { unsigned int ctrl_mask; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_defs.h linux/drivers/isdn/hysdn/hysdn_defs.h --- v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_defs.h Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hysdn/hysdn_defs.h Tue Nov 28 21:44:41 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_defs.h,v 1.4 2000/11/13 22:51:47 kai Exp $ +/* $Id: hysdn_defs.h,v 1.5.6.1 2000/11/28 12:02:47 kai Exp $ * Linux driver for HYSDN cards, global definitions and exported vars and functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -114,21 +114,6 @@ #define PROC_SUBDIR_NAME "hysdn" #define PROC_CONF_BASENAME "cardconf" #define PROC_LOG_BASENAME "cardlog" - -/************************/ -/* PCI constant defines */ -/************************/ -#define PCI_VENDOR_ID_HYPERCOPE 0x1365 -#define PCI_DEVICE_ID_PLX 0x9050 /* all DPRAM cards use the same id */ - -/*****************************/ -/* sub ids determining cards */ -/*****************************/ -#define PCI_SUB_ID_OLD_ERGO 0x0104 -#define PCI_SUB_ID_ERGO 0x0106 -#define PCI_SUB_ID_METRO 0x0107 -#define PCI_SUB_ID_CHAMP2 0x0108 -#define PCI_SUB_ID_PLEXUS 0x0109 /***********************************/ /* PCI 32 bit parms for IO and MEM */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_init.c linux/drivers/isdn/hysdn/hysdn_init.c --- v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_init.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hysdn/hysdn_init.c Tue Nov 28 21:44:41 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_init.c,v 1.6 2000/11/13 22:51:47 kai Exp $ +/* $Id: hysdn_init.c,v 1.6.6.1 2000/11/28 12:02:47 kai Exp $ * Linux driver for HYSDN cards, init functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,7 @@ #include "hysdn_defs.h" -static char *hysdn_init_revision = "$Revision: 1.6 $"; +static char *hysdn_init_revision = "$Revision: 1.6.6.1 $"; int cardmax; /* number of found cards */ hysdn_card *card_root = NULL; /* pointer to first card */ @@ -45,22 +46,31 @@ } pci_subid_map[] = { { - PCI_SUB_ID_METRO, BD_METRO + PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO }, { - PCI_SUB_ID_CHAMP2, BD_CHAMP2 + PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2 }, { - PCI_SUB_ID_ERGO, BD_ERGO + PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO }, { - PCI_SUB_ID_OLD_ERGO, BD_ERGO + PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO }, { 0, 0 } /* terminating entry */ }; +static struct pci_device_id hysdn_pci_tbl[] __initdata = { + {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO}, + {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2}, + {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO}, + {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO}, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl); + /*********************************************************************/ /* search_cards searches for available cards in the pci config data. */ /* If a card is found, the card structure is allocated and the cards */ @@ -75,7 +85,7 @@ card_root = NULL; card_last = NULL; - while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_PLX, + while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, akt_pcidev)) != NULL) { if (pci_enable_device(akt_pcidev)) continue; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_proclog.c linux/drivers/isdn/hysdn/hysdn_proclog.c --- v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_proclog.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hysdn/hysdn_proclog.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_proclog.c,v 1.8 2000/11/13 22:51:47 kai Exp $ +/* $Id: hysdn_proclog.c,v 1.9 2000/11/25 17:01:01 kai Exp $ * Linux driver for HYSDN cards, /proc/net filesystem log functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_sched.c linux/drivers/isdn/hysdn/hysdn_sched.c --- v2.4.0-test11/linux/drivers/isdn/hysdn/hysdn_sched.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/hysdn/hysdn_sched.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_sched.c,v 1.4 2000/11/13 22:51:47 kai Exp $ +/* $Id: hysdn_sched.c,v 1.5 2000/11/22 17:13:13 kai Exp $ * Linux driver for HYSDN cards, scheduler routines for handling exchange card <-> pc. * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c --- v2.4.0-test11/linux/drivers/isdn/isdn_cards.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/isdn_cards.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_cards.c,v 1.13 2000/10/28 23:03:38 kai Exp $ +/* $Id: isdn_cards.c,v 1.14 2000/11/23 20:45:14 kai Exp $ * Linux ISDN subsystem, initialization for non-modularized drivers. * @@ -38,11 +38,6 @@ extern void eicon_init(void); #endif -#ifdef CONFIG_ISDN_DRV_AVMB1 -extern void kcapi_init(void); -extern void capi_init(void); -extern void capidrv_init(void); -#endif #if CONFIG_ISDN_DRV_ACT2000 extern void act2000_init(void); #endif @@ -58,11 +53,6 @@ #endif #if CONFIG_ISDN_DRV_PCBIT pcbit_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1 - kcapi_init(); - capi_init(); - capidrv_init(); #endif #if CONFIG_ISDN_DRV_ACT2000 act2000_init(); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.4.0-test11/linux/drivers/isdn/isdn_common.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/isdn_common.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.113 2000/11/01 17:54:00 detabc Exp $ +/* $Id: isdn_common.c,v 1.114 2000/11/25 17:00:59 kai Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -48,7 +48,7 @@ isdn_dev *dev; -static char *isdn_revision = "$Revision: 1.113 $"; +static char *isdn_revision = "$Revision: 1.114 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h --- v2.4.0-test11/linux/drivers/isdn/isdn_common.h Tue Aug 8 15:03:57 2000 +++ linux/drivers/isdn/isdn_common.h Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.h,v 1.20 2000/06/16 13:00:27 keil Exp $ +/* $Id: isdn_common.h,v 1.21 2000/11/25 17:00:59 kai Exp $ * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel). * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- v2.4.0-test11/linux/drivers/isdn/isdn_ppp.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/isdn_ppp.c Tue Nov 28 21:43:13 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.84 2000/11/13 22:51:46 kai Exp $ +/* $Id: isdn_ppp.c,v 1.85 2000/11/25 17:00:59 kai Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -83,7 +83,7 @@ static int isdn_ppp_bundle(struct ippp_struct *, int unit); #endif /* CONFIG_ISDN_MPP */ -char *isdn_ppp_revision = "$Revision: 1.84 $"; +char *isdn_ppp_revision = "$Revision: 1.85 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c --- v2.4.0-test11/linux/drivers/isdn/isdn_tty.c Tue Aug 8 15:03:57 2000 +++ linux/drivers/isdn/isdn_tty.c Mon Nov 27 16:53:43 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_tty.c,v 1.93 2000/08/05 09:58:26 armin Exp $ +/* $Id: isdn_tty.c,v 1.94 2000/11/25 17:00:59 kai Exp $ * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). * @@ -66,7 +66,7 @@ static int si2bit[8] = {4, 1, 4, 4, 4, 4, 4, 4}; -char *isdn_tty_revision = "$Revision: 1.93 $"; +char *isdn_tty_revision = "$Revision: 1.94 $"; /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() diff -u --recursive --new-file v2.4.0-test11/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c --- v2.4.0-test11/linux/drivers/isdn/pcbit/drv.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/isdn/pcbit/drv.c Mon Dec 11 12:39:45 2000 @@ -135,7 +135,7 @@ dev->b2->id = 1; - dev->qdelivery.next = NULL; + INIT_LIST_HEAD(&dev->qdelivery.list); dev->qdelivery.sync = 0; dev->qdelivery.routine = pcbit_deliver; dev->qdelivery.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c --- v2.4.0-test11/linux/drivers/macintosh/mac_keyb.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/macintosh/mac_keyb.c Sun Dec 3 17:48:19 2000 @@ -255,8 +255,6 @@ int adb_button3_keycode = 0x7c; /* right option key */ #endif -extern int console_loglevel; - extern struct kbd_struct kbd_table[]; extern wait_queue_head_t keypress_wait; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/macintosh/via-macii.c linux/drivers/macintosh/via-macii.c --- v2.4.0-test11/linux/drivers/macintosh/via-macii.c Sun Feb 13 11:21:42 2000 +++ linux/drivers/macintosh/via-macii.c Sun Dec 3 17:48:19 2000 @@ -125,7 +125,6 @@ static int driver_running = 0; /* debug level 10 required for ADB logging (should be && debug_adb, ideally) */ -extern int console_loglevel; /* Check for MacII style ADB */ static int macii_probe(void) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/Makefile linux/drivers/md/Makefile --- v2.4.0-test11/linux/drivers/md/Makefile Sun Oct 8 10:50:18 2000 +++ linux/drivers/md/Makefile Mon Dec 11 13:19:34 2000 @@ -16,18 +16,26 @@ obj-n := obj- := -obj-$(CONFIG_BLK_DEV_MD) += md.o +# Note: link order is important. All raid personalities +# and xor.o must come before md.o, as they each initialise +# themselves, and md.o may use the personalities when it +# auto-initialised. +# The use of MIX_OBJS allows link order to be maintained even +# though some are export-objs and some aren't. + obj-$(CONFIG_MD_LINEAR) += linear.o obj-$(CONFIG_MD_RAID0) += raid0.o obj-$(CONFIG_MD_RAID1) += raid1.o obj-$(CONFIG_MD_RAID5) += raid5.o xor.o +obj-$(CONFIG_BLK_DEV_MD) += md.o obj-$(CONFIG_BLK_DEV_LVM) += lvm-mod.o # Translate to Rules.make lists. -O_OBJS := $(filter-out $(export-objs), $(obj-y)) -OX_OBJS := $(filter $(export-objs), $(obj-y)) -M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) -MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) +active-objs := $(sort $(obj-y) $(obj-m)) + +O_OBJS := $(obj-y) +M_OBJS := $(obj-m) +MIX_OBJS := $(filter $(export-objs), $(active-objs)) include $(TOPDIR)/Rules.make diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/linear.c linux/drivers/md/linear.c --- v2.4.0-test11/linux/drivers/md/linear.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/md/linear.c Mon Dec 11 13:19:35 2000 @@ -84,21 +84,19 @@ dev_info_t *disk = conf->disks + j; if (size < 0) { - table->dev1 = disk; - table++; + table[-1].dev1 = disk; } size += disk->size; - while (size) { + while (size>0) { table->dev0 = disk; - size -= conf->smallest->size; - if (size < 0) - break; table->dev1 = NULL; + size -= conf->smallest->size; table++; } } - table->dev1 = NULL; + if (table-conf->hash_table != nb_zone) + BUG(); return 0; @@ -136,7 +134,8 @@ if (!hash->dev1) { printk ("linear_make_request : hash->dev1==NULL for block %ld\n", block); - return -1; + buffer_IO_error(bh); + return 0; } tmp_dev = hash->dev1; } else @@ -145,7 +144,8 @@ if (block >= (tmp_dev->size + tmp_dev->offset) || block < tmp_dev->offset) { printk ("linear_make_request: Block %ld out of bounds on dev %s size %ld offset %ld\n", block, kdevname(tmp_dev->dev), tmp_dev->size, tmp_dev->offset); - return -1; + buffer_IO_error(bh); + return 0; } bh->b_rdev = tmp_dev->dev; bh->b_rsector = bh->b_rsector - (tmp_dev->offset << 1); @@ -190,24 +190,16 @@ status: linear_status, }; -#ifndef MODULE - -void md__init linear_init (void) +static int md__init linear_init (void) { - register_md_personality (LINEAR, &linear_personality); + return register_md_personality (LINEAR, &linear_personality); } -#else - -int init_module (void) -{ - return (register_md_personality (LINEAR, &linear_personality)); -} - -void cleanup_module (void) +static void linear_exit (void) { unregister_md_personality (LINEAR); } -#endif +module_init(linear_init); +module_exit(linear_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/lvm.c linux/drivers/md/lvm.c --- v2.4.0-test11/linux/drivers/md/lvm.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/md/lvm.c Mon Dec 11 13:19:35 2000 @@ -123,6 +123,7 @@ * - avoided inline strings functions lvm_strlen etc. * 14/02/2000 - support for 2.3.43 * - integrated Andrea Arcangeli's snapshot code + * 07/12/2000 - make sure lvm_make_request_fn returns correct value - 0 or 1 - NeilBrown * */ @@ -1488,8 +1489,10 @@ */ static int lvm_make_request_fn(request_queue_t *q, int rw, struct buffer_head *bh) { - lvm_map(bh, rw); - return 1; + if (lvm_map(bh, rw)<0) + return 0; /* failure, buffer_IO_error has been called, don't recurse */ + else + return 1; /* all ok, mapping done, call lower level driver */ } /* diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/md.c linux/drivers/md/md.c --- v2.4.0-test11/linux/drivers/md/md.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/md/md.c Mon Dec 11 13:19:35 2000 @@ -179,7 +179,7 @@ return mddev->pers->make_request(mddev, rw, bh); else { buffer_IO_error(bh); - return -1; + return 0; } } @@ -203,6 +203,7 @@ init_MUTEX(&mddev->resync_sem); MD_INIT_LIST_HEAD(&mddev->disks); MD_INIT_LIST_HEAD(&mddev->all_mddevs); + atomic_set(&mddev->active, 0); /* * The 'base' mddev is the one with data NULL. @@ -656,32 +657,25 @@ static int lock_rdev (mdk_rdev_t *rdev) { int err = 0; + struct block_device *bdev; - /* - * First insert a dummy inode. - */ - if (rdev->inode) - MD_BUG(); - rdev->inode = get_empty_inode(); - if (!rdev->inode) + bdev = bdget(rdev->dev); + if (bdev == NULL) return -ENOMEM; - /* - * we dont care about any other fields - */ - rdev->inode->i_dev = rdev->inode->i_rdev = rdev->dev; - insert_inode_hash(rdev->inode); - - memset(&rdev->filp, 0, sizeof(rdev->filp)); - rdev->filp.f_mode = 3; /* read write */ + err = blkdev_get(bdev, FMODE_READ|FMODE_WRITE, 0, BDEV_FILE); + if (!err) { + rdev->bdev = bdev; + } return err; } static void unlock_rdev (mdk_rdev_t *rdev) { - if (!rdev->inode) + if (!rdev->bdev) MD_BUG(); - iput(rdev->inode); - rdev->inode = NULL; + blkdev_put(rdev->bdev, BDEV_FILE); + bdput(rdev->bdev); + rdev->bdev = NULL; } static void export_rdev (mdk_rdev_t * rdev) @@ -1149,7 +1143,7 @@ abort_free: if (rdev->sb) { - if (rdev->inode) + if (rdev->bdev) unlock_rdev(rdev); free_disk_sb(rdev); } @@ -1718,12 +1712,20 @@ #define STILL_MOUNTED KERN_WARNING \ "md: md%d still mounted.\n" +#define STILL_IN_USE \ +"md: md%d still in use.\n" static int do_md_stop (mddev_t * mddev, int ro) { int err = 0, resync_interrupted = 0; kdev_t dev = mddev_to_kdev(mddev); + if (atomic_read(&mddev->active)>1) { + printk(STILL_IN_USE, mdidx(mddev)); + OUT(-EBUSY); + } + + /* this shouldn't be needed as above would have fired */ if (!ro && get_super(dev)) { printk (STILL_MOUNTED, mdidx(mddev)); OUT(-EBUSY); @@ -1859,8 +1861,10 @@ * the 'same_array' list. Then order this list based on superblock * update time (freshest comes first), kick out 'old' disks and * compare superblocks. If everything's fine then run it. + * + * If "unit" is allocated, then bump its reference count */ -static void autorun_devices (void) +static void autorun_devices (kdev_t countdev) { struct md_list_head candidates; struct md_list_head *tmp; @@ -1902,6 +1906,12 @@ continue; } mddev = alloc_mddev(md_kdev); + if (mddev == NULL) { + printk("md: cannot allocate memory for md drive.\n"); + break; + } + if (md_kdev == countdev) + atomic_inc(&mddev->active); printk("created md%d\n", mdidx(mddev)); ITERATE_RDEV_GENERIC(candidates,pending,rdev,tmp) { bind_rdev_to_array(rdev, mddev); @@ -1945,7 +1955,7 @@ #define AUTORUNNING KERN_INFO \ "md: auto-running md%d.\n" -static int autostart_array (kdev_t startdev) +static int autostart_array (kdev_t startdev, kdev_t countdev) { int err = -EINVAL, i; mdp_super_t *sb = NULL; @@ -2002,7 +2012,7 @@ /* * possibly return codes */ - autorun_devices(); + autorun_devices(countdev); return 0; abort: @@ -2077,7 +2087,7 @@ md_list_add(&rdev->pending, &pending_raid_disks); } - autorun_devices(); + autorun_devices(-1); } dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */ @@ -2607,6 +2617,8 @@ err = -ENOMEM; goto abort; } + atomic_inc(&mddev->active); + /* * alloc_mddev() should possibly self-lock. */ @@ -2640,7 +2652,7 @@ /* * possibly make it lock the array ... */ - err = autostart_array((kdev_t)arg); + err = autostart_array((kdev_t)arg, dev); if (err) { printk("autostart %s failed!\n", partition_name((kdev_t)arg)); @@ -2820,14 +2832,26 @@ static int md_open (struct inode *inode, struct file *file) { /* - * Always succeed + * Always succeed, but increment the usage count */ + mddev_t *mddev = kdev_to_mddev(inode->i_rdev); + if (mddev) + atomic_inc(&mddev->active); return (0); } +static int md_release (struct inode *inode, struct file * file) +{ + mddev_t *mddev = kdev_to_mddev(inode->i_rdev); + if (mddev) + atomic_dec(&mddev->active); + return 0; +} + static struct block_device_operations md_fops= { open: md_open, + release: md_release, ioctl: md_ioctl, }; @@ -3279,7 +3303,7 @@ if (mddev2 == mddev) continue; if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { - printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2)); + printk(KERN_INFO "md: serializing resync, md%d shares one or more physical units with md%d!\n", mdidx(mddev), mdidx(mddev2)); serialize = 1; break; } @@ -3576,20 +3600,14 @@ create_proc_read_entry("mdstat", 0, NULL, md_status_read_proc, NULL); #endif } -void hsm_init (void); -void translucent_init (void); -void linear_init (void); -void raid0_init (void); -void raid1_init (void); -void raid5_init (void); int md__init md_init (void) { static char * name = "mdrecoveryd"; - printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n", + printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MD_SB_DISKS=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, - MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL); + MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); if (devfs_register_blkdev (MAJOR_NR, "md", &md_fops)) { @@ -3617,18 +3635,6 @@ md_register_reboot_notifier(&md_notifier); raid_table_header = register_sysctl_table(raid_root_table, 1); -#ifdef CONFIG_MD_LINEAR - linear_init (); -#endif -#ifdef CONFIG_MD_RAID0 - raid0_init (); -#endif -#ifdef CONFIG_MD_RAID1 - raid1_init (); -#endif -#ifdef CONFIG_MD_RAID5 - raid5_init (); -#endif md_geninit(); return (0); } @@ -3639,7 +3645,7 @@ unsigned long set; int pers[MAX_MD_BOOT_DEVS]; int chunk[MAX_MD_BOOT_DEVS]; - kdev_t devices[MAX_MD_BOOT_DEVS][MAX_REAL]; + kdev_t devices[MAX_MD_BOOT_DEVS][MD_SB_DISKS]; } md_setup_args md__initdata = { 0, }; /* @@ -3713,7 +3719,7 @@ pername="super-block"; } devnames = str; - for (; ib_rsector, bh->b_size >> 10); - return -1; + goto outerr; bad_hash: printk("raid0_make_request bug: hash==NULL for block %ld\n", block); - return -1; + goto outerr; bad_zone0: printk ("raid0_make_request bug: hash->zone0==NULL for block %ld\n", block); - return -1; + goto outerr; bad_zone1: printk ("raid0_make_request bug: hash->zone1==NULL for block %ld\n", block); - return -1; + outerr: + buffer_IO_error(bh); + return 0; } static int raid0_status (char *page, mddev_t *mddev) @@ -333,24 +335,17 @@ status: raid0_status, }; -#ifndef MODULE - -void raid0_init (void) +static int md__init raid0_init (void) { - register_md_personality (RAID0, &raid0_personality); + return register_md_personality (RAID0, &raid0_personality); } -#else - -int init_module (void) -{ - return (register_md_personality (RAID0, &raid0_personality)); -} - -void cleanup_module (void) +static void raid0_exit (void) { unregister_md_personality (RAID0); } -#endif +module_init(raid0_init); +module_exit(raid0_exit); + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/raid1.c linux/drivers/md/raid1.c --- v2.4.0-test11/linux/drivers/md/raid1.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/md/raid1.c Mon Dec 11 13:19:35 2000 @@ -463,16 +463,12 @@ if (conf->resync_mirrors) goto rb_out; - if (conf->working_disks < 2) { - int i = 0; - - while( !conf->mirrors[new_disk].operational && - (i < MD_SB_DISKS) ) { - new_disk = conf->mirrors[new_disk].next; - i++; - } - - if (i >= MD_SB_DISKS) { + + /* make sure that disk is operational */ + while( !conf->mirrors[new_disk].operational) { + if (new_disk <= 0) new_disk = conf->raid_disks; + new_disk--; + if (new_disk == disk) { /* * This means no working disk was found * Nothing much to do, lets not change anything @@ -480,11 +476,13 @@ */ new_disk = conf->last_used; + + goto rb_out; } - - goto rb_out; } - + disk = new_disk; + /* now disk == new_disk == starting point for search */ + /* * Don't touch anything for sequential reads. */ @@ -501,16 +499,16 @@ if (conf->sect_count >= conf->mirrors[new_disk].sect_limit) { conf->sect_count = 0; - - while( new_disk != conf->mirrors[new_disk].next ) { - if ((conf->mirrors[new_disk].write_only) || - (!conf->mirrors[new_disk].operational) ) - continue; - - new_disk = conf->mirrors[new_disk].next; - break; - } - + + do { + if (new_disk<=0) + new_disk = conf->raid_disks; + new_disk--; + if (new_disk == disk) + break; + } while ((conf->mirrors[new_disk].write_only) || + (!conf->mirrors[new_disk].operational)); + goto rb_out; } @@ -519,8 +517,10 @@ /* Find the disk which is closest */ - while( conf->mirrors[disk].next != conf->last_used ) { - disk = conf->mirrors[disk].next; + do { + if (disk <= 0) + disk = conf->raid_disks; + disk--; if ((conf->mirrors[disk].write_only) || (!conf->mirrors[disk].operational)) @@ -534,7 +534,7 @@ current_distance = new_distance; new_disk = disk; } - } + } while (disk != conf->last_used); rb_out: conf->mirrors[new_disk].head_position = this_sector + sectors; @@ -702,16 +702,6 @@ return sz; } -static void unlink_disk (raid1_conf_t *conf, int target) -{ - int disks = MD_SB_DISKS; - int i; - - for (i = 0; i < disks; i++) - if (conf->mirrors[i].next == target) - conf->mirrors[i].next = conf->mirrors[target].next; -} - #define LAST_DISK KERN_ALERT \ "raid1: only one disk left and IO error.\n" @@ -735,7 +725,6 @@ mdp_super_t *sb = mddev->sb; mirror->operational = 0; - unlink_disk(conf, failed); mark_disk_faulty(sb->disks+mirror->number); mark_disk_nonsync(sb->disks+mirror->number); mark_disk_inactive(sb->disks+mirror->number); @@ -786,25 +775,6 @@ #undef DISK_FAILED #undef START_SYNCING -/* - * Insert the spare disk into the drive-ring - */ -static void link_disk(raid1_conf_t *conf, struct mirror_info *mirror) -{ - int j, next; - int disks = MD_SB_DISKS; - struct mirror_info *p = conf->mirrors; - - for (j = 0; j < disks; j++, p++) - if (p->operational && !p->write_only) { - next = p->next; - p->next = mirror->raid_disk; - mirror->next = next; - return; - } - - printk("raid1: bug: no read-operational devices\n"); -} static void print_raid1_conf (raid1_conf_t *conf) { @@ -828,6 +798,32 @@ } } +static void close_sync(raid1_conf_t *conf) +{ + mddev_t *mddev = conf->mddev; + /* If reconstruction was interrupted, we need to close the "active" and "pending" + * holes. + * we know that there are no active rebuild requests, os cnt_active == cnt_ready ==0 + */ + /* this is really needed when recovery stops too... */ + spin_lock_irq(&conf->segment_lock); + conf->start_active = conf->start_pending; + conf->start_ready = conf->start_pending; + wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); + conf->start_active =conf->start_ready = conf->start_pending = conf->start_future; + conf->start_future = mddev->sb->size+1; + conf->cnt_pending = conf->cnt_future; + conf->cnt_future = 0; + conf->phase = conf->phase ^1; + wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); + conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0; + conf->phase = 0; + conf->cnt_future = conf->cnt_done;; + conf->cnt_done = 0; + spin_unlock_irq(&conf->segment_lock); + wake_up(&conf->wait_done); +} + static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state) { int err = 0; @@ -940,6 +936,7 @@ * Deactivate a spare disk: */ case DISKOP_SPARE_INACTIVE: + close_sync(conf); sdisk = conf->mirrors + spare_disk; sdisk->operational = 0; sdisk->write_only = 0; @@ -952,7 +949,7 @@ * property) */ case DISKOP_SPARE_ACTIVE: - + close_sync(conf); sdisk = conf->mirrors + spare_disk; fdisk = conf->mirrors + failed_disk; @@ -1017,7 +1014,6 @@ */ fdisk->spare = 0; fdisk->write_only = 0; - link_disk(conf, fdisk); /* * if we activate a spare, we definitely replace a @@ -1244,27 +1240,7 @@ conf->resync_mirrors = 0; } - /* If reconstruction was interrupted, we need to close the "active" and "pending" - * holes. - * we know that there are no active rebuild requests, os cnt_active == cnt_ready ==0 - */ - /* this is really needed when recovery stops too... */ - spin_lock_irq(&conf->segment_lock); - conf->start_active = conf->start_pending; - conf->start_ready = conf->start_pending; - wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); - conf->start_active =conf->start_ready = conf->start_pending = conf->start_future; - conf->start_future = mddev->sb->size+1; - conf->cnt_pending = conf->cnt_future; - conf->cnt_future = 0; - conf->phase = conf->phase ^1; - wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); - conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0; - conf->phase = 0; - conf->cnt_future = conf->cnt_done;; - conf->cnt_done = 0; - spin_unlock_irq(&conf->segment_lock); - wake_up(&conf->wait_done); + close_sync(conf); up(&mddev->recovery_sem); raid1_shrink_buffers(conf); @@ -1325,6 +1301,7 @@ struct raid1_bh *r1_bh; struct buffer_head *bh; int bsize; + int disk; spin_lock_irq(&conf->segment_lock); if (!block_nr) { @@ -1377,6 +1354,16 @@ * could dedicate one to rebuild and others to * service read requests .. */ + disk = conf->last_used; + /* make sure disk is operational */ + while (!conf->mirrors[disk].operational) { + if (disk <= 0) disk = conf->raid_disks; + disk--; + if (disk == conf->last_used) + break; + } + conf->last_used = disk; + mirror = conf->mirrors+conf->last_used; r1_bh = raid1_alloc_buf (conf); @@ -1396,7 +1383,7 @@ bh->b_list = BUF_LOCKED; bh->b_dev = mirror->dev; bh->b_rdev = mirror->dev; - bh->b_state = (1<b_state = (1<b_page) BUG(); if (!bh->b_data) @@ -1717,19 +1704,10 @@ * find the first working one and use it as a starting point * to read balancing. */ - for (j = 0; !conf->mirrors[j].operational; j++) + for (j = 0; !conf->mirrors[j].operational && j < MD_SB_DISKS; j++) /* nothing */; conf->last_used = j; - /* - * initialize the 'working disks' list. - */ - for (i = conf->raid_disks - 1; i >= 0; i--) { - if (conf->mirrors[i].operational) { - conf->mirrors[i].next = j; - j = i; - } - } if (conf->working_disks != sb->raid_disks) { printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); @@ -1882,19 +1860,16 @@ sync_request: raid1_sync_request }; -int raid1_init (void) +static int md__init raid1_init (void) { return register_md_personality (RAID1, &raid1_personality); } -#ifdef MODULE -int init_module (void) -{ - return raid1_init(); -} - -void cleanup_module (void) +static void raid1_exit (void) { unregister_md_personality (RAID1); } -#endif + +module_init(raid1_init); +module_exit(raid1_exit); + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/raid5.c linux/drivers/md/raid5.c --- v2.4.0-test11/linux/drivers/md/raid5.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/md/raid5.c Mon Dec 11 13:19:34 2000 @@ -1516,8 +1516,8 @@ raid5_conf_t *conf = (raid5_conf_t *) mddev->private; struct stripe_head *sh; int sectors_per_chunk = conf->chunk_size >> 9; - unsigned long stripe = (block_nr<<2)/sectors_per_chunk; - int chunk_offset = (block_nr<<2) % sectors_per_chunk; + unsigned long stripe = (block_nr<<1)/sectors_per_chunk; + int chunk_offset = (block_nr<<1) % sectors_per_chunk; int dd_idx, pd_idx; unsigned long first_sector; int raid_disks = conf->raid_disks; @@ -2352,19 +2352,16 @@ sync_request: raid5_sync_request }; -int raid5_init (void) +static int md__init raid5_init (void) { return register_md_personality (RAID5, &raid5_personality); } -#ifdef MODULE -int init_module (void) -{ - return raid5_init(); -} - -void cleanup_module (void) +static void raid5_exit (void) { unregister_md_personality (RAID5); } -#endif + +module_init(raid5_init); +module_exit(raid5_exit); + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/md/xor.c linux/drivers/md/xor.c --- v2.4.0-test11/linux/drivers/md/xor.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/md/xor.c Tue Dec 5 12:43:47 2000 @@ -16,7 +16,6 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include #define BH_TRACE 0 #include #include diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-aimslab.c linux/drivers/media/radio/radio-aimslab.c --- v2.4.0-test11/linux/drivers/media/radio/radio-aimslab.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-aimslab.c Mon Nov 27 17:47:38 2000 @@ -338,7 +338,7 @@ return -EINVAL; } - if (check_region(io, 2)) + if (request_region(io, 2, "rtrack")) { printk(KERN_ERR "rtrack: port 0x%x already in use\n", io); return -EBUSY; @@ -347,9 +347,10 @@ rtrack_radio.priv=&rtrack_unit; if(video_register_device(&rtrack_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io, 2); return -EINVAL; - - request_region(io, 2, "rtrack"); + } printk(KERN_INFO "AIMSlab RadioTrack/RadioReveal card driver.\n"); /* Set up the I/O locking */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-aztech.c linux/drivers/media/radio/radio-aztech.c --- v2.4.0-test11/linux/drivers/media/radio/radio-aztech.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-aztech.c Mon Nov 27 17:47:38 2000 @@ -289,7 +289,7 @@ return -EINVAL; } - if (check_region(io, 2)) + if (request_region(io, 2, "aztech")) { printk(KERN_ERR "aztech: port 0x%x already in use\n", io); return -EBUSY; @@ -299,9 +299,11 @@ aztech_radio.priv=&aztech_unit; if(video_register_device(&aztech_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io,2); return -EINVAL; + } - request_region(io, 2, "aztech"); printk(KERN_INFO "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n"); /* mute card - prevents noisy bootups */ outb (0, io); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-cadet.c linux/drivers/media/radio/radio-cadet.c --- v2.4.0-test11/linux/drivers/media/radio/radio-cadet.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-cadet.c Mon Nov 27 17:47:38 2000 @@ -27,6 +27,7 @@ #include /* kernel radio structs */ #include /* CONFIG_RADIO_CADET_PORT */ #include +#include #ifndef CONFIG_RADIO_CADET_PORT #define CONFIG_RADIO_CADET_PORT 0x330 @@ -44,16 +45,9 @@ static unsigned char rdsbuf[RDS_BUFFER]; static int cadet_lock=0; -#ifndef MODULE static int cadet_probe(void); -#endif - -#ifdef CONFIG_ISAPNP -#include - -struct pci_dev *dev; +static struct pci_dev *dev; static int isapnp_cadet_probe(void); -#endif /* * Signal Strength Threshold Values @@ -551,7 +545,6 @@ ioctl: cadet_ioctl, }; -#ifdef CONFIG_ISAPNP static int isapnp_cadet_probe(void) { dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'), @@ -574,9 +567,7 @@ return io; } -#endif /* CONFIG_ISAPNP */ -#ifdef MODULE static int cadet_probe(void) { static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; @@ -584,30 +575,35 @@ for(i=0;i<8;i++) { io=iovals[i]; - if(check_region(io,2)>=0) { + if(request_region(io,2, "cadet-probe")>=0) { cadet_setfreq(1410); if(cadet_getfreq()==1410) { + release_region(io, 2); return io; } + release_region(io, 2); } } return -1; } -#endif /* MODULE */ static int __init cadet_init(void) { -#ifdef CONFIG_ISAPNP - io = isapnp_cadet_probe(); - + /* + * If a probe was requested then probe ISAPnP first (safest) + */ if (io < 0) - return (io); -#else -#ifndef MODULE /* only probe on non-ISAPnP monolithic compiles */ - io = cadet_probe (); -#endif /* MODULE */ -#endif /* CONFIG_ISAPNP */ + io = isapnp_cadet_probe(); + /* + * If that fails then probe unsafely if probe is requested + */ + if(io < 0) + io = cadet_probe (); + /* + * Else we bail out + */ + if(io < 0) { #ifdef MODULE printk(KERN_ERR "You must set an I/O address with io=0x???\n"); @@ -638,10 +634,8 @@ video_unregister_device(&cadet_radio); release_region(io,2); -#ifdef CONFIG_ISAPNP if (dev) dev->deactivate(dev); -#endif } module_init(cadet_init); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-gemtek.c linux/drivers/media/radio/radio-gemtek.c --- v2.4.0-test11/linux/drivers/media/radio/radio-gemtek.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-gemtek.c Mon Nov 27 17:47:38 2000 @@ -265,7 +265,7 @@ return -EINVAL; } - if (check_region(io, 4)) + if (request_region(io, 4, "gemtek")) { printk(KERN_ERR "gemtek: port 0x%x already in use\n", io); return -EBUSY; @@ -274,9 +274,10 @@ gemtek_radio.priv=&gemtek_unit; if(video_register_device(&gemtek_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io, 4); return -EINVAL; - - request_region(io, 4, "gemtek"); + } printk(KERN_INFO "GemTek Radio Card driver.\n"); spin_lock_init(&lock); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-rtrack2.c linux/drivers/media/radio/radio-rtrack2.c --- v2.4.0-test11/linux/drivers/media/radio/radio-rtrack2.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-rtrack2.c Mon Nov 27 17:47:38 2000 @@ -230,7 +230,7 @@ printk(KERN_ERR "You must set an I/O address with io=0x20c or io=0x30c\n"); return -EINVAL; } - if (check_region(io, 4)) + if (request_region(io, 4, "rtrack2")) { printk(KERN_ERR "rtrack2: port 0x%x already in use\n", io); return -EBUSY; @@ -240,9 +240,11 @@ spin_lock_init(&lock); if(video_register_device(&rtrack2_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io, 4); return -EINVAL; + } - request_region(io, 4, "rtrack2"); printk(KERN_INFO "AIMSlab Radiotrack II card driver.\n"); /* mute card - prevents noisy bootups */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-sf16fmi.c linux/drivers/media/radio/radio-sf16fmi.c --- v2.4.0-test11/linux/drivers/media/radio/radio-sf16fmi.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-sf16fmi.c Mon Nov 27 17:47:38 2000 @@ -291,7 +291,7 @@ printk(KERN_ERR "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if (check_region(io, 2)) + if (request_region(io, 2, "fmi")) { printk(KERN_ERR "fmi: port 0x%x already in use\n", io); return -EBUSY; @@ -306,9 +306,11 @@ init_MUTEX(&lock); if(video_register_device(&fmi_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io, 2); return -EINVAL; + } - request_region(io, 2, "fmi"); printk(KERN_INFO "SF16FMx radio card driver at 0x%x.\n", io); printk(KERN_INFO "(c) 1998 Petr Vandrovec, vandrove@vc.cvut.cz.\n"); /* mute card - prevents noisy bootups */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-terratec.c linux/drivers/media/radio/radio-terratec.c --- v2.4.0-test11/linux/drivers/media/radio/radio-terratec.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-terratec.c Mon Nov 27 17:47:38 2000 @@ -309,7 +309,7 @@ printk(KERN_ERR "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if (check_region(io, 2)) + if (request_region(io, 2, "terratec")) { printk(KERN_ERR "TerraTec: port 0x%x already in use\n", io); return -EBUSY; @@ -320,9 +320,11 @@ spin_lock_init(&lock); if(video_register_device(&terratec_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io,2); return -EINVAL; + } - request_region(io, 2, "terratec"); printk(KERN_INFO "TERRATEC ActivRadio Standalone card driver.\n"); /* mute card - prevents noisy bootups */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-trust.c linux/drivers/media/radio/radio-trust.c --- v2.4.0-test11/linux/drivers/media/radio/radio-trust.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-trust.c Mon Nov 27 17:47:38 2000 @@ -300,14 +300,15 @@ printk(KERN_ERR "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if(check_region(io, 2)) { + if(request_region(io, 2, "Trust FM Radio")) { printk(KERN_ERR "trust: port 0x%x already in use\n", io); return -EBUSY; } if(video_register_device(&trust_radio, VFL_TYPE_RADIO)==-1) + { + release_region(io, 2); return -EINVAL; - - request_region(io, 2, "Trust FM Radio"); + } printk(KERN_INFO "Trust FM Radio card driver v1.0.\n"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-typhoon.c linux/drivers/media/radio/radio-typhoon.c --- v2.4.0-test11/linux/drivers/media/radio/radio-typhoon.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-typhoon.c Mon Nov 27 17:47:38 2000 @@ -350,7 +350,7 @@ printk(KERN_INFO BANNER); io = typhoon_unit.iobase; - if (check_region(io, 8)) { + if (request_region(io, 8, "typhoon")) { printk(KERN_ERR "radio-typhoon: port 0x%x already in use\n", typhoon_unit.iobase); return -EBUSY; @@ -358,9 +358,10 @@ typhoon_radio.priv = &typhoon_unit; if (video_register_device(&typhoon_radio, VFL_TYPE_RADIO) == -1) + { + release_region(io, 8); return -EINVAL; - - request_region(typhoon_unit.iobase, 8, "typhoon"); + } printk(KERN_INFO "radio-typhoon: port 0x%x.\n", typhoon_unit.iobase); printk(KERN_INFO "radio-typhoon: mute frequency is %lu kHz.\n", typhoon_unit.mutefreq); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/radio/radio-zoltrix.c linux/drivers/media/radio/radio-zoltrix.c --- v2.4.0-test11/linux/drivers/media/radio/radio-zoltrix.c Sun Nov 19 18:44:08 2000 +++ linux/drivers/media/radio/radio-zoltrix.c Mon Nov 27 17:47:38 2000 @@ -355,20 +355,22 @@ printk(KERN_ERR "You must set an I/O address with io=0x???\n"); return -EINVAL; } - if (check_region(io, 2)) { - printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); - return -EBUSY; - } if ((io != 0x20c) && (io != 0x30c)) { printk(KERN_ERR "zoltrix: invalid port, try 0x20c or 0x30c\n"); return -ENXIO; } + zoltrix_radio.priv = &zoltrix_unit; + if (request_region(io, 2, "zoltrix")) { + printk(KERN_ERR "zoltrix: port 0x%x already in use\n", io); + return -EBUSY; + } if (video_register_device(&zoltrix_radio, VFL_TYPE_RADIO) == -1) + { + release_region(io, 2); return -EINVAL; - - request_region(io, 2, "zoltrix"); + } printk(KERN_INFO "Zoltrix Radio Plus card driver.\n"); init_MUTEX(&zoltrix_unit.lock); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/bttv-cards.c linux/drivers/media/video/bttv-cards.c --- v2.4.0-test11/linux/drivers/media/video/bttv-cards.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/media/video/bttv-cards.c Sun Dec 3 17:45:22 2000 @@ -1319,6 +1319,24 @@ } } +#ifndef MODULE + +static int __init bttv_card_setup(char *str) +{ + int i,number,res = 2; + + for (i = 0; res == 2 && i < BTTV_MAX; i++) { + res = get_option(&str,&number); + if (res) + card[i] = number; + } + return 1; +} + +__setup("bttv_card=", bttv_card_setup); + +#endif /* not MODULE */ + /* * Local variables: * c-basic-offset: 8 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c --- v2.4.0-test11/linux/drivers/media/video/bttv-driver.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/media/video/bttv-driver.c Sun Dec 3 17:45:22 2000 @@ -3082,6 +3082,24 @@ module_init(bttv_init_module); module_exit(bttv_cleanup_module); +#ifndef MODULE + +static int __init bttv_radio_setup(char *str) +{ + int i,number,res = 2; + + for (i = 0; res == 2 && i < BTTV_MAX; i++) { + res = get_option(&str,&number); + if (res) + radio[i] = number; + } + return 1; +} + +__setup("bttv_radio=", bttv_radio_setup); + +#endif /* not MODULE */ + /* * Local variables: * c-basic-offset: 8 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/bw-qcam.c linux/drivers/media/video/bw-qcam.c --- v2.4.0-test11/linux/drivers/media/video/bw-qcam.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/media/video/bw-qcam.c Mon Nov 27 17:47:38 2000 @@ -865,12 +865,9 @@ case VIDIOCGWIN: { struct video_window vw; - vw.x=0; - vw.y=0; + memset(&vw, 0, sizeof(vw)); vw.width=qcam->width/qcam->transfer_scale; vw.height=qcam->height/qcam->transfer_scale; - vw.chromakey=0; - vw.flags=0; if(copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; return 0; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/c-qcam.c linux/drivers/media/video/c-qcam.c --- v2.4.0-test11/linux/drivers/media/video/c-qcam.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/media/video/c-qcam.c Mon Nov 27 17:47:38 2000 @@ -679,12 +679,9 @@ case VIDIOCGWIN: { struct video_window vw; - vw.x=0; - vw.y=0; + memset(&vw, 0, sizeof(vw)); vw.width=qcam->width; vw.height=qcam->height; - vw.chromakey=0; - vw.flags=0; if(copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; return 0; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/msp3400.c linux/drivers/media/video/msp3400.c --- v2.4.0-test11/linux/drivers/media/video/msp3400.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/media/video/msp3400.c Sun Dec 3 17:45:22 2000 @@ -912,7 +912,7 @@ msp->thread = NULL; if(msp->notify != NULL) - up(msp->notify); + up_and_exit(msp->notify, 0); return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/tvaudio.c linux/drivers/media/video/tvaudio.c --- v2.4.0-test11/linux/drivers/media/video/tvaudio.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/media/video/tvaudio.c Tue Dec 5 12:43:47 2000 @@ -14,6 +14,7 @@ * */ +#include #include #include #include @@ -291,7 +292,7 @@ chip->thread = NULL; dprintk("%s: thread exiting\n", chip->c.name); if(chip->notify != NULL) - up(chip->notify); + up_and_exit(chip->notify,0); return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/media/video/zr36120.h linux/drivers/media/video/zr36120.h --- v2.4.0-test11/linux/drivers/media/video/zr36120.h Wed Dec 29 17:08:55 1999 +++ linux/drivers/media/video/zr36120.h Mon Dec 11 13:38:29 2000 @@ -130,7 +130,7 @@ int tuner_type; /* tuner type, when found */ int running; /* are we rolling? */ rwlock_t lock; - int state; /* what is requested of us? */ + long state; /* what is requested of us? */ #define STATE_OVERLAY 0 #define STATE_VBI 1 struct vidinfo* workqueue; /* buffers to grab, head is active */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/Config.in linux/drivers/mtd/Config.in --- v2.4.0-test11/linux/drivers/mtd/Config.in Sun Aug 13 10:21:20 2000 +++ linux/drivers/mtd/Config.in Mon Dec 11 14:57:58 2000 @@ -1,15 +1,21 @@ -# $Id: Config.in,v 1.20 2000/07/13 12:40:46 scote1 Exp $ +# $Id: No. :) $ mainmenu_option next_comment comment 'Memory Technology Devices (MTD)' tristate 'Memory Technology Device (MTD) support' CONFIG_MTD -if [ "$CONFIG_MTD" != "n" ]; then - dep_tristate ' M-Systems Disk-On-Chip 1000 support' CONFIG_MTD_DOC1000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip 2000' CONFIG_MTD_DOC2000 $CONFIG_MTD - dep_tristate ' M-Systems Disk-On-Chip Millennium' CONFIG_MTD_DOC2001 $CONFIG_MTD +if [ "$CONFIG_MTD" = "y" -o "$CONFIG_MTD" = "m" ]; then + bool 'Debugging' CONFIG_MTD_DEBUG + if [ "$CONFIG_MTD_DEBUG" = "y" ]; then + int ' Debugging verbosity (0 = quiet, 3 = noisy)' CONFIG_MTD_DEBUG_VERBOSE 0 + fi + +comment 'Disk-On-Chip Device Drivers' + dep_tristate ' M-Systems Disk-On-Chip 1000' CONFIG_MTD_DOC1000 $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip 2000 and Millennium' CONFIG_MTD_DOC2000 $CONFIG_MTD + dep_tristate ' M-Systems Disk-On-Chip Millennium-only alternative driver' CONFIG_MTD_DOC2001 $CONFIG_MTD if [ "$CONFIG_MTD_DOC2001" = "y" -o "$CONFIG_MTD_DOC2000" = "y" ]; then define_tristate CONFIG_MTD_DOCPROBE y else @@ -19,10 +25,18 @@ define_tristate CONFIG_MTD_DOCPROBE n fi fi + if [ "$CONFIG_MTD_DOCPROBE" = "y" -o "$CONFIG_MTD_DOCPROBE" = "m" ]; then + hex ' Physical address of DiskOnChip' CONFIG_MTD_DOCPROBE_ADDRESS 0x0000 + bool ' Probe high addresses' CONFIG_MTD_DOCPROBE_HIGH + bool ' Probe for 0x55 0xAA BIOS Extension Signature' CONFIG_MTD_DOCPROBE_55AA + fi + +comment 'RAM/ROM Device Drivers' dep_tristate ' Use extra onboard system memory as MTD device' CONFIG_MTD_SLRAM $CONFIG_MTD dep_tristate ' Ramix PMC551 PCI Mezzanine ram card support' CONFIG_MTD_PMC551 $CONFIG_MTD $CONFIG_PCI if [ "$CONFIG_MTD_PMC551" != "n" ]; then bool ' PMC551 256M DRAM Bugfix' CONFIG_MTD_PMC551_BUGFIX + bool ' PMC551 Debugging' CONFIG_MTD_PMC551_DEBUG fi dep_tristate ' Debugging RAM test driver' CONFIG_MTD_MTDRAM $CONFIG_MTD if [ "$CONFIG_MTD_MTDRAM" != "n" ]; then @@ -30,20 +44,21 @@ int 'Size of the erase sectors in kB' CONFIG_MTDRAM_ERASE_SIZE 128 fi -comment 'MTD drivers for mapped chips' +comment 'Linearly Mapped Flash Device Drivers' dep_tristate ' Common Flash Interface (CFI) support' CONFIG_MTD_CFI $CONFIG_MTD dep_tristate ' CFI support for Intel/Sharp Extended Command Set chips' CONFIG_MTD_CFI_INTELEXT $CONFIG_MTD_CFI dep_tristate ' CFI support for AMD/Fujitsu Standard Command Set chips' CONFIG_MTD_CFI_AMDSTD $CONFIG_MTD_CFI + dep_tristate ' Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONFIG_MTD + dep_tristate ' Support for ROM chips in bus mapping' CONFIG_MTD_ROM $CONFIG_MTD # These will later become config-options define_bool CONFIG_MTD_JEDEC n -define_bool CONFIG_MTD_RAM n -define_bool CONFIG_MTD_ROM n - dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI - if [ "$CONFIG_MTD_PHYSMAP" != "n" ]; then - hex 'Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 - hex 'Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 + dep_tristate ' Flash chip mapping in physical memory' CONFIG_MTD_PHYSMAP $CONFIG_MTD_CFI + if [ "$CONFIG_MTD_PHYSMAP" = "y" -o "$CONFIG_MTD_PHYSMAP" = "m" ]; then + hex ' Physical start location of flash chip mapping' CONFIG_MTD_PHYSMAP_START 0x8000000 + hex ' Physical length of flash chip mapping' CONFIG_MTD_PHYSMAP_LEN 0x4000000 + int ' Bus width in octets' CONFIG_MTD_PHYSMAP_BUSWIDTH 2 fi comment 'Drivers for chip mappings' @@ -56,11 +71,11 @@ comment 'User modules and translation layers for MTD devices' dep_tristate ' Direct chardevice access to MTD devices' CONFIG_MTD_CHAR $CONFIG_MTD - dep_tristate ' Pseudo-blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD + dep_tristate ' Caching blockdevice access to MTD devices' CONFIG_MTD_BLOCK $CONFIG_MTD dep_tristate ' FTL (Flash Translation Layer) support' CONFIG_FTL $CONFIG_MTD dep_tristate ' NFTL (NAND Flash Translation Layer) support' CONFIG_NFTL $CONFIG_MTD - if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NFTL" != "n" ]; then - bool ' Write support for NFTL (EXPERIMENTAL)' CONFIG_NFTL_RW + if [ "$CONFIG_NFTL" = "y" -o "$CONFIG_NFTL" = "m" ]; then + bool ' Write support for NFTL (BETA)' CONFIG_NFTL_RW fi fi diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/Makefile linux/drivers/mtd/Makefile --- v2.4.0-test11/linux/drivers/mtd/Makefile Sun Nov 19 18:44:09 2000 +++ linux/drivers/mtd/Makefile Mon Dec 11 14:57:58 2000 @@ -44,7 +44,7 @@ ALL_SUB_DIRS := MOD_SUB_DIRS := -export-objs := mtdcore.o +export-objs := mtdcore.o mtdpart.o list-multi := # MTD devices @@ -52,7 +52,7 @@ obj-$(CONFIG_MTD_DOC1000) += doc1000.o obj-$(CONFIG_MTD_DOC2000) += doc2000.o obj-$(CONFIG_MTD_DOC2001) += doc2001.o -obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o +obj-$(CONFIG_MTD_DOCPROBE) += docprobe.o docecc.o obj-$(CONFIG_MTD_SLRAM) += slram.o obj-$(CONFIG_MTD_PMC551) += pmc551.o obj-$(CONFIG_MTD_MTDRAM) += mtdram.o @@ -70,7 +70,7 @@ obj-$(CONFIG_MTD_MIXMEM) += mixmem.o obj-$(CONFIG_MTD_NORA) += nora.o obj-$(CONFIG_MTD_OCTAGON) += octagon-5066.o -obj-$(CONFIG_MTD_PNC2000) += pnc2000.o +obj-$(CONFIG_MTD_PNC2000) += pnc2000.o mtdpart.o obj-$(CONFIG_MTD_RPXLITE) += rpxlite.o obj-$(CONFIG_MTD_VMAX) += vmax301.o @@ -78,7 +78,7 @@ obj-$(CONFIG_MTD_CHAR) += mtdchar.o obj-$(CONFIG_MTD_BLOCK) += mtdblock.o obj-$(CONFIG_FTL) += ftl.o -obj-$(CONFIG_NFTL) += nftl.o +obj-$(CONFIG_NFTL) += nftl.o nftlmount.o # Extract lists of the multi-part drivers. # The 'int-*' lists are the intermediate files used to build the multi's. diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/cfi_cmdset_0002.c linux/drivers/mtd/cfi_cmdset_0002.c --- v2.4.0-test11/linux/drivers/mtd/cfi_cmdset_0002.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/mtd/cfi_cmdset_0002.c Sun Dec 3 17:45:22 2000 @@ -437,7 +437,7 @@ adr = instr->addr - (chipnum << cfi->chipshift) * (cfi->interleave); len = instr->len; -printk("erase : 0x%lx 0x%lx 0x%x 0x%x\n", adr, len, chipnum, mtd->size); + printk("erase : 0x%lx 0x%lx 0x%x 0x%lx\n", adr, len, chipnum, mtd->size); while(len) { //printk("erase : 0x%x 0x%x 0x%x 0x%x\n", chipnum, adr, len, cfi->chipshift); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/doc1000.c linux/drivers/mtd/doc1000.c --- v2.4.0-test11/linux/drivers/mtd/doc1000.c Thu Jul 6 01:22:24 2000 +++ linux/drivers/mtd/doc1000.c Sun Dec 3 17:45:22 2000 @@ -1,16 +1,7 @@ /*====================================================================== - $Id: doc1000.c,v 1.8 2000/07/03 10:01:38 dwmw2 Exp $ + $Id: doc1000.c,v 1.11 2000/11/24 13:43:16 dwmw2 Exp $ - A general driver for accessing PCMCIA card memory via Bulk - Memory Services. - - This driver provides the equivalent of /dev/mem for a PCMCIA - card's attribute and common memory. It includes character - and block devices. - - Written by David Hinds, dhinds@allegro.stanford.edu - ======================================================================*/ @@ -295,10 +286,9 @@ static inline int byte_write (volatile u_char *addr, u_char byte) { register u_char status; - register u_short i; - - for (i = 0; i < max_tries; i++) - { + register u_short i = 0; + + do { status = readb(addr); if (status & CSR_WR_READY) { @@ -306,7 +296,9 @@ writeb(byte, addr); return 0; } - } + i++; + } while(i < max_tries); + printk(KERN_NOTICE "flashcard: byte_write timed out, status 0x%x\n",status); return -EIO; @@ -314,11 +306,10 @@ static inline int word_write (volatile u_char *addr, __u16 word) { - register u_short status = 0; - register u_short i; + register u_short status; + register u_short i = 0; - for (i = 0; i < max_tries; i++) - { + do { status = readw(addr); if ((status & CSR_WR_READY) == CSR_WR_READY) { @@ -326,7 +317,8 @@ writew(word, addr); return 0; } - } + i++; + } while(i < max_tries); printk(KERN_NOTICE "flashcard: word_write timed out at %p, status 0x%x\n", addr, status); return -EIO; @@ -362,24 +354,22 @@ static inline int suspend_erase(volatile u_char *addr) { - __u16 status = 0; - u_long i; + __u16 status; + u_long i = 0; writew(IF_ERASE_SUSPEND, addr); writew(IF_READ_CSR, addr); - for (i = 0; i < max_tries; i++) - { + do { status = readw(addr); - if ((status & CSR_WR_READY) == CSR_WR_READY) break; - } - if (i == max_tries) - { - printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); - return -EIO; - } - - return 0; + if ((status & CSR_WR_READY) == CSR_WR_READY) + return 0; + i++; + } while(i < max_tries); + + printk(KERN_NOTICE "flashcard: suspend_erase timed out, status 0x%x\n", status); + return -EIO; + } static inline void resume_erase(volatile u_char *addr) @@ -413,12 +403,11 @@ static inline int check_write(volatile u_char *addr) { - u_short status = 0, i; + u_short status, i = 0; writew(IF_READ_CSR, addr); - for (i=0; i < max_tries; i++) - { + do { status = readw(addr); if (status & (CSR_WR_ERR | CSR_VPP_LOW)) { @@ -428,7 +417,9 @@ } if ((status & CSR_WR_READY) == CSR_WR_READY) return 0; - } + i++; + } while (i < max_tries); + printk(KERN_NOTICE "flashcard: write timed out at %p, status 0x%x\n", addr, status); return -EIO; } @@ -519,7 +510,7 @@ } -#if defined (MODULE) && LINUX_VERSION_CODE < 0x20300 +#if defined (MODULE) && LINUX_VERSION_CODE < 0x20211 #define init_doc1000 init_module #define cleanup_doc1000 cleanup_module #endif @@ -600,3 +591,7 @@ kfree(mymtd); } +#if LINUX_VERSION_CODE >= 0x20211 +module_init(init_doc1000); +module_exit(cleanup_doc1000); +#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/doc2000.c linux/drivers/mtd/doc2000.c --- v2.4.0-test11/linux/drivers/mtd/doc2000.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/mtd/doc2000.c Mon Dec 11 14:57:58 2000 @@ -1,8 +1,11 @@ -/* Linux driver for Disk-On-Chip 2000 */ -/* (c) 1999 Machine Vision Holdings, Inc. */ -/* Author: David Woodhouse */ -/* $Id: doc2000.c,v 1.24 2000/07/13 10:03:31 dwmw2 Exp $ */ +/* + * Linux driver for Disk-On-Chip 2000 and Millennium + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse + * + * $Id: doc2000.c,v 1.39 2000/12/01 17:34:29 dwmw2 Exp $ + */ #include #include @@ -19,286 +22,383 @@ #include #include +#include #include -//#define PRERELEASE +#define DOC_SUPPORT_2000 +#define DOC_SUPPORT_MILLENNIUM -static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); -static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eecbuf); -static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf); -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf); -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); -static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); +#ifdef DOC_SUPPORT_2000 +#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k) +#else +#define DoC_is_2000(doc) (0) +#endif +#ifdef DOC_SUPPORT_MILLENNIUM +#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil) +#else +#define DoC_is_Millennium(doc) (0) +#endif + +/* #define ECC_DEBUG */ + +/* I have no idea why some DoC chips can not use memcpy_from|to_io(). + * This may be due to the different revisions of the ASIC controller built-in or + * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment + * this: + #undef USE_MEMCPY +*/ + +static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *eccbuf); +static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, u_char *eccbuf); +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, u_char *buf); +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf); +static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); static struct mtd_info *doc2klist = NULL; -/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ +/* Perform the required delay cycles by reading from the appropriate register */ +static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles) +{ + volatile char dummy; + int i; + + for (i = 0; i < cycles; i++) { + if (DoC_is_Millennium(doc)) + dummy = ReadDOC(doc->virtadr, NOP); + else + dummy = ReadDOC(doc->virtadr, DOCStatus); + } + +} -static int _DoC_WaitReady (unsigned long docptr) +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ +static int _DoC_WaitReady(struct DiskOnChip *doc) { - //long c=-1; - short c=-1; + unsigned long docptr = doc->virtadr; + unsigned short c = 0xffff; - DEBUG(2,"_DoC_WaitReady called for out-of-line wait\n"); + DEBUG(MTD_DEBUG_LEVEL3, + "_DoC_WaitReady called for out-of-line wait\n"); /* Out-of-line routine to wait for chip response */ while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) ; if (c == 0) - DEBUG(2, "_DoC_WaitReady timed out.\n"); - - return (c==0); + DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); + + return (c == 0); } -static inline int DoC_WaitReady(unsigned long docptr) +static inline int DoC_WaitReady(struct DiskOnChip *doc) { + unsigned long docptr = doc->virtadr; /* This is inline, to optimise the common case, where it's ready instantly */ - volatile char dummy; int ret = 0; - /* Out-of-line routine to wait for chip response */ - /* TPW: Add 4 reads - see Software Requirement 2.3.2 */ - dummy = ReadDOC(docptr, CDSNControl); - dummy = ReadDOC(docptr, CDSNControl); - dummy = ReadDOC(docptr, CDSNControl); - dummy = ReadDOC(docptr, CDSNControl); - + /* 4 read form NOP register should be issued in prior to the read from CDSNControl + see Software Requirement 11.4 item 2. */ + DoC_Delay(doc, 4); + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) - ret = _DoC_WaitReady(docptr); /* Call the out-of-line routine to wait */ - - /* TPW: Add 2 reads - see Software Requirement 2.3.2 */ - dummy = ReadDOC(docptr, CDSNControl); - dummy = ReadDOC(docptr, CDSNControl); + /* Call the out-of-line routine to wait */ + ret = _DoC_WaitReady(doc); + + /* issue 2 read from NOP register after reading from CDSNControl register + see Software Requirement 11.4 item 2. */ + DoC_Delay(doc, 2); return ret; } +/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -/* DoC_Command: Send a flash command to the flash chip */ - -static inline int DoC_Command(unsigned long docptr, unsigned char command, unsigned char xtraflags) +static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, + unsigned char xtraflags) { + unsigned long docptr = doc->virtadr; + + if (DoC_is_2000(doc)) + xtraflags |= CDSN_CTRL_FLASH_IO; + /* Assert the CLE (Command Latch Enable) line to the flash chip */ - WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, - docptr, CDSNControl); + WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + if (DoC_is_Millennium(doc)) + WriteDOC(command, docptr, CDSNSlowIO); /* Send the command */ - WriteDOC(command, docptr, 2k_CDSN_IO); - + WriteDOC_(command, docptr, doc->ioreg); + /* Lower the CLE line */ - WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ - /* Wait for the chip to respond */ - return DoC_WaitReady(docptr); + /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */ + return DoC_WaitReady(doc); } -/* DoC_Address: Set the current address for the flash chip */ +/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static inline int DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs, - unsigned char xtraflags1, unsigned char xtraflags2) +static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, + unsigned char xtraflags1, unsigned char xtraflags2) { - /* Assert the ALE (Address Latch Enable line to the flash chip */ - WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, - docptr, CDSNControl); + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (DoC_is_2000(doc)) + xtraflags1 |= CDSN_CTRL_FLASH_IO; + + /* Assert the ALE (Address Latch Enable) line to the flash chip */ + WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); + + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ /* Send the address */ - /* Three cases: - numbytes == 1: Send single byte, bits 0-7. - numbytes == 2: Send bits 9-16 followed by 17-23 - numbytes == 3: Send 0-7, 9-16, then 17-23 - */ - if (numbytes != 2) - WriteDOC(ofs & 0xff, docptr, 2k_CDSN_IO); - - if (numbytes != 1) { - WriteDOC((ofs >> 9) & 0xff, docptr, 2k_CDSN_IO); - WriteDOC((ofs >> 17) & 0xff, docptr, 2k_CDSN_IO); + /* Devices with 256-byte page are addressed as: + Column (bits 0-7), Page (bits 8-15, 16-23, 24-31) + * there is no device on the market with page256 + and more than 24 bits. + Devices with 512-byte page are addressed as: + Column (bits 0-7), Page (bits 9-16, 17-24, 25-31) + * 25-31 is sent only if the chip support it. + * bit 8 changes the read command to be sent + (NAND_CMD_READ0 or NAND_CMD_READ1). + */ + + if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) { + if (DoC_is_Millennium(doc)) + WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); + WriteDOC_(ofs & 0xff, docptr, doc->ioreg); } - /* Lower the ALE line */ - WriteDOC( CDSN_CTRL_FLASH_IO | xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, CDSNControl); + + if (doc->page256) { + ofs = ofs >> 8; + } else { + ofs = ofs >> 9; + } + + if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) { + for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) { + if (DoC_is_Millennium(doc)) + WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); + WriteDOC_(ofs & 0xff, docptr, doc->ioreg); + } + } + + DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ - /* Wait for the chip to respond */ - return DoC_WaitReady(docptr); + /* FIXME: The SlowIO's for millennium could be replaced by + a single WritePipeTerm here. mf. */ + + /* Lower the ALE line */ + WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, + CDSNControl); + + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for the chip to respond - Software requirement 11.4.1 */ + return DoC_WaitReady(doc); +} + +/* Read a buffer from DoC, taking care of Millennium odditys */ +static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len) +{ + int dummy; + int modulus = 0xffff; + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (len <= 0) + return; + + if (DoC_is_Millennium(doc)) { + /* Read the data via the internal pipeline through CDSN IO register, + see Pipelined Read Operations 11.3 */ + dummy = ReadDOC(docptr, ReadPipeInit); + + /* Millennium should use the LastDataRead register - Pipeline Reads */ + len--; + + /* This is needed for correctly ECC calculation */ + modulus = 0xff; + } + + for (i = 0; i < len; i++) + buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus)); + + if (DoC_is_Millennium(doc)) { + buf[i] = ReadDOC(docptr, LastDataRead); + } } +/* Write a buffer to DoC, taking care of Millennium odditys */ +static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len) +{ + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (len <= 0) + return; + + for (i = 0; i < len; i++) + WriteDOC_(buf[i], docptr, doc->ioreg + i); + + if (DoC_is_Millennium(doc)) { + WriteDOC(0x00, docptr, WritePipeTerm); + } +} + + /* DoC_SelectChip: Select a given flash chip within the current floor */ -static inline int DoC_SelectChip(unsigned long docptr, int chip) +static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip) { + unsigned long docptr = doc->virtadr; + + /* Software requirement 11.4.4 before writing DeviceSelect */ + /* Deassert the CE line to eliminate glitches on the FCE# outputs */ + WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + /* Select the individual flash chip requested */ - WriteDOC( chip, docptr, CDSNDeviceSelect); - + WriteDOC(chip, docptr, CDSNDeviceSelect); + DoC_Delay(doc, 4); + + /* Reassert the CE line */ + WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr, + CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + /* Wait for it to be ready */ - return DoC_WaitReady(docptr); + return DoC_WaitReady(doc); } /* DoC_SelectFloor: Select a given floor (bank of flash chips) */ -static inline int DoC_SelectFloor(unsigned long docptr, int floor) +static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor) { + unsigned long docptr = doc->virtadr; + /* Select the floor (bank) of chips required */ - WriteDOC( floor, docptr, FloorSelect); + WriteDOC(floor, docptr, FloorSelect); /* Wait for the chip to be ready */ - return DoC_WaitReady(docptr); + return DoC_WaitReady(doc); } - + /* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) { - int mfr, id, chipshift=0; - char *mfrname=NULL, *idname=NULL; + int mfr, id, i; + volatile char dummy; /* Page in the required floor/chip */ - DoC_SelectFloor(doc->virtadr, floor); - DoC_SelectChip(doc->virtadr, chip); + DoC_SelectFloor(doc, floor); + DoC_SelectChip(doc, chip); /* Reset the chip */ - if (DoC_Command(doc->virtadr, NAND_CMD_RESET, CDSN_CTRL_WP)) { - DEBUG(2, "DoC_Command (reset) for %d,%d returned true\n", floor,chip); + if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { + DEBUG(MTD_DEBUG_LEVEL2, + "DoC_Command (reset) for %d,%d returned true\n", + floor, chip); return 0; } - - /* Read the NAND chip ID: 1. Send ReadID command */ - if(DoC_Command(doc->virtadr, NAND_CMD_READID, CDSN_CTRL_WP)) { - DEBUG(2,"DoC_Command (ReadID) for %d,%d returned true\n", floor,chip); + + + /* Read the NAND chip ID: 1. Send ReadID command */ + if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { + DEBUG(MTD_DEBUG_LEVEL2, + "DoC_Command (ReadID) for %d,%d returned true\n", + floor, chip); return 0; } - /* Read the NAND chip ID: 2. Send address byte zero - */ - DoC_Address(doc->virtadr, 1, 0, CDSN_CTRL_WP, 0); - + /* Read the NAND chip ID: 2. Send address byte zero */ + DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0); + /* Read the manufacturer and device id codes from the device */ - mfr = ReadDOC(doc->virtadr, 2k_CDSN_IO); - id = ReadDOC(doc->virtadr, 2k_CDSN_IO); - + + /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ + dummy = ReadDOC(doc->virtadr, CDSNSlowIO); + DoC_Delay(doc, 2); + mfr = ReadDOC_(doc->virtadr, doc->ioreg); + + /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ + dummy = ReadDOC(doc->virtadr, CDSNSlowIO); + DoC_Delay(doc, 2); + id = ReadDOC_(doc->virtadr, doc->ioreg); + /* No response - return failure */ if (mfr == 0xff || mfr == 0) return 0; - + /* Check it's the same as the first chip we identified. * M-Systems say that any given DiskOnChip device should only * contain _one_ type of flash part, although that's not a * hardware restriction. */ if (doc->mfr) { if (doc->mfr == mfr && doc->id == id) - return 1; /* This is another the same the first */ + return 1; /* This is another the same the first */ else - printk(KERN_WARNING "Flash chip at floor %d, chip %d is different:\n", + printk(KERN_WARNING + "Flash chip at floor %d, chip %d is different:\n", floor, chip); } - - /* Print (and store if first time) the manufacturer and ID codes. */ - - switch(mfr) { - case NAND_MFR_TOSHIBA: /* Toshiba */ - mfrname = "Toshiba"; - - switch(id) { - case 0x64: - idname = "TC5816BDC"; - chipshift = 21; - break; - - case 0x6b: - idname = "TC5832DC"; - chipshift = 22; - break; - - case 0x73: - idname = "TH58V128DC"; - chipshift = 24; - break; - - case 0x75: - idname = "TC58256FT/DC"; - chipshift = 25; - break; - - case 0xe5: - idname = "TC58V32DC"; - chipshift = 22; - break; - - case 0xe6: - idname = "TC58V64DC"; - chipshift = 23; - break; - - case 0xea: - idname = "TC58V16BDC"; - chipshift = 21; - break; - } - break; /* End of Toshiba parts */ - - case NAND_MFR_SAMSUNG: /* Samsung */ - mfrname = "Samsung"; - - switch(id) { - case 0x64: - idname = "KM29N16000"; - chipshift = 21; - - case 0x73: - idname = "KM29U128T"; - chipshift = 24; - break; - - case 0x75: - idname = "KM29U256T"; - chipshift = 25; - break; - - case 0xe3: - idname = "KM29W32000"; - chipshift = 22; - break; - - case 0xe6: - idname = "KM29U64000"; - chipshift = 23; - break; - - case 0xea: - idname = "KM29W16000"; - chipshift = 21; - break; - } - break; /* End of Samsung parts */ - } - - /* If we've identified it fully, print the full names */ - if (idname) { -#ifdef PRERELEASE - DEBUG(1, "Flash chip found: %2.2X %2.2X (%s %s)\n", - mfr,id,mfrname,idname); -#endif - /* If this is the first chip, store the id codes */ - if (!doc->mfr) { - doc->mfr = mfr; - doc->id = id; - doc->chipshift = chipshift; - return 1; + + /* Print and store the manufacturer and ID codes. */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (mfr == nand_flash_ids[i].manufacture_id && + id == nand_flash_ids[i].model_id) { + printk(KERN_INFO + "Flash chip found: Manufacturer ID: %2.2X, " + "Chip ID: %2.2X (%s)\n", mfr, id, + nand_flash_ids[i].name); + if (!doc->mfr) { + doc->mfr = mfr; + doc->id = id; + doc->chipshift = + nand_flash_ids[i].chipshift; + doc->page256 = nand_flash_ids[i].page256; + doc->pageadrlen = + nand_flash_ids[i].pageadrlen; + doc->erasesize = + nand_flash_ids[i].erasesize; + return 1; + } + return 0; } - return 0; } + /* We haven't fully identified the chip. Print as much as we know. */ - if (mfrname) - printk(KERN_WARNING "Unknown %s flash chip found: %2.2X %2.2X\n", mfrname, - id, mfr); - else - printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", id, mfr); - - printk(KERN_WARNING "Please report to David.Woodhouse@mvhi.com\n"); + printk(KERN_WARNING "Unknown flash chip found: %2.2X %2.2X\n", + id, mfr); + + printk(KERN_WARNING "Please report to dwmw2@infradead.org\n"); return 0; -} +} /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ @@ -306,18 +406,22 @@ { int floor, chip; int numchips[MAX_FLOORS]; + int maxchips = MAX_CHIPS; int ret = 1; - + this->numchips = 0; this->mfr = 0; this->id = 0; - + + if (DoC_is_Millennium(this)) + maxchips = MAX_CHIPS_MIL; + /* For each floor, find the number of valid chips it contains */ - for (floor = 0 ; floor < MAX_FLOORS ; floor++) { + for (floor = 0; floor < MAX_FLOORS; floor++) { ret = 1; - numchips[floor]=0; - for (chip = 0 ; chip < MAX_CHIPS && ret != 0; chip++ ) { - + numchips[floor] = 0; + for (chip = 0; chip < maxchips && ret != 0; chip++) { + ret = DoC_IdentChip(this, floor, chip); if (ret) { numchips[floor]++; @@ -325,26 +429,26 @@ } } } - + /* If there are none at all that we recognise, bail */ if (!this->numchips) { printk("No flash chips recognised.\n"); return; } - + /* Allocate an array to hold the information for each chip */ this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); - if (!this->chips){ + if (!this->chips) { printk("No memory for allocating chip info structures\n"); return; } - + ret = 0; - + /* Fill out the chip array with {floor, chipno} for each * detected chip in the device. */ for (floor = 0; floor < MAX_FLOORS; floor++) { - for (chip = 0 ; chip < numchips[floor] ; chip++) { + for (chip = 0; chip < numchips[floor]; chip++) { this->chips[ret].floor = floor; this->chips[ret].chip = chip; this->chips[ret].curadr = 0; @@ -356,8 +460,9 @@ /* Calculate and print the total size of the device */ this->totlen = this->numchips * (1 << this->chipshift); - printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mb\n", this->numchips , - this->totlen >> 20); + printk(KERN_INFO + "%d flash chips found. Total DiskOnChip size: %ld Mb\n", + this->numchips, this->totlen >> 20); } @@ -371,15 +476,15 @@ * purpose. If it's value is the same on both chips, they might * be the same chip, and we write to one and check for a change in * the other. It's unclear if this register is usuable in the - * DoC 2000 (it's in the Millenium docs), but it seems to work. */ + * DoC 2000 (it's in the Millennium docs), but it seems to work. */ tmp1 = ReadDOC(doc1->virtadr, AliasResolution); tmp2 = ReadDOC(doc2->virtadr, AliasResolution); if (tmp1 != tmp2) return 0; - - WriteDOC((tmp1+1) % 0xff, doc1->virtadr, AliasResolution); + + WriteDOC((tmp1 + 1) % 0xff, doc1->virtadr, AliasResolution); tmp2 = ReadDOC(doc2->virtadr, AliasResolution); - if (tmp2 == (tmp1+1) % 0xff) + if (tmp2 == (tmp1 + 1) % 0xff) retval = 1; else retval = 0; @@ -387,11 +492,10 @@ /* Restore register contents. May not be necessary, but do it just to * be safe. */ WriteDOC(tmp1, doc1->virtadr, AliasResolution); - + return retval; } - static const char im_name[] = "DoC2k_init"; /* This routine is made available to other mtd code via @@ -403,36 +507,48 @@ */ static void DoC2k_init(struct mtd_info *mtd) { - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; struct DiskOnChip *old = NULL; /* We must avoid being called twice for the same device. */ if (doc2klist) - old = (struct DiskOnChip *)doc2klist->priv; + old = (struct DiskOnChip *) doc2klist->priv; while (old) { if (DoC2k_is_alias(old, this)) { - printk(KERN_NOTICE "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n", + printk(KERN_NOTICE + "Ignoring DiskOnChip 2000 at 0x%lX - already configured\n", this->physadr); - iounmap((void *)this->virtadr); + iounmap((void *) this->virtadr); kfree(mtd); return; } if (old->nextdoc) - old = (struct DiskOnChip *)old->nextdoc->priv; + old = (struct DiskOnChip *) old->nextdoc->priv; else old = NULL; } - - - mtd->name = "DiskOnChip 2000"; - printk(KERN_NOTICE "DiskOnChip 2000 found at address 0x%lX\n",this->physadr); + + + switch (this->ChipID) { + case DOC_ChipID_Doc2k: + mtd->name = "DiskOnChip 2000"; + this->ioreg = DoC_2k_CDSN_IO; + break; + case DOC_ChipID_DocMil: + mtd->name = "DiskOnChip Millennium"; + this->ioreg = DoC_Mil_CDSN_IO; + break; + } + + printk(KERN_NOTICE "%s found at address 0x%lX\n", mtd->name, + this->physadr); mtd->type = MTD_NANDFLASH; mtd->flags = MTD_CAP_NANDFLASH; mtd->size = 0; - mtd->erasesize = 0x2000; + mtd->erasesize = 0; mtd->oobblock = 512; mtd->oobsize = 16; mtd->module = THIS_MODULE; @@ -446,131 +562,182 @@ mtd->read_oob = doc_read_oob; mtd->write_oob = doc_write_oob; mtd->sync = NULL; - + this->totlen = 0; this->numchips = 0; - + this->curfloor = -1; this->curchip = -1; - + /* Ident all the chips present. */ DoC_ScanChips(this); - + if (!this->totlen) { kfree(mtd); - iounmap((void *)this->virtadr); + iounmap((void *) this->virtadr); } else { this->nextdoc = doc2klist; doc2klist = mtd; - mtd->size = this->totlen; + mtd->size = this->totlen; + mtd->erasesize = this->erasesize; add_mtd_device(mtd); return; } } - -static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) +static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf) { /* Just a special case of doc_read_ecc */ return doc_read_ecc(mtd, from, len, retlen, buf, NULL); } -static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf) +static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t * retlen, u_char * buf, u_char * eccbuf) { - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - int di=0; /* Yes, DI is a hangover from when I was disassembling the binary driver */ + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; unsigned long docptr; struct Nand *mychip; + unsigned char syndrome[6]; + volatile char dummy; + int i, len256 = 0, ret=0; docptr = this->virtadr; /* Don't allow read past end of device */ if (from >= this->totlen) return -EINVAL; - + /* Don't allow a single read to cross a 512-byte block boundary */ - if (from + len > ( (from | 0x1ff) + 1)) + if (from + len > ((from | 0x1ff) + 1)) len = ((from | 0x1ff) + 1) - from; + /* The ECC will not be calculated correctly if less than 512 is read */ + if (len != 0x200 && eccbuf) + printk(KERN_WARNING + "ECC needs a full sector read (adr: %lx size %lx)\n", + (long) from, (long) len); + + /* printk("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); */ + + /* Find the chip which is to be used and select it */ mychip = &this->chips[from >> (this->chipshift)]; - + if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); } - + this->curfloor = mychip->floor; this->curchip = mychip->chip; - + + DoC_Command(this, + (!this->page256 + && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, + CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, + CDSN_CTRL_ECC_IO); if (eccbuf) { /* Prime the ECC engine */ - WriteDOC ( DOC_ECC_RESET, docptr, ECCConf); - WriteDOC ( DOC_ECC_EN, docptr, ECCConf); + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); } - DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); - DoC_Address(docptr, 3, from, CDSN_CTRL_WP , CDSN_CTRL_ECC_IO); + /* treat crossing 256-byte sector for 2M x 8bits devices */ + if (this->page256 && from + len > (from | 0xff) + 1) { + len256 = (from | 0xff) + 1 - from; + DoC_ReadBuf(this, buf, len256); - for (di=0; di < len ; di++) { - buf[di] = ReadDOC(docptr, 2k_CDSN_IO); + DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, from + len256, + CDSN_CTRL_WP, CDSN_CTRL_ECC_IO); } + DoC_ReadBuf(this, &buf[len256], len - len256); + /* Let the caller know we completed it */ *retlen = len; if (eccbuf) { /* Read the ECC data through the DiskOnChip ECC logic */ - for (di=0; di<6; di++) { - eccbuf[di] = ReadDOC(docptr, 2k_CDSN_IO); - } - + /* Note: this will work even with 2M x 8bit devices as */ + /* they have 8 bytes of OOB per 256 page. mf. */ + DoC_ReadBuf(this, eccbuf, 6); + /* Flush the pipeline */ - (void) ReadDOC(docptr, 2k_ECCStatus); - (void) ReadDOC(docptr, 2k_ECCStatus); - + if (DoC_is_Millennium(this)) { + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + i = ReadDOC(docptr, ECCConf); + } else { + dummy = ReadDOC(docptr, 2k_ECCStatus); + dummy = ReadDOC(docptr, 2k_ECCStatus); + i = ReadDOC(docptr, 2k_ECCStatus); + } + /* Check the ECC Status */ - if (ReadDOC(docptr, 2k_ECCStatus) & 0x80) { + if (i & 0x80) { + int nb_errors; /* There was an ECC error */ +#ifdef ECC_DEBUG printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); +#endif + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = + ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); - /* FIXME: Implement ECC error correction, don't just whinge */ - - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ - return -EIO; +#ifdef ECC_DEBUG + printk("Errors corrected: %x\n", nb_errors); +#endif + if (nb_errors < 0) { + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + ret = -EIO; + } } + #ifdef PSYCHO_DEBUG - else - printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4], - eccbuf[5]); + printk("ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], + eccbuf[3], eccbuf[4], eccbuf[5]); #endif - /* Reset the ECC engine */ - WriteDOC(DOC_ECC_RESV, docptr , ECCConf); - + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); } - return 0; + return ret; } -static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf) { - static char as[6]; - return doc_write_ecc(mtd, to, len, retlen, buf, as); + char eccbuf[6]; + return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf); } -static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf, u_char *eccbuf) +static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t * retlen, const u_char * buf, + u_char * eccbuf) { - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - int di=0; + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ unsigned long docptr; + volatile char dummy; + int len256 = 0; struct Nand *mychip; docptr = this->virtadr; @@ -578,82 +745,118 @@ /* Don't allow write past end of device */ if (to >= this->totlen) return -EINVAL; -#if 0 + /* Don't allow a single write to cross a 512-byte block boundary */ - if (to + len > ( (to | 0x1ff) + 1)) + if (to + len > ((to | 0x1ff) + 1)) len = ((to | 0x1ff) + 1) - to; -#else - /* Don't allow writes which aren't exactly one block */ - if (to & 0x1ff || len != 0x200) - return -EINVAL; -#endif + /* The ECC will not be calculated correctly if less than 512 is written */ + if (len != 0x200 && eccbuf) + printk(KERN_WARNING + "ECC needs a full sector write (adr: %lx size %lx)\n", + (long) to, (long) len); + + /* printk("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */ /* Find the chip which is to be used and select it */ mychip = &this->chips[to >> (this->chipshift)]; - + if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); } - + this->curfloor = mychip->floor; this->curchip = mychip->chip; - + /* Set device to main plane of flash */ - DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); - DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP); + DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(this, + (!this->page256 + && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, + CDSN_CTRL_WP); + + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); if (eccbuf) { /* Prime the ECC engine */ - WriteDOC ( DOC_ECC_RESET, docptr, ECCConf); - WriteDOC ( DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); } - DoC_Command(docptr, NAND_CMD_SEQIN, 0); - DoC_Address(docptr, 3, to, 0, CDSN_CTRL_ECC_IO); + /* treat crossing 256-byte sector for 2M x 8bits devices */ + if (this->page256 && to + len > (to | 0xff) + 1) { + len256 = (to | 0xff) + 1 - to; + DoC_WriteBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); - for (di=0; di < len ; di++) { - WriteDOC(buf[di], docptr, 2k_CDSN_IO); + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return -EIO; + } + + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0, + CDSN_CTRL_ECC_IO); } + DoC_WriteBuf(this, &buf[len256], len - len256); if (eccbuf) { - WriteDOC( CDSN_CTRL_ECC_IO | CDSN_CTRL_CE , docptr, CDSNControl ); - -#if 1 - /* eduardp@m-sys.com says this shouldn't be necessary, - * but it doesn't actually work without it, so I've - * left it in for now. dwmw2. - */ - - WriteDOC( 0, docptr, 2k_CDSN_IO); - WriteDOC( 0, docptr, 2k_CDSN_IO); - WriteDOC( 0, docptr, 2k_CDSN_IO); -#endif + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, + CDSNControl); + + if (DoC_is_Millennium(this)) { + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + } else { + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + } + /* Read the ECC data through the DiskOnChip ECC logic */ - for (di=0; di<6; di++) { + for (di = 0; di < 6; di++) { eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); } + + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + #ifdef PSYCHO_DEBUG - printk("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long) to, eccbuf[0], eccbuf[1], eccbuf[2], - eccbuf[3], eccbuf[4], eccbuf[5] ); + printk + ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - /* Reset the ECC engine */ - WriteDOC(DOC_ECC_RESV, docptr , ECCConf); - } - DoC_Command(docptr, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_PAGEPROG, 0); - DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); /* There's an implicit DoC_WaitReady() in DoC_Command */ - if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { printk("Error programming flash\n"); /* Error in programming */ *retlen = 0; @@ -662,84 +865,155 @@ /* Let the caller know we completed it */ *retlen = len; + + if (eccbuf) { + unsigned char x[8]; + size_t dummy; + + /* Write the ECC data to flash */ + for (di=0; di<6; di++) + x[di] = eccbuf[di]; + + x[6]=0x55; + x[7]=0x55; + + return doc_write_oob(mtd, to, 8, &dummy, x); + } return 0; } - - -static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf) +static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t * retlen, u_char * buf) { - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - int i; + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + int len256 = 0; unsigned long docptr; struct Nand *mychip; - + docptr = this->virtadr; - + mychip = &this->chips[ofs >> this->chipshift]; - + if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; - - - - DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); - DoC_Address(docptr, 3, ofs, CDSN_CTRL_WP, 0); - - for (i=0; ipage256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (this->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + DoC_ReadBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), + CDSN_CTRL_WP, 0); + } + + DoC_ReadBuf(this, &buf[len256], len - len256); + *retlen = len; return 0; } -static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) +static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, + size_t * retlen, const u_char * buf) { - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; - int i; - unsigned long docptr; - struct Nand *mychip; + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; + int len256 = 0; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[ofs >> this->chipshift]; + int dummy; - // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, + // printk("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n",(long)ofs, len, // buf[0], buf[1], buf[2], buf[3], buf[8], buf[9], buf[14],buf[15]); - docptr = this->virtadr; - - mychip = &this->chips[ofs >> this->chipshift]; - + /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; - - DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); - DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); - DoC_Command(docptr, NAND_CMD_SEQIN, 0); - DoC_Address(docptr, 3, ofs, 0, 0); - - for (i=0; ipage256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + /* issue the Serial Data In command to initial the Page Program process */ + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (this->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + DoC_WriteBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_STATUS, 0); + /* DoC_WaitReady() is implicit in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printk("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return -EIO; + } + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0); + } - DoC_Command(docptr, NAND_CMD_PAGEPROG, 0); - DoC_Command(docptr, NAND_CMD_STATUS, 0); + DoC_WriteBuf(this, &buf[len256], len - len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_STATUS, 0); /* DoC_WaitReady() is implicit in DoC_Command */ - if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { printk("Error programming oob data\n"); /* There was an error */ *retlen = 0; @@ -751,102 +1025,89 @@ } - -int doc_erase (struct mtd_info *mtd, struct erase_info *instr) +int doc_erase(struct mtd_info *mtd, struct erase_info *instr) { - struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; + struct DiskOnChip *this = (struct DiskOnChip *) mtd->priv; unsigned long ofs = instr->addr; unsigned long len = instr->len; unsigned long docptr; struct Nand *mychip; - - if(len != mtd->erasesize) - printk(KERN_WARNING "Erase not right size (%lx != %lx)n", len, mtd->erasesize); - + + if (len != mtd->erasesize) + printk(KERN_WARNING "Erase not right size (%lx != %lx)n", + len, mtd->erasesize); docptr = this->virtadr; - + mychip = &this->chips[ofs >> this->chipshift]; - + if (this->curfloor != mychip->floor) { - DoC_SelectFloor(docptr, mychip->floor); - DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { - DoC_SelectChip(docptr, mychip->chip); + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; - + instr->state = MTD_ERASE_PENDING; - DoC_Command(docptr, NAND_CMD_ERASE1, 0); - DoC_Address(docptr, 2, ofs, 0, 0); - DoC_Command(docptr, NAND_CMD_ERASE2, 0); + DoC_Command(this, NAND_CMD_ERASE1, 0); + DoC_Address(this, ADDR_PAGE, ofs, 0, 0); + DoC_Command(this, NAND_CMD_ERASE2, 0); instr->state = MTD_ERASING; - DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); - if (ReadDOC(docptr, 2k_CDSN_IO) & 1) { + if (ReadDOC_(docptr, this->ioreg) & 1) { printk("Error writing\n"); /* There was an error */ instr->state = MTD_ERASE_FAILED; - } - else + } else instr->state = MTD_ERASE_DONE; - if (instr->callback) + if (instr->callback) instr->callback(instr); - + return 0; } - - - /**************************************************************************** * * Module stuff * ****************************************************************************/ -static int __init init_doc2000(void) -{ - inter_module_register(im_name, THIS_MODULE, &DoC2k_init); - return 0; -} - -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define cleanup_doc2000 cleanup_module -#endif -#define __exit +#define init_doc2000 init_module #endif +int __init init_doc2000(void) +{ + inter_module_register(im_name, THIS_MODULE, &DoC2k_init); + return 0; +} static void __exit cleanup_doc2000(void) { struct mtd_info *mtd; struct DiskOnChip *this; - while((mtd=doc2klist)) { - this = (struct DiskOnChip *)mtd->priv; + while ((mtd = doc2klist)) { + this = (struct DiskOnChip *) mtd->priv; doc2klist = this->nextdoc; - + del_mtd_device(mtd); - - iounmap((void *)this->virtadr); + + iounmap((void *) this->virtadr); kfree(this->chips); kfree(mtd); } inter_module_unregister(im_name); - } -module_init(init_doc2000); - -#if LINUX_VERSION_CODE > 0x20300 module_exit(cleanup_doc2000); -#endif +module_init(init_doc2000); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/doc2001.c linux/drivers/mtd/doc2001.c --- v2.4.0-test11/linux/drivers/mtd/doc2001.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/mtd/doc2001.c Mon Dec 11 14:57:58 2000 @@ -1,7 +1,11 @@ -/* Linux driver for Disk-On-Chip Millennium */ -/* (c) 1999 Machine Vision Holdings, Inc. */ -/* Author: David Woodhouse */ -/* $Id: doc2001.c,v 1.7 2000/07/13 10:41:39 dwmw2 Exp $ */ + +/* + * Linux driver for Disk-On-Chip Millennium + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse + * + * $Id: doc2001.c,v 1.24 2000/12/01 13:11:02 dwmw2 Exp $ + */ #include #include @@ -18,38 +22,26 @@ #include #include +#include #include -static struct { - char * name; - int manufacture_id; - int model_id; - int chipshift; -} nand_flash_ids[] = { - {"Toshiba TC5816BDC", NAND_MFR_TOSHIBA, 0x64, 21}, - {"Toshiba TC5832DC", NAND_MFR_TOSHIBA, 0x6b, 22}, - {"Toshiba TH58V128DC", NAND_MFR_TOSHIBA, 0x73, 24}, - {"Toshiba TC58256FT/DC", NAND_MFR_TOSHIBA, 0x75, 25}, - {"Toshiba TC58V32DC", NAND_MFR_TOSHIBA, 0xe5, 22}, - {"Toshiba TC58V64DC", NAND_MFR_TOSHIBA, 0xe6, 23}, - {"Toshiba TC58V16BDC", NAND_MFR_TOSHIBA, 0xea, 21}, - {"Samsung KM29N16000", NAND_MFR_SAMSUNG, 0x64, 21}, - {"Samsung KM29U128T", NAND_MFR_SAMSUNG, 0x73, 24}, - {"Samsung KM29U256T", NAND_MFR_SAMSUNG, 0x75, 25}, - {"Samsung KM29W32000", NAND_MFR_SAMSUNG, 0xe3, 22}, - {"Samsung KM29U64000", NAND_MFR_SAMSUNG, 0xe6, 23}, - {"Samsung KM29W16000", NAND_MFR_SAMSUNG, 0xea, 21}, - {NULL,} -}; +/* #define ECC_DEBUG */ -static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf); -static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf); -static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf, u_char *eecbuf); -static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf, u_char *eccbuf); +/* I have no idea why some DoC chips can not use memcop_form|to_io(). + * This may be due to the different revisions of the ASIC controller built-in or + * simplily a QA/Bug issue. Who knows ?? If you have trouble, please uncomment + * this: + #undef USE_MEMCPY +*/ + +static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf); +static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); +static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, u_char *eccbuf); +static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, u_char *eccbuf); static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf); static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, @@ -58,6 +50,7 @@ static struct mtd_info *docmillist = NULL; +/* Perform the required delay cycles by reading from the NOP register */ static void DoC_Delay(unsigned long docptr, unsigned short cycles) { volatile char dummy; @@ -72,14 +65,20 @@ { unsigned short c = 0xffff; + DEBUG(MTD_DEBUG_LEVEL3, + "_DoC_WaitReady called for out-of-line wait\n"); + /* Out-of-line routine to wait for chip response */ while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B) && --c) ; + if (c == 0) + DEBUG(MTD_DEBUG_LEVEL2, "_DoC_WaitReady timed out.\n"); + return (c == 0); } -static __inline__ int DoC_WaitReady(unsigned long docptr) +static inline int DoC_WaitReady(unsigned long docptr) { /* This is inline, to optimise the common case, where it's ready instantly */ int ret = 0; @@ -99,33 +98,35 @@ return ret; } -/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to bypass - the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after - writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static __inline__ void DoC_Command(unsigned long docptr, unsigned char command, - unsigned char xtraflags) +/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static inline void DoC_Command(unsigned long docptr, unsigned char command, + unsigned char xtraflags) { /* Assert the CLE (Command Latch Enable) line to the flash chip */ - WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); + WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); DoC_Delay(docptr, 4); /* Send the command */ WriteDOC(command, docptr, CDSNSlowIO); WriteDOC(command, docptr, Mil_CDSN_IO); - + /* Lower the CLE line */ WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); DoC_Delay(docptr, 4); } -/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to bypass - the internal pipeline. Each of 4 delay cycles (read from the NOP register) is required after - writing to CDSN Control register, see Software Requirement 11.4 item 3. */ -static __inline__ void DoC_Address (unsigned long docptr, int numbytes, unsigned long ofs, +/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static inline void DoC_Address(unsigned long docptr, int numbytes, unsigned long ofs, unsigned char xtraflags1, unsigned char xtraflags2) { - /* Assert the ALE (Address Latch Enable line to the flash chip */ - WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); + /* Assert the ALE (Address Latch Enable) line to the flash chip */ + WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); DoC_Delay(docptr, 4); /* Send the address */ @@ -217,11 +218,11 @@ if (mfr == 0xff || mfr == 0) return 0; - /* FIXME: to deal with mulit-flash on multi-Millennium case more carefully */ + /* FIXME: to deal with multi-flash on multi-Millennium case more carefully */ for (i = 0; nand_flash_ids[i].name != NULL; i++) { if (mfr == nand_flash_ids[i].manufacture_id && id == nand_flash_ids[i].model_id) { - printk(KERN_INFO "Flash chip found: Manufacture ID: %2.2X, " + printk(KERN_INFO "Flash chip found: Manufacturer ID: %2.2X, " "Chip ID: %2.2X (%s)\n", mfr, id, nand_flash_ids[i].name); doc->mfr = mfr; @@ -235,7 +236,7 @@ return 0; else return 1; -} +} /* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ static void DoC_ScanChips(struct DiskOnChip *this) @@ -243,11 +244,11 @@ int floor, chip; int numchips[MAX_FLOORS_MIL]; int ret; - + this->numchips = 0; this->mfr = 0; this->id = 0; - + /* For each floor, find the number of valid chips it contains */ for (floor = 0,ret = 1; floor < MAX_FLOORS_MIL; floor++) { numchips[floor] = 0; @@ -264,14 +265,14 @@ printk("No flash chips recognised.\n"); return; } - + /* Allocate an array to hold the information for each chip */ this->chips = kmalloc(sizeof(struct Nand) * this->numchips, GFP_KERNEL); if (!this->chips){ printk("No memory for allocating chip info structures\n"); return; } - + /* Fill out the chip array with {floor, chipno} for each * detected chip in the device. */ for (floor = 0, ret = 0; floor < MAX_FLOORS_MIL; floor++) { @@ -286,7 +287,7 @@ /* Calculate and print the total size of the device */ this->totlen = this->numchips * (1 << this->chipshift); - printk(KERN_INFO "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n", + printk(KERN_NOTICE "%d flash chips found. Total DiskOnChip size: %ld Mbytes\n", this->numchips ,this->totlen >> 20); } @@ -317,7 +318,7 @@ /* Restore register contents. May not be necessary, but do it just to * be safe. */ WriteDOC(tmp1, doc1->virtadr, AliasResolution); - + return retval; } @@ -330,7 +331,7 @@ * this module is non-zero, i.e. between inter_module_get and * inter_module_put. Keith Owens 29 Oct 2000. */ -void DoCMil_init(struct mtd_info *mtd) +static void DoCMil_init(struct mtd_info *mtd) { struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; struct DiskOnChip *old = NULL; @@ -355,12 +356,15 @@ mtd->name = "DiskOnChip Millennium"; printk(KERN_NOTICE "DiskOnChip Millennium found at address 0x%lX\n", - this->physadr); + this->physadr); mtd->type = MTD_NANDFLASH; mtd->flags = MTD_CAP_NANDFLASH; mtd->size = 0; + + /* FIXME: erase size is not always 8kB */ mtd->erasesize = 0x2000; + mtd->oobblock = 512; mtd->oobsize = 16; mtd->module = THIS_MODULE; @@ -374,15 +378,15 @@ mtd->read_oob = doc_read_oob; mtd->write_oob = doc_write_oob; mtd->sync = NULL; - + this->totlen = 0; - this->numchips = 0; + this->numchips = 0; this->curfloor = -1; this->curchip = -1; - + /* Ident all the chips present. */ DoC_ScanChips(this); - + if (!this->totlen) { kfree(mtd); iounmap((void *)this->virtadr); @@ -405,8 +409,9 @@ static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, u_char *eccbuf) { - int i; + int i, ret; volatile char dummy; + unsigned char syndrome[6]; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; unsigned long docptr = this->virtadr; struct Nand *mychip = &this->chips[from >> (this->chipshift)]; @@ -429,45 +434,55 @@ this->curfloor = mychip->floor; this->curchip = mychip->chip; + /* issue the Read0 or Read1 command depend on which half of the page + we are accessing. Polling the Flash Ready bit after issue 3 bytes + address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/ + DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); + DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); + DoC_WaitReady(docptr); + if (eccbuf) { /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_EN, docptr, ECCConf); } else { - /* disable the ECC engine, FIXME: is this correct ?? */ + /* disable the ECC engine */ WriteDOC (DOC_ECC_RESET, docptr, ECCConf); - WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); } - /* issue the Read0 or Read1 command depend on which half of the page - we are accessing. Polling the Flash Ready bit after issue 3 bytes - address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/ - DoC_Command(docptr, (from >> 8) & 1, CDSN_CTRL_WP); - DoC_Address(docptr, 3, from, CDSN_CTRL_WP, 0x00); - DoC_WaitReady(docptr); - /* Read the data via the internal pipeline through CDSN IO register, see Pipelined Read Operations 11.3 */ dummy = ReadDOC(docptr, ReadPipeInit); +#ifndef USE_MEMCPY for (i = 0; i < len-1; i++) { - buf[i] = ReadDOC(docptr, Mil_CDSN_IO); + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + buf[i] = ReadDOC(docptr, Mil_CDSN_IO + (i & 0xff)); } - buf[i] = ReadDOC(docptr, LastDataRead); +#else + memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1); +#endif + buf[len - 1] = ReadDOC(docptr, LastDataRead); /* Let the caller know we completed it */ *retlen = len; + ret = 0; if (eccbuf) { - /* FIXME: are we reading the ECC from the ECC logic of DOC or - the spare data space on the flash chip i.e. How do we - control the Spare Area Enable bit of the flash ?? */ - /* Read the ECC data through the DiskOnChip ECC logic + /* Read the ECC data from Spare Data Area, see Reed-Solomon EDC/ECC 11.1 */ dummy = ReadDOC(docptr, ReadPipeInit); +#ifndef USE_MEMCPY for (i = 0; i < 5; i++) { - eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO); + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + eccbuf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); } - eccbuf[i] = ReadDOC(docptr, LastDataRead); +#else + memcpy_fromio(eccbuf, docptr + DoC_Mil_CDSN_IO, 5); +#endif + eccbuf[5] = ReadDOC(docptr, LastDataRead); /* Flush the pipeline */ dummy = ReadDOC(docptr, ECCConf); @@ -475,34 +490,45 @@ /* Check the ECC Status */ if (ReadDOC(docptr, ECCConf) & 0x80) { + int nb_errors; /* There was an ECC error */ +#ifdef ECC_DEBUG printk("DiskOnChip ECC Error: Read at %lx\n", (long)from); - - /* FIXME: Implement ECC error correction, don't just whinge */ - - /* We return error, but have actually done the read. Not that - this can be told to user-space, via sys_read(), but at least - MTD-aware stuff can know about it by checking *retlen */ - return -EIO; +#endif + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); +#ifdef ECC_DEBUG + printk("Errors corrected: %x\n", nb_errors); +#endif + if (nb_errors < 0) { + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + ret = -EIO; + } } + #ifdef PSYCHO_DEBUG - else - printk("ECC OK at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], - eccbuf[4], eccbuf[5]); + printk("ECC DATA at %lx: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); #endif - /* Reset the ECC engine */ - WriteDOC(DOC_ECC_RESV, docptr , ECCConf); + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); } - return 0; + return ret; } static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { - static char as[6]; - return doc_write_ecc(mtd, to, len, retlen, buf, as); + char eccbuf[6]; + return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf); } static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, @@ -532,42 +558,48 @@ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { + } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; /* Reset the chip, see Software Requirement 11.4 item 1. */ - DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(docptr, NAND_CMD_RESET, 0x00); DoC_WaitReady(docptr); /* Set device to main plane of flash */ - DoC_Command(docptr, NAND_CMD_READ0, CDSN_CTRL_WP); + DoC_Command(docptr, NAND_CMD_READ0, 0x00); + + /* issue the Serial Data In command to initial the Page Program process */ + DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); + DoC_Address(docptr, 3, to, 0x00, 0x00); + DoC_WaitReady(docptr); if (eccbuf) { /* init the ECC engine, see Reed-Solomon EDC/ECC 11.1 .*/ WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); } else { - /* disable the ECC engine, FIXME: is this correct ?? */ + /* disable the ECC engine */ WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_DIS, docptr, ECCConf); } - /* issue the Serial Data In command to initial the Page Program process */ - DoC_Command(docptr, NAND_CMD_SEQIN, 0x00); - DoC_Address(docptr, 3, to, 0x00, 0x00); - /* Write the data via the internal pipeline through CDSN IO register, see Pipelined Write Operations 11.2 */ +#ifndef USE_MEMCPY for (i = 0; i < len; i++) { - WriteDOC(buf[i], docptr, Mil_CDSN_IO); + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); } +#else + memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); +#endif WriteDOC(0x00, docptr, WritePipeTerm); if (eccbuf) { - /* Write ECC data to flash, the ECC info is generated by the DiskOnChip DECC logic + /* Write ECC data to flash, the ECC info is generated by the DiskOnChip ECC logic see Reed-Solomon EDC/ECC 11.1 */ WriteDOC(0, docptr, NOP); WriteDOC(0, docptr, NOP); @@ -578,10 +610,26 @@ eccbuf[i] = ReadDOC(docptr, ECCSyndrome0 + i); } + /* ignore the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); + +#ifndef USE_MEMCPY /* Write the ECC data to flash */ for (i = 0; i < 6; i++) { - WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO); + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(eccbuf[i], docptr, Mil_CDSN_IO + i); } +#else + memcpy_toio(docptr + DoC_Mil_CDSN_IO, eccbuf, 6); +#endif + + /* write the block status BLOCK_USED (0x5555) at the end of ECC data + FIXME: this is only a hack for programming the IPL area for LinuxBIOS + and should be replace with proper codes in user space utilities */ + WriteDOC(0x55, docptr, Mil_CDSN_IO); + WriteDOC(0x55, docptr, Mil_CDSN_IO + 1); + WriteDOC(0x00, docptr, WritePipeTerm); #ifdef PSYCHO_DEBUG @@ -589,9 +637,6 @@ (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], eccbuf[4], eccbuf[5]); #endif - - /* Reset the ECC engine */ - WriteDOC(DOC_ECC_RESV, docptr , ECCConf); } /* Commit the Page Program command and wait for ready @@ -601,12 +646,13 @@ /* Read the status of the flash device through CDSN Slow IO register see Software Requirement 11.4 item 5.*/ - DoC_Command(docptr, NAND_CMD_STATUS, 0x00); + DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); dummy = ReadDOC(docptr, CDSNSlowIO); DoC_Delay(docptr, 2); if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { printk("Error programming flash\n"); - /* Error in programming */ + /* Error in programming + FIXME: implement Bad Block Replacement (in nftl.c ??) */ *retlen = 0; return -EIO; } @@ -620,31 +666,29 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, u_char *buf) { - volatile char dummy; +#ifndef USE_MEMCPY int i; +#endif + volatile char dummy; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; unsigned long docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; - /* FIXME: should we restrict the access between 512 to 527 ?? */ - /* Find the chip which is to be used and select it */ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { + } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; - /* FIXME: should we disable ECC engine in this way ?? */ - /* disable the ECC engine, FIXME: is this correct ?? */ + /* disable the ECC engine */ WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_DIS, docptr, ECCConf); - /* issue the Read2 command to read the Spare Data Area. + /* issue the Read2 command to set the pointer to the Spare Data Area. Polling the Flash Ready bit after issue 3 bytes address in Sequence Read Mode, see Software Requirement 11.4 item 1.*/ DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); @@ -654,10 +698,17 @@ /* Read the data out via the internal pipeline through CDSN IO register, see Pipelined Read Operations 11.3 */ dummy = ReadDOC(docptr, ReadPipeInit); +#ifndef USE_MEMCPY for (i = 0; i < len-1; i++) { - buf[i] = ReadDOC(docptr, Mil_CDSN_IO); + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + buf[i] = ReadDOC(docptr, Mil_CDSN_IO + i); } buf[i] = ReadDOC(docptr, LastDataRead); +#else + memcpy_fromio(buf, docptr + DoC_Mil_CDSN_IO, len - 1); +#endif + buf[len - 1] = ReadDOC(docptr, LastDataRead); *retlen = len; @@ -667,32 +718,32 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) { +#ifndef USE_MEMCPY int i; +#endif volatile char dummy; struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; unsigned long docptr = this->virtadr; struct Nand *mychip = &this->chips[ofs >> this->chipshift]; /* Find the chip which is to be used and select it */ - if (this->curfloor != mychip->floor) { + if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { + } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; - /* FIXME: should we disable ECC engine in this way ?? */ - /* disable the ECC engine, FIXME: is this correct ?? */ + /* disable the ECC engine */ WriteDOC (DOC_ECC_RESET, docptr, ECCConf); WriteDOC (DOC_ECC_DIS, docptr, ECCConf); /* Reset the chip, see Software Requirement 11.4 item 1. */ DoC_Command(docptr, NAND_CMD_RESET, CDSN_CTRL_WP); DoC_WaitReady(docptr); - /* issue the Read2 command to read the Spare Data Area. */ + /* issue the Read2 command to set the pointer to the Spare Data Area. */ DoC_Command(docptr, NAND_CMD_READOOB, CDSN_CTRL_WP); /* issue the Serial Data In command to initial the Page Program process */ @@ -701,8 +752,15 @@ /* Write the data via the internal pipeline through CDSN IO register, see Pipelined Write Operations 11.2 */ - for (i = 0; i < len; i++) - WriteDOC(buf[i], docptr, Mil_CDSN_IO); +#ifndef USE_MEMCPY + for (i = 0; i < len; i++) { + /* N.B. you have to increase the source address in this way or the + ECC logic will not work properly */ + WriteDOC(buf[i], docptr, Mil_CDSN_IO + i); + } +#else + memcpy_toio(docptr + DoC_Mil_CDSN_IO, buf, len); +#endif WriteDOC(0x00, docptr, WritePipeTerm); /* Commit the Page Program command and wait for ready @@ -717,6 +775,7 @@ DoC_Delay(docptr, 2); if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { printk("Error programming oob data\n"); + /* FIXME: implement Bad Block Replacement (in nftl.c ??) */ *retlen = 0; return -EIO; } @@ -743,13 +802,12 @@ if (this->curfloor != mychip->floor) { DoC_SelectFloor(docptr, mychip->floor); DoC_SelectChip(docptr, mychip->chip); - } - else if (this->curchip != mychip->chip) { + } else if (this->curchip != mychip->chip) { DoC_SelectChip(docptr, mychip->chip); } this->curfloor = mychip->floor; this->curchip = mychip->chip; - + instr->state = MTD_ERASE_PENDING; /* issue the Erase Setup command */ @@ -764,13 +822,16 @@ instr->state = MTD_ERASING; /* Read the status of the flash device through CDSN Slow IO register - see Software Requirement 11.4 item 5.*/ + see Software Requirement 11.4 item 5. + FIXME: it seems that we are not wait long enough, some blocks are not + erased fully */ DoC_Command(docptr, NAND_CMD_STATUS, CDSN_CTRL_WP); dummy = ReadDOC(docptr, CDSNSlowIO); DoC_Delay(docptr, 2); if (ReadDOC(docptr, Mil_CDSN_IO) & 1) { - printk("Error Erasing\n"); - /* There was an error */ + printk("Error Erasing at 0x%lx\n", ofs); + /* There was an error + FIXME: implement Bad Block Replacement (in nftl.c ??) */ instr->state = MTD_ERASE_FAILED; } else instr->state = MTD_ERASE_DONE; @@ -787,20 +848,17 @@ * ****************************************************************************/ -static int __init init_doc2001(void) +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define cleanup_doc2001 cleanup_module +#define init_doc2001 init_module +#endif + +int __init init_doc2001(void) { inter_module_register(im_name, THIS_MODULE, &DoCMil_init); return 0; } -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE -#define cleanup_doc2001 cleanup_module -#endif -#define __exit -#endif - - static void __exit cleanup_doc2001(void) { struct mtd_info *mtd; @@ -817,11 +875,9 @@ kfree(mtd); } inter_module_unregister(im_name); - } +module_exit(cleanup_doc2001); module_init(init_doc2001); -#if LINUX_VERSION_CODE > 0x20300 -module_exit(cleanup_doc2001); -#endif + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/docecc.c linux/drivers/mtd/docecc.c --- v2.4.0-test11/linux/drivers/mtd/docecc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/docecc.c Mon Dec 11 14:57:58 2000 @@ -0,0 +1,522 @@ +/* + * ECC algorithm for M-systems disk on chip. We use the excellent Reed + * Solmon code of Phil Karn (karn@ka9q.ampr.org) available under the + * GNU GPL License. The rest is simply to convert the disk on chip + * syndrom into a standard syndom. + * + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Copyright (C) 2000 Netgem S.A. + * + * $Id: docecc.c,v 1.1 2000/11/03 12:43:43 dwmw2 Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 +#include +#include +#include + +#include +#include + +/* need to undef it (from asm/termbits.h) */ +#undef B0 + +#define MM 10 /* Symbol size in bits */ +#define KK (1023-4) /* Number of data symbols per block */ +#define B0 510 /* First root of generator polynomial, alpha form */ +#define PRIM 1 /* power of alpha used to generate roots of generator poly */ +#define NN ((1 << MM) - 1) + +typedef unsigned short dtype; + +/* 1+x^3+x^10 */ +static const int Pp[MM+1] = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1 }; + +/* This defines the type used to store an element of the Galois Field + * used by the code. Make sure this is something larger than a char if + * if anything larger than GF(256) is used. + * + * Note: unsigned char will work up to GF(256) but int seems to run + * faster on the Pentium. + */ +typedef int gf; + +/* No legal value in index form represents zero, so + * we need a special value for this purpose + */ +#define A0 (NN) + +/* Compute x % NN, where NN is 2**MM - 1, + * without a slow divide + */ +static inline gf +modnn(int x) +{ + while (x >= NN) { + x -= NN; + x = (x >> MM) + (x & NN); + } + return x; +} + +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#define CLEAR(a,n) {\ +int ci;\ +for(ci=(n)-1;ci >=0;ci--)\ +(a)[ci] = 0;\ +} + +#define COPY(a,b,n) {\ +int ci;\ +for(ci=(n)-1;ci >=0;ci--)\ +(a)[ci] = (b)[ci];\ +} + +#define COPYDOWN(a,b,n) {\ +int ci;\ +for(ci=(n)-1;ci >=0;ci--)\ +(a)[ci] = (b)[ci];\ +} + +#define Ldec 1 + +/* generate GF(2**m) from the irreducible polynomial p(X) in Pp[0]..Pp[m] + lookup tables: index->polynomial form alpha_to[] contains j=alpha**i; + polynomial form -> index form index_of[j=alpha**i] = i + alpha=2 is the primitive element of GF(2**m) + HARI's COMMENT: (4/13/94) alpha_to[] can be used as follows: + Let @ represent the primitive element commonly called "alpha" that + is the root of the primitive polynomial p(x). Then in GF(2^m), for any + 0 <= i <= 2^m-2, + @^i = a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) + where the binary vector (a(0),a(1),a(2),...,a(m-1)) is the representation + of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for + example the polynomial representation of @^5 would be given by the binary + representation of the integer "alpha_to[5]". + Similarily, index_of[] can be used as follows: + As above, let @ represent the primitive element of GF(2^m) that is + the root of the primitive polynomial p(x). In order to find the power + of @ (alpha) that has the polynomial representation + a(0) + a(1) @ + a(2) @^2 + ... + a(m-1) @^(m-1) + we consider the integer "i" whose binary representation with a(0) being LSB + and a(m-1) MSB is (a(0),a(1),...,a(m-1)) and locate the entry + "index_of[i]". Now, @^index_of[i] is that element whose polynomial + representation is (a(0),a(1),a(2),...,a(m-1)). + NOTE: + The element alpha_to[2^m-1] = 0 always signifying that the + representation of "@^infinity" = 0 is (0,0,0,...,0). + Similarily, the element index_of[0] = A0 always signifying + that the power of alpha which has the polynomial representation + (0,0,...,0) is "infinity". + +*/ + +static void +generate_gf(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1]) +{ + register int i, mask; + + mask = 1; + Alpha_to[MM] = 0; + for (i = 0; i < MM; i++) { + Alpha_to[i] = mask; + Index_of[Alpha_to[i]] = i; + /* If Pp[i] == 1 then, term @^i occurs in poly-repr of @^MM */ + if (Pp[i] != 0) + Alpha_to[MM] ^= mask; /* Bit-wise EXOR operation */ + mask <<= 1; /* single left-shift */ + } + Index_of[Alpha_to[MM]] = MM; + /* + * Have obtained poly-repr of @^MM. Poly-repr of @^(i+1) is given by + * poly-repr of @^i shifted left one-bit and accounting for any @^MM + * term that may occur when poly-repr of @^i is shifted. + */ + mask >>= 1; + for (i = MM + 1; i < NN; i++) { + if (Alpha_to[i - 1] >= mask) + Alpha_to[i] = Alpha_to[MM] ^ ((Alpha_to[i - 1] ^ mask) << 1); + else + Alpha_to[i] = Alpha_to[i - 1] << 1; + Index_of[Alpha_to[i]] = i; + } + Index_of[0] = A0; + Alpha_to[NN] = 0; +} + +/* + * Performs ERRORS+ERASURES decoding of RS codes. bb[] is the content + * of the feedback shift register after having processed the data and + * the ECC. + * + * Return number of symbols corrected, or -1 if codeword is illegal + * or uncorrectable. If eras_pos is non-null, the detected error locations + * are written back. NOTE! This array must be at least NN-KK elements long. + * The corrected data are written in eras_val[]. They must be xor with the data + * to retrieve the correct data : data[erase_pos[i]] ^= erase_val[i] . + * + * First "no_eras" erasures are declared by the calling program. Then, the + * maximum # of errors correctable is t_after_eras = floor((NN-KK-no_eras)/2). + * If the number of channel errors is not greater than "t_after_eras" the + * transmitted codeword will be recovered. Details of algorithm can be found + * in R. Blahut's "Theory ... of Error-Correcting Codes". + + * Warning: the eras_pos[] array must not contain duplicate entries; decoder failure + * will result. The decoder *could* check for this condition, but it would involve + * extra time on every decoding operation. + * */ +static int +eras_dec_rs(dtype Alpha_to[NN + 1], dtype Index_of[NN + 1], + gf bb[NN - KK + 1], gf eras_val[NN-KK], int eras_pos[NN-KK], + int no_eras) +{ + int deg_lambda, el, deg_omega; + int i, j, r,k; + gf u,q,tmp,num1,num2,den,discr_r; + gf lambda[NN-KK + 1], s[NN-KK + 1]; /* Err+Eras Locator poly + * and syndrome poly */ + gf b[NN-KK + 1], t[NN-KK + 1], omega[NN-KK + 1]; + gf root[NN-KK], reg[NN-KK + 1], loc[NN-KK]; + int syn_error, count; + + syn_error = 0; + for(i=0;i 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = Alpha_to[modnn(PRIM * eras_pos[0])]; + for (i = 1; i < no_eras; i++) { + u = modnn(PRIM*eras_pos[i]); + for (j = i+1; j > 0; j--) { + tmp = Index_of[lambda[j - 1]]; + if(tmp != A0) + lambda[j] ^= Alpha_to[modnn(u + tmp)]; + } + } +#if DEBUG >= 1 + /* Test code that verifies the erasure locator polynomial just constructed + Needed only for decoder debugging. */ + + /* find roots of the erasure location polynomial */ + for(i=1;i<=no_eras;i++) + reg[i] = Index_of[lambda[i]]; + count = 0; + for (i = 1,k=NN-Ldec; i <= NN; i++,k = modnn(NN+k-Ldec)) { + q = 1; + for (j = 1; j <= no_eras; j++) + if (reg[j] != A0) { + reg[j] = modnn(reg[j] + j); + q ^= Alpha_to[reg[j]]; + } + if (q != 0) + continue; + /* store root and error location number indices */ + root[count] = i; + loc[count] = k; + count++; + } + if (count != no_eras) { + printf("\n lambda(x) is WRONG\n"); + count = -1; + goto finish; + } +#if DEBUG >= 2 + printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); +#endif +#endif + } + for(i=0;i 0; j--){ + if (reg[j] != A0) { + reg[j] = modnn(reg[j] + j); + q ^= Alpha_to[reg[j]]; + } + } + if (q != 0) + continue; + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if(++count == deg_lambda) + break; + } + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + count = -1; + goto finish; + } + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**(NN-KK)). in index form. Also find deg(omega). + */ + deg_omega = 0; + for (i = 0; i < NN-KK;i++){ + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for(;j >= 0; j--){ + if ((s[i + 1 - j] != A0) && (lambda[j] != A0)) + tmp ^= Alpha_to[modnn(s[i + 1 - j] + lambda[j])]; + } + if(tmp != 0) + deg_omega = i; + omega[i] = Index_of[tmp]; + } + omega[NN-KK] = A0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(B0-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >=0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= Alpha_to[modnn(omega[i] + i * root[j])]; + } + num2 = Alpha_to[modnn(root[j] * (B0 - 1) + NN)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = min(deg_lambda,NN-KK-1) & ~1; i >= 0; i -=2) { + if(lambda[i+1] != A0) + den ^= Alpha_to[modnn(lambda[i+1] + i * root[j])]; + } + if (den == 0) { +#if DEBUG >= 1 + printf("\n ERROR: denominator = 0\n"); +#endif + /* Convert to dual- basis */ + count = -1; + goto finish; + } + /* Apply error to data */ + if (num1 != 0) { + eras_val[j] = Alpha_to[modnn(Index_of[num1] + Index_of[num2] + NN - Index_of[den])]; + } else { + eras_val[j] = 0; + } + } + finish: + for(i=0;i> 2) | ((ecc1[2] & 0x0f) << 6); + bb[2] = ((ecc1[2] & 0xf0) >> 4) | ((ecc1[3] & 0x3f) << 4); + bb[3] = ((ecc1[3] & 0xc0) >> 6) | ((ecc1[0] & 0xff) << 2); + + nb_errors = eras_dec_rs(Alpha_to, Index_of, bb, + error_val, error_pos, 0); + if (nb_errors <= 0) + goto the_end; + + /* correct the errors */ + for(i=0;i= NB_DATA && pos < KK) { + nb_errors = -1; + goto the_end; + } + if (pos < NB_DATA) { + /* extract bit position (MSB first) */ + pos = 10 * (NB_DATA - 1 - pos) - 6; + /* now correct the following 10 bits. At most two bytes + can be modified since pos is even */ + index = (pos >> 3) ^ 1; + bitpos = pos & 7; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = error_val[i] >> (2 + bitpos); + parity ^= val; + if (index < SECTOR_SIZE) + sector[index] ^= val; + } + index = ((pos >> 3) + 1) ^ 1; + bitpos = (bitpos + 10) & 7; + if (bitpos == 0) + bitpos = 8; + if ((index >= 0 && index < SECTOR_SIZE) || + index == (SECTOR_SIZE + 1)) { + val = error_val[i] << (8 - bitpos); + parity ^= val; + if (index < SECTOR_SIZE) + sector[index] ^= val; + } + } + } + + /* use parity to test extra errors */ + if ((parity & 0xff) != 0) + nb_errors = -1; + + the_end: + kfree(Alpha_to); + kfree(Index_of); + return nb_errors; +} + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/docprobe.c linux/drivers/mtd/docprobe.c --- v2.4.0-test11/linux/drivers/mtd/docprobe.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/mtd/docprobe.c Mon Dec 11 14:57:58 2000 @@ -3,7 +3,7 @@ /* Probe routines common to all DoC devices */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $ */ +/* $Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $ */ @@ -26,6 +26,21 @@ #define DOC_PASSIVE_PROBE */ + +/* DOC_SINGLE_DRIVER: + Millennium driver has been merged into DOC2000 driver. + + The newly-merged driver doesn't appear to work for writing. It's the + same with the DiskOnChip 2000 and the Millennium. If you have a + Millennium and you want write support to work, remove the definition + of DOC_SINGLE_DRIVER below to use the old doc2001-specific driver. + + Otherwise, it's left on in the hope that it'll annoy someone with + a Millennium enough that they go through and work out what the + difference is :) +*/ +#define DOC_SINGLE_DRIVER + #include #include #include @@ -44,21 +59,36 @@ #include /* Where to look for the devices? */ +#ifndef CONFIG_MTD_DOCPROBE_ADDRESS +#define CONFIG_MTD_DOCPROBE_ADDRESS 0 +#endif + + +static unsigned long doc_config_location = CONFIG_MTD_DOCPROBE_ADDRESS; +MODULE_PARM(doc_config_location, "l"); + +static unsigned long __initdata doc_locations[] = { #if defined (__alpha__) || defined(__i386__) -static unsigned long __initdata doc_locations[] = { - 0xc8000, 0xca000, 0xcc000, 0xce000, - 0xd0000, 0xd2000, 0xd4000, 0xd6000, - 0xd8000, 0xda000, 0xdc000, 0xde000, - 0xe0000, 0xe2000, 0xe4000, 0xe6000, - 0xe8000, 0xea000, 0xec000, 0xee000, 0 }; +#ifdef CONFIG_MTD_DOCPROBE_HIGH + 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, + 0xfffd0000, 0xfffd2000, 0xfffd4000, 0xfffd6000, + 0xfffd8000, 0xfffda000, 0xfffdc000, 0xfffde000, + 0xfffe0000, 0xfffe2000, 0xfffe4000, 0xfffe6000, + 0xfffe8000, 0xfffea000, 0xfffec000, 0xfffee000, +#else /* CONFIG_MTD_DOCPROBE_HIGH */ + 0xc8000, 0xca000, 0xcc000, 0xce000, + 0xd0000, 0xd2000, 0xd4000, 0xd6000, + 0xd8000, 0xda000, 0xdc000, 0xde000, + 0xe0000, 0xe2000, 0xe4000, 0xe6000, + 0xe8000, 0xea000, 0xec000, 0xee000, +#endif /* CONFIG_MTD_DOCPROBE_HIGH */ #elif defined(__ppc__) -static unsigned long __initdata doc_locations[] = { - 0xe4000000, 0}; + 0xe4000000, #else #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif - + 0 }; /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ @@ -71,10 +101,13 @@ #endif /* Routine copied from the Linux DOC driver */ - - /* Check for 0x55 0xAA signature at beginning of window */ + +#ifdef CONFIG_MTD_DOCPROBE_55AA + /* Check for 0x55 0xAA signature at beginning of window, + this is no longer true once we remove the IPL (for Millennium */ if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa) return 0; +#endif /* CONFIG_MTD_DOCPROBE_55AA */ #ifndef DOC_PASSIVE_PROBE /* It's not possible to cleanly detect the DiskOnChip - the @@ -118,9 +151,10 @@ break; default: +#ifndef CONFIG_MTD_DOCPROBE_55AA printk(KERN_WARNING "Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", ChipID, physadr); - +#endif #ifndef DOC_PASSIVE_PROBE /* Put back the contents of the DOCControl register, in case it's not * actually a DiskOnChip. @@ -177,28 +211,35 @@ this->physadr = physadr; this->ChipID = ChipID; sprintf(namebuf, "with ChipID %2.2X", ChipID); - + switch(ChipID) { case DOC_ChipID_Doc2k: name="2000"; im_funcname = "DoC2k_init"; im_modname = "doc2000"; break; - + case DOC_ChipID_DocMil: name="Millennium"; +#ifdef DOC_SINGLE_DRIVER + im_funcname = "DoC2k_init"; + im_modname = "doc2000"; +#else im_funcname = "DoCMil_init"; im_modname = "doc2001"; +#endif /* DOC_SINGLE_DRIVER */ break; } + if (im_funcname) initroutine = inter_module_get_request(im_funcname, im_modname); + if (initroutine) { (*initroutine)(mtd); inter_module_put(im_funcname); return; } - printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name, physadr); + printk("Cannot find driver for DiskOnChip %s at 0x%lX\n", name, physadr); } iounmap((void *)docptr); } @@ -210,12 +251,9 @@ * ****************************************************************************/ -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_doc init_module #endif -#define __exit -#endif int __init init_doc(void) { @@ -223,19 +261,22 @@ printk(KERN_NOTICE "M-Systems DiskOnChip driver. (C) 1999 Machine Vision Holdings, Inc.\n"); #ifdef PRERELEASE - printk(KERN_INFO "$Id: docprobe.c,v 1.10 2000/07/13 14:23:20 dwmw2 Exp $\n"); + printk(KERN_INFO "$Id: docprobe.c,v 1.21 2000/12/03 19:32:34 dwmw2 Exp $\n"); #endif - - for (i=0; doc_locations[i]; i++) { - DoC_Probe(doc_locations[i]); + if (doc_config_location) { + printk("Using configured probe address 0x%lx\n", doc_config_location); + DoC_Probe(doc_config_location); + } else { + for (i=0; doc_locations[i]; i++) { + DoC_Probe(doc_locations[i]); + } } - + /* So it looks like we've been used and we get unloaded */ + MOD_INC_USE_COUNT; + MOD_DEC_USE_COUNT; return 0; } - -#if LINUX_VERSION_CODE > 0x20300 module_init(init_doc); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c --- v2.4.0-test11/linux/drivers/mtd/ftl.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/ftl.c Sun Dec 3 17:45:22 2000 @@ -1,6 +1,10 @@ /* This version ported to the Linux-MTD system by dwmw2@infradead.org - * $Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $ - * Based on: + * + * - Based on Id: ftl.c,v 1.21 2000/08/01 13:07:49 dwmw2 Exp + * - With the Franz Galiana's set_bam_entry fix from v1.23 + * - Perhaps it's about time I made a branch for the 2.4 series. + + * Originally based on: */ /*====================================================================== @@ -263,12 +267,13 @@ static int scan_header(partition_t *part) { erase_unit_header_t header; - loff_t offset; + loff_t offset, max_offset; int ret; part->header.FormattedSize = 0; + max_offset = (0x100000mtd->size)?0x100000:part->mtd->size; /* Search first megabyte for a valid FTL header */ for (offset = 0; - offset < 0x100000; + offset < max_offset; offset += part->mtd->erasesize?part->mtd->erasesize:0x2000) { ret = part->mtd->read(part->mtd, offset, sizeof(header), &ret, @@ -280,7 +285,7 @@ if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break; } - if (offset == 0x100000) { + if (offset == max_offset) { printk(KERN_NOTICE "ftl_cs: FTL header not found.\n"); return -ENOENT; } @@ -998,7 +1003,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr, u_int32_t virt_addr) { - u_int32_t bsize, blk; + u_int32_t bsize, blk, le_virt_addr; #ifdef PSYCHO_DEBUG u_int32_t old_addr; #endif @@ -1035,6 +1040,7 @@ return -EIO; } #endif + le_virt_addr = cpu_to_le32(virt_addr); if (part->bam_index == eun) { #ifdef PSYCHO_DEBUG if (le32_to_cpu(part->bam_cache[blk]) != old_addr) { @@ -1049,10 +1055,10 @@ return -EIO; } #endif - part->bam_cache[blk] = cpu_to_le32(virt_addr); + part->bam_cache[blk] = le_virt_addr; } ret = part->mtd->write(part->mtd, offset, sizeof(u_int32_t), - &retlen, (u_char *)&part->bam_cache[blk]); + &retlen, (u_char *)&le_virt_addr); if (ret) { printk(KERN_NOTICE "ftl_cs: set_bam_entry() failed!\n"); @@ -1409,8 +1415,6 @@ int i; memset(myparts, 0, sizeof(myparts)); - - DEBUG(0, "$Id: ftl.c,v 1.20 2000/06/23 15:17:53 dwmw2 Exp $\n"); if (register_blkdev(FTL_MAJOR, "ftl", &ftl_blk_fops)) { printk(KERN_NOTICE "ftl_cs: unable to grab major " diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/map_ram.c linux/drivers/mtd/map_ram.c --- v2.4.0-test11/linux/drivers/mtd/map_ram.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/mtd/map_ram.c Mon Dec 11 14:57:58 2000 @@ -1,7 +1,7 @@ /* * Common code to handle map devices which are simple RAM * (C) 2000 Red Hat. GPL'd. - * $Id: map_ram.c,v 1.2 2000/07/03 10:01:38 dwmw2 Exp $ + * $Id: map_ram.c,v 1.7 2000/12/10 01:39:13 dwmw2 Exp $ */ #include @@ -29,6 +29,7 @@ * this module is non-zero, i.e. between inter_module_get and * inter_module_put. Keith Owens 29 Oct 2000. */ + static struct mtd_info *map_ram_probe(struct map_info *map) { struct mtd_info *mtd; @@ -59,6 +60,7 @@ memset(mtd, 0, sizeof(*mtd)); + map->im_name = im_name; map->fldrv_destroy = mapram_nop; mtd->priv = map; mtd->name = map->name; @@ -69,9 +71,9 @@ mtd->read = mapram_read; mtd->write = mapram_write; mtd->sync = mapram_nop; - mtd->im_name = im_name; mtd->flags = MTD_CAP_RAM | MTD_VOLATILE; - + mtd->erasesize = PAGE_SIZE; + return mtd; } @@ -114,6 +116,11 @@ { /* Nothing to see here */ } + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define map_ram_init init_module +#define map_ram_exit cleanup_module +#endif static int __init map_ram_init(void) { diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/map_rom.c linux/drivers/mtd/map_rom.c --- v2.4.0-test11/linux/drivers/mtd/map_rom.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/map_rom.c Mon Dec 11 14:57:58 2000 @@ -1,7 +1,7 @@ /* * Common code to handle map devices which are simple ROM * (C) 2000 Red Hat. GPL'd. - * $Id: map_rom.c,v 1.2 2000/07/03 10:01:38 dwmw2 Exp $ + * $Id: map_rom.c,v 1.10 2000/12/10 01:39:13 dwmw2 Exp $ */ #include @@ -14,12 +14,19 @@ #include - static int maprom_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int maprom_write (struct mtd_info *, loff_t, size_t, size_t *, const u_char *); static void maprom_nop (struct mtd_info *); -struct mtd_info *map_rom_probe(struct map_info *); -EXPORT_SYMBOL(map_rom_probe); +static const char im_name[] = "map_rom_probe"; + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens 29 Oct 2000. + */ struct mtd_info *map_rom_probe(struct map_info *map) { @@ -31,16 +38,18 @@ memset(mtd, 0, sizeof(*mtd)); + map->im_name = im_name; map->fldrv_destroy = maprom_nop; mtd->priv = map; mtd->name = map->name; mtd->type = MTD_ROM; mtd->size = map->size; mtd->read = maprom_read; + mtd->write = maprom_write; mtd->sync = maprom_nop; mtd->flags = MTD_CAP_ROM; - - MOD_INC_USE_COUNT; + mtd->erasesize = 131072; + return mtd; } @@ -58,3 +67,28 @@ { /* Nothing to see here */ } + +static int maprom_write (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) +{ + printk(KERN_NOTICE "maprom_write called\n"); + return -EIO; +} + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) +#define map_rom_init init_module +#define map_rom_exit cleanup_module +#endif + +static int __init map_rom_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &map_rom_probe); + return 0; +} + +static void __exit map_rom_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(map_rom_init); +module_exit(map_rom_exit); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c --- v2.4.0-test11/linux/drivers/mtd/mtdblock.c Fri Jul 14 14:51:53 2000 +++ linux/drivers/mtd/mtdblock.c Mon Dec 11 14:57:58 2000 @@ -1,16 +1,15 @@ /* * Direct MTD block device access * - * $Id: mtdblock.c,v 1.17 2000/07/13 14:25:54 dwmw2 Exp $ + * $Id: mtdblock.c,v 1.38 2000/11/27 08:50:22 dwmw2 Exp $ + * + * 02-nov-2000 Nicolas Pitre Added read-modify-write with cache */ -#ifdef MTDBLOCK_DEBUG -#define DEBUGLVL debug -#endif - #include #include - +#include +#include #include #define MAJOR_NR MTD_BLOCK_MAJOR @@ -21,62 +20,332 @@ #define DEVICE_OFF(device) #define DEVICE_NO_RANDOM #include - +/* for old kernels... */ +#ifndef QUEUE_EMPTY +#define QUEUE_EMPTY (!CURRENT) +#endif #if LINUX_VERSION_CODE < 0x20300 -#define RQFUNC_ARG void -#define blkdev_dequeue_request(req) do {CURRENT = req->next;} while (0) +#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].plug_tq.sync) #else -#define RQFUNC_ARG request_queue_t *q +#define QUEUE_PLUGGED (blk_dev[MAJOR_NR].request_queue.plugged) #endif -#ifdef MTDBLOCK_DEBUG -static int debug = MTDBLOCK_DEBUG; -MODULE_PARM(debug, "i"); +#ifdef CONFIG_DEVFS_FS +#include +static void mtd_notify_add(struct mtd_info* mtd); +static void mtd_notify_remove(struct mtd_info* mtd); +static struct mtd_notifier notifier = { + mtd_notify_add, + mtd_notify_remove, + NULL +}; +static devfs_handle_t devfs_dir_handle = NULL; +static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES]; #endif -#if 1 -static void mtdblock_end_request(struct request *req, int res) +static struct mtdblk_dev { + struct mtd_info *mtd; /* Locked */ + int count; + struct semaphore cache_sem; + unsigned char *cache_data; + unsigned long cache_offset; + unsigned int cache_size; + enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state; +} *mtdblks[MAX_MTD_DEVICES]; + +static spinlock_t mtdblks_lock; + +static int mtd_sizes[MAX_MTD_DEVICES]; +static int mtd_blksizes[MAX_MTD_DEVICES]; + + +/* + * Cache stuff... + * + * Since typical flash erasable sectors are much larger than what Linux's + * buffer cache can handle, we must implement read-modify-write on flash + * sectors for each block write requests. To avoid over-erasing flash sectors + * and to speed things up, we locally cache a whole flash sector while it is + * being written to until a different sector is required. + */ + +static void erase_callback(struct erase_info *done) { - if (end_that_request_first( req, res, "mtdblock" )) - return; - end_that_request_last( req ); + wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv; + wake_up(wait_q); } -#endif -static int mtd_sizes[MAX_MTD_DEVICES]; +static int erase_write (struct mtd_info *mtd, unsigned long pos, + int len, const char *buf) +{ + struct erase_info erase; + DECLARE_WAITQUEUE(wait, current); + wait_queue_head_t wait_q; + size_t retlen; + int ret; + + /* + * First, let's erase the flash block. + */ + + init_waitqueue_head(&wait_q); + erase.mtd = mtd; + erase.callback = erase_callback; + erase.addr = pos; + erase.len = len; + erase.priv = (u_long)&wait_q; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&wait_q, &wait); + + ret = MTD_ERASE(mtd, &erase); + if (ret) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&wait_q, &wait); + printk (KERN_WARNING "mtdblock: erase of region [0x%lx, 0x%x] " + "on \"%s\" failed\n", + pos, len, mtd->name); + return ret; + } + + schedule(); /* Wait for erase to finish. */ + remove_wait_queue(&wait_q, &wait); + /* + * Next, writhe data to flash. + */ + + ret = MTD_WRITE (mtd, pos, len, &retlen, buf); + if (ret) + return ret; + if (retlen != len) + return -EIO; + return 0; +} -/* Keeping a separate list rather than just getting stuff directly out of - the MTD core's mtd_table is perhaps not very nice, but I happen - to dislike the idea of directly accessing mtd_table even more. - dwmw2 31/3/0 -*/ -static int mtdblock_open(struct inode *inode, struct file *file) +static int write_cached_data (struct mtdblk_dev *mtdblk) +{ + struct mtd_info *mtd = mtdblk->mtd; + int ret; + + if (mtdblk->cache_state != STATE_DIRTY) + return 0; + + DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: writing cached data for \"%s\" " + "at 0x%lx, size 0x%x\n", mtd->name, + mtdblk->cache_offset, mtdblk->cache_size); + + ret = erase_write (mtd, mtdblk->cache_offset, + mtdblk->cache_size, mtdblk->cache_data); + if (ret) + return ret; + + /* + * Here we could argably set the cache state to STATE_CLEAN. + * However this could lead to inconsistency since we will not + * be notified if this content is altered on the flash by other + * means. Let's declare it empty and leave buffering tasks to + * the buffer cache instead. + */ + mtdblk->cache_state = STATE_EMPTY; + return 0; +} + + +static int do_cached_write (struct mtdblk_dev *mtdblk, unsigned long pos, + int len, const char *buf) { - struct mtd_info *mtd = NULL; + struct mtd_info *mtd = mtdblk->mtd; + unsigned int sect_size = mtd->erasesize; + size_t retlen; + int ret; + DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: write on \"%s\" at 0x%lx, size 0x%x\n", + mtd->name, pos, len); + + while (len > 0) { + unsigned long sect_start = (pos/sect_size)*sect_size; + unsigned int offset = pos - sect_start; + unsigned int size = sect_size - offset; + if( size > len ) + size = len; + + if (size == sect_size) { + /* + * We are covering a whole sector. Thus there is no + * need to bother with the cache while it may still be + * useful for other partial writes. + */ + ret = erase_write (mtd, pos, size, buf); + if (ret) + return ret; + } else { + /* Partial sector: need to use the cache */ + + if (mtdblk->cache_state == STATE_DIRTY && + mtdblk->cache_offset != sect_start) { + ret = write_cached_data(mtdblk); + if (ret) + return ret; + } + + if (mtdblk->cache_state == STATE_EMPTY || + mtdblk->cache_offset != sect_start) { + /* fill the cache with the current sector */ + mtdblk->cache_state = STATE_EMPTY; + ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data); + if (ret) + return ret; + if (retlen != sect_size) + return -EIO; + + mtdblk->cache_offset = sect_start; + mtdblk->cache_size = sect_size; + mtdblk->cache_state = STATE_CLEAN; + } + + /* write data to our local cache */ + memcpy (mtdblk->cache_data + offset, buf, size); + mtdblk->cache_state = STATE_DIRTY; + } + + buf += size; + pos += size; + len -= size; + } + + return 0; +} + + +static int do_cached_read (struct mtdblk_dev *mtdblk, unsigned long pos, + int len, char *buf) +{ + struct mtd_info *mtd = mtdblk->mtd; + unsigned int sect_size = mtd->erasesize; + size_t retlen; + int ret; + + DEBUG(MTD_DEBUG_LEVEL2, "mtdblock: read on \"%s\" at 0x%lx, size 0x%x\n", + mtd->name, pos, len); + + while (len > 0) { + unsigned long sect_start = (pos/sect_size)*sect_size; + unsigned int offset = pos - sect_start; + unsigned int size = sect_size - offset; + if (size > len) + size = len; + + /* + * Check if the requested data is already cached + * Read the requested amount of data from our internal cache if it + * contains what we want, otherwise we read the data directly + * from flash. + */ + if (mtdblk->cache_state != STATE_EMPTY && + mtdblk->cache_offset == sect_start) { + memcpy (buf, mtdblk->cache_data + offset, size); + } else { + ret = MTD_READ (mtd, pos, size, &retlen, buf); + if (ret) + return ret; + if (retlen != size) + return -EIO; + } + + buf += size; + pos += size; + len -= size; + } + + return 0; +} + + + +static int mtdblock_open(struct inode *inode, struct file *file) +{ + struct mtdblk_dev *mtdblk; int dev; - DEBUG(1,"mtdblock_open\n"); + DEBUG(MTD_DEBUG_LEVEL1,"mtdblock_open\n"); - if (inode == 0) + if (!inode) return -EINVAL; dev = MINOR(inode->i_rdev); + if (dev >= MAX_MTD_DEVICES) + return -EINVAL; MOD_INC_USE_COUNT; - mtd = get_mtd_device(NULL, dev); + spin_lock(&mtdblks_lock); + + /* If it's already open, no need to piss about. */ + if (mtdblks[dev]) { + mtdblks[dev]->count++; + spin_unlock(&mtdblks_lock); + return 0; + } + + /* OK, it's not open. Try to find it */ + + /* First we have to drop the lock, because we have to + to things which might sleep. + */ + spin_unlock(&mtdblks_lock); + + mtdblk = kmalloc(sizeof(struct mtdblk_dev), GFP_KERNEL); + if (!mtdblk) { + MOD_DEC_USE_COUNT; + return -ENOMEM; + } + memset(mtdblk, 0, sizeof(*mtdblk)); + mtdblk->count = 1; + mtdblk->mtd = get_mtd_device(NULL, dev); - if (!mtd) { + if (!mtdblk->mtd) { + kfree(mtdblk); MOD_DEC_USE_COUNT; return -ENODEV; } - mtd_sizes[dev] = mtd->size>>9; + init_MUTEX (&mtdblk->cache_sem); + mtdblk->cache_state = STATE_EMPTY; + mtdblk->cache_size = mtdblk->mtd->erasesize; + mtdblk->cache_data = vmalloc(mtdblk->mtd->erasesize); + if (!mtdblk->cache_data) { + put_mtd_device(mtdblk->mtd); + kfree(mtdblk); + MOD_DEC_USE_COUNT; + return -ENOMEM; + } + + /* OK, we've created a new one. Add it to the list. */ + + spin_lock(&mtdblks_lock); - DEBUG(1, "ok\n"); + if (mtdblks[dev]) { + /* Another CPU made one at the same time as us. */ + mtdblks[dev]->count++; + spin_unlock(&mtdblks_lock); + put_mtd_device(mtdblk->mtd); + vfree(mtdblk->cache_data); + kfree(mtdblk); + return 0; + } + + mtdblks[dev] = mtdblk; + mtd_sizes[dev] = mtdblk->mtd->size/1024; + mtd_blksizes[dev] = mtdblk->mtd->erasesize; + if (mtd_blksizes[dev] > PAGE_SIZE) + mtd_blksizes[dev] = PAGE_SIZE; + set_device_ro (inode->i_rdev, !(mtdblk->mtd->flags & MTD_WRITEABLE)); + + spin_unlock(&mtdblks_lock); + + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); return 0; } @@ -84,11 +353,11 @@ static release_t mtdblock_release(struct inode *inode, struct file *file) { int dev; - struct mtd_info *mtd; + struct mtdblk_dev *mtdblk; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) struct super_block * sb = get_super(inode->i_rdev); #endif - DEBUG(1, "mtdblock_release\n"); + DEBUG(MTD_DEBUG_LEVEL1, "mtdblock_release\n"); if (inode == NULL) release_return(-ENODEV); @@ -100,150 +369,189 @@ invalidate_buffers(inode->i_rdev); dev = MINOR(inode->i_rdev); - mtd = __get_mtd_device(NULL, dev); + mtdblk = mtdblks[dev]; - if (!mtd) { - printk(KERN_WARNING "MTD device is absent on mtd_release!\n"); - MOD_DEC_USE_COUNT; - release_return(-ENODEV); - + down(&mtdblk->cache_sem); + write_cached_data(mtdblk); + up(&mtdblk->cache_sem); + + spin_lock(&mtdblks_lock); + if (!--mtdblk->count) { + /* It was the last usage. Free the device */ + mtdblks[dev] = NULL; + spin_unlock(&mtdblks_lock); + if (mtdblk->mtd->sync) + mtdblk->mtd->sync(mtdblk->mtd); + put_mtd_device(mtdblk->mtd); + vfree(mtdblk->cache_data); + kfree(mtdblk); + } else { + spin_unlock(&mtdblks_lock); } - - if (mtd->sync) - mtd->sync(mtd); - - put_mtd_device(mtd); - DEBUG(1, "ok\n"); + DEBUG(MTD_DEBUG_LEVEL1, "ok\n"); MOD_DEC_USE_COUNT; release_return(0); } -static void mtdblock_request(RQFUNC_ARG) +/* + * This is a special request_fn because it is executed in a process context + * to be able to sleep independently of the caller. The io_request_lock + * is held upon entry and exit. + * The head of our request queue is considered active so there is no need + * to dequeue requests before we are done. + */ +static void handle_mtdblock_request(void) { - struct request *current_request; - unsigned int res = 0; - struct mtd_info *mtd; - - while (1) - { - /* Grab the Request and unlink it from the request list, INIT_REQUEST - will execute a return if we are done. */ - INIT_REQUEST; - current_request = CURRENT; - - if (MINOR(current_request->rq_dev) >= MAX_MTD_DEVICES) - { - printk("mtd: Unsupported device!\n"); - end_request(0); - continue; - } - - // Grab our MTD structure - - mtd = __get_mtd_device(NULL, MINOR(current_request->rq_dev)); - if (!mtd) { - printk("MTD device %d doesn't appear to exist any more\n", CURRENT_DEV); - end_request(0); - } - - if (current_request->sector << 9 > mtd->size || - (current_request->sector + current_request->nr_sectors) << 9 > mtd->size) - { - printk("mtd: Attempt to read past end of device!\n"); - printk("size: %lx, sector: %lx, nr_sectors %lx\n", mtd->size, current_request->sector, current_request->nr_sectors); - end_request(0); - continue; - } - - /* Remove the request we are handling from the request list so nobody messes - with it */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - blkdev_dequeue_request(current_request); - - /* Now drop the lock that the ll_rw_blk functions grabbed for us - and process the request. This is necessary due to the extreme time - we spend processing it. */ - spin_unlock_irq(&io_request_lock); -#endif - - // Handle the request - switch (current_request->cmd) - { - size_t retlen; - - case READ: - if (mtd->read(mtd,current_request->sector<<9, - current_request->nr_sectors << 9, - &retlen, current_request->buffer) == 0) - res = 1; - else - res = 0; - break; - - case WRITE: -//printk("mtdblock_request WRITE sector=%d(%d)\n",current_request->sector, -// current_request->nr_sectors); - - // Read only device - if ((mtd->flags & MTD_CAP_RAM) == 0) - { - res = 0; - break; - } - - // Do the write - if (mtd->write(mtd,current_request->sector<<9, - current_request->nr_sectors << 9, - &retlen, current_request->buffer) == 0) - res = 1; - else - res = 0; - break; - - // Shouldn't happen - default: - printk("mtd: unknown request\n"); - break; - } + struct request *req; + struct mtdblk_dev *mtdblk; + unsigned int res; + + for (;;) { + INIT_REQUEST; + req = CURRENT; + spin_unlock_irq(&io_request_lock); + mtdblk = mtdblks[MINOR(req->rq_dev)]; + res = 0; + + if (MINOR(req->rq_dev) >= MAX_MTD_DEVICES) + panic(__FUNCTION__": minor out of bound"); + + if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9)) + goto end_req; + + // Handle the request + switch (req->cmd) + { + int err; + + case READ: + down(&mtdblk->cache_sem); + err = do_cached_read (mtdblk, req->sector << 9, + req->current_nr_sectors << 9, + req->buffer); + up(&mtdblk->cache_sem); + if (!err) + res = 1; + break; + + case WRITE: + // Read only device + if ( !(mtdblk->mtd->flags & MTD_WRITEABLE) ) + break; + + // Do the write + down(&mtdblk->cache_sem); + err = do_cached_write (mtdblk, req->sector << 9, + req->current_nr_sectors << 9, + req->buffer); + up(&mtdblk->cache_sem); + if (!err) + res = 1; + break; + } + +end_req: + spin_lock_irq(&io_request_lock); + end_request(res); + } +} - // Grab the lock and re-thread the item onto the linked list -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - spin_lock_irq(&io_request_lock); - mtdblock_end_request(current_request, res); +static volatile int leaving = 0; +#if LINUX_VERSION_CODE > 0x020300 +static DECLARE_MUTEX_LOCKED(thread_sem); +static DECLARE_WAIT_QUEUE_HEAD(thr_wq); #else - end_request(res); +static struct semaphore thread_sem = MUTEX_LOCKED; +DECLARE_WAIT_QUEUE_HEAD(thr_wq); #endif - } + +int mtdblock_thread(void *dummy) +{ + struct task_struct *tsk = current; + DECLARE_WAITQUEUE(wait, tsk); + + tsk->session = 1; + tsk->pgrp = 1; + /* we might get involved when memory gets low, so use PF_MEMALLOC */ + tsk->flags |= PF_MEMALLOC; + strcpy(tsk->comm, "mtdblockd"); + tsk->tty = NULL; + spin_lock_irq(&tsk->sigmask_lock); + sigfillset(&tsk->blocked); + recalc_sigpending(tsk); + spin_unlock_irq(&tsk->sigmask_lock); + exit_mm(tsk); + exit_files(tsk); + exit_sighand(tsk); + exit_fs(tsk); + + while (!leaving) { + add_wait_queue(&thr_wq, &wait); + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irq(&io_request_lock); + if (QUEUE_EMPTY || QUEUE_PLUGGED) { + spin_unlock_irq(&io_request_lock); + schedule(); + remove_wait_queue(&thr_wq, &wait); + } else { + remove_wait_queue(&thr_wq, &wait); + set_current_state(TASK_RUNNING); + handle_mtdblock_request(); + spin_unlock_irq(&io_request_lock); + } + } + + up(&thread_sem); + return 0; } +#if LINUX_VERSION_CODE < 0x20300 +#define RQFUNC_ARG void +#else +#define RQFUNC_ARG request_queue_t *q +#endif + +static void mtdblock_request(RQFUNC_ARG) +{ + /* Don't do anything, except wake the thread if necessary */ + wake_up(&thr_wq); +} static int mtdblock_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct mtd_info *mtd; + struct mtdblk_dev *mtdblk; - mtd = __get_mtd_device(NULL, MINOR(inode->i_rdev)); + mtdblk = mtdblks[MINOR(inode->i_rdev)]; - if (!mtd) return -EINVAL; +#ifdef PARANOIA + if (!mtdblk) + BUG(); +#endif switch (cmd) { case BLKGETSIZE: /* Return device size */ - if (!arg) return -EFAULT; - return put_user((mtd->size >> 9), - (long *) arg); + if (!arg) + return -EFAULT; + return put_user((mtdblk->mtd->size >> 9), + (long *) arg)?-EFAULT:0; case BLKFLSBUF: #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) - if(!capable(CAP_SYS_ADMIN)) return -EACCES; + if(!capable(CAP_SYS_ADMIN)) + return -EACCES; #endif fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); - if (mtd->sync) - mtd->sync(mtd); + down(&mtdblk->cache_sem); + write_cached_data(mtdblk); + up(&mtdblk->cache_sem); + if (mtdblk->mtd->sync) + mtdblk->mtd->sync(mtdblk->mtd); return 0; default: @@ -251,7 +559,6 @@ } } - /*}}}*/ #if LINUX_VERSION_CODE < 0x20326 static struct file_operations mtd_fops = { @@ -270,32 +577,69 @@ }; #endif -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#ifdef CONFIG_DEVFS_FS +/* Notification that a new device has been added. Create the devfs entry for + * it. */ + +static void mtd_notify_add(struct mtd_info* mtd) +{ + char name[8]; + + if (!mtd) + return; + + sprintf(name, "%d", mtd->index); + devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name, + DEVFS_FL_DEFAULT, MTD_BLOCK_MAJOR, mtd->index, + S_IFBLK | S_IRUGO | S_IWUGO, + &mtd_fops, NULL); +} + +static void mtd_notify_remove(struct mtd_info* mtd) +{ + if (!mtd) + return; + + devfs_unregister(devfs_rw_handle[mtd->index]); +} +#endif + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_mtdblock init_module #define cleanup_mtdblock cleanup_module #endif -#define __exit -#endif - int __init init_mtdblock(void) { int i; + spin_lock_init(&mtdblks_lock); +#ifdef CONFIG_DEVFS_FS + if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops)) + { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_BLOCK_MAJOR); + return -EAGAIN; + } + + devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); + register_mtd_user(¬ifier); +#else if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_BLOCK_MAJOR); return -EAGAIN; } +#endif /* We fill it in at open() time. */ for (i=0; i< MAX_MTD_DEVICES; i++) { mtd_sizes[i] = 0; + mtd_blksizes[i] = BLOCK_SIZE; } - + init_waitqueue_head(&thr_wq); /* Allow the block size to default to BLOCK_SIZE. */ - blksize_size[MAJOR_NR] = NULL; + blksize_size[MAJOR_NR] = mtd_blksizes; blk_size[MAJOR_NR] = mtd_sizes; #if LINUX_VERSION_CODE < 0x20320 @@ -303,15 +647,30 @@ #else blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request); #endif + kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); return 0; } static void __exit cleanup_mtdblock(void) { + leaving = 1; + wake_up(&thr_wq); + down(&thread_sem); +#ifdef CONFIG_DEVFS_FS + unregister_mtd_user(¬ifier); + devfs_unregister(devfs_dir_handle); + devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME); +#else unregister_blkdev(MAJOR_NR,DEVICE_NAME); +#endif +#if LINUX_VERSION_CODE < 0x20320 + blk_dev[MAJOR_NR].request_fn = NULL; +#else + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); +#endif + blksize_size[MAJOR_NR] = NULL; + blk_size[MAJOR_NR] = NULL; } -#if LINUX_VERSION_CODE > 0x20300 module_init(init_mtdblock); module_exit(cleanup_mtdblock); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c --- v2.4.0-test11/linux/drivers/mtd/mtdchar.c Fri Jul 14 14:51:53 2000 +++ linux/drivers/mtd/mtdchar.c Mon Dec 11 14:57:58 2000 @@ -1,5 +1,6 @@ /* - * $Id: mtdchar.c,v 1.7 2000/06/30 15:54:19 dwmw2 Exp $ + * Almost: $Id: mtdchar.c,v 1.21 2000/12/09 21:15:12 dwmw2 Exp $ + * (With some of the compatibility for previous kernels taken out) * * Character-device access to raw MTD devices. * @@ -13,6 +14,20 @@ #include #include +#ifdef CONFIG_DEVFS_FS +#include +static void mtd_notify_add(struct mtd_info* mtd); +static void mtd_notify_remove(struct mtd_info* mtd); +static struct mtd_notifier notifier = { + mtd_notify_add, + mtd_notify_remove, + NULL +}; +static devfs_handle_t devfs_dir_handle = NULL; +static devfs_handle_t devfs_rw_handle[MAX_MTD_DEVICES]; +static devfs_handle_t devfs_ro_handle[MAX_MTD_DEVICES]; +#endif + #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) #else @@ -22,11 +37,11 @@ struct mtd_info *mtd=(struct mtd_info *)file->private_data; switch (orig) { - case 0: + case 0: /* SEEK_SET */ file->f_pos = offset; break; - case 1: + case 1: /* SEEK_CUR */ file->f_pos += offset; break; @@ -34,11 +49,11 @@ /* SEEK_END */ file->f_pos =mtd->size + offset; break; - default: + default: return -EINVAL; } - if (file->f_pos < 0) + if (file->f_pos < 0) file->f_pos = 0; else if (file->f_pos >= mtd->size) file->f_pos = mtd->size - 1; @@ -54,7 +69,7 @@ int devnum = minor >> 1; struct mtd_info *mtd; - DEBUG(0, "MTD_open\n"); + DEBUG(MTD_DEBUG_LEVEL0, "MTD_open\n"); if (devnum >= MAX_MTD_DEVICES) return -ENODEV; @@ -86,7 +101,7 @@ { struct mtd_info *mtd; - DEBUG(0, "MTD_close\n"); + DEBUG(MTD_DEBUG_LEVEL0, "MTD_close\n"); mtd = (struct mtd_info *)file->private_data; @@ -115,7 +130,7 @@ int ret=0; char *kbuf; - DEBUG(0,"MTD_read\n"); + DEBUG(MTD_DEBUG_LEVEL0,"MTD_read\n"); if (FILE_POS + count > mtd->size) count = mtd->size - FILE_POS; @@ -124,7 +139,7 @@ return 0; /* FIXME: Use kiovec in 2.3 or 2.2+rawio, or at - * least split the IO into smaller chunks. + * least split the IO into smaller chunks. */ kbuf = vmalloc(count); @@ -157,7 +172,7 @@ size_t retlen; int ret=0; - DEBUG(0,"MTD_write\n"); + DEBUG(MTD_DEBUG_LEVEL0,"MTD_write\n"); if (FILE_POS == mtd->size) return -ENOSPC; @@ -208,7 +223,7 @@ int ret = 0; u_long size; - DEBUG(0, "MTD_ioctl\n"); + DEBUG(MTD_DEBUG_LEVEL0, "MTD_ioctl\n"); size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; if (cmd & IOC_IN) { @@ -222,8 +237,9 @@ switch (cmd) { case MEMGETINFO: - copy_to_user((struct mtd_info *)arg, mtd, - sizeof(struct mtd_info_user)); + if (copy_to_user((struct mtd_info *)arg, mtd, + sizeof(struct mtd_info_user))) + return -EFAULT; break; case MEMERASE: @@ -238,28 +254,23 @@ init_waitqueue_head(&waitq); memset (erase,0,sizeof(struct erase_info)); - copy_from_user(&erase->addr, (u_long *)arg, - 2 * sizeof(u_long)); + if (copy_from_user(&erase->addr, (u_long *)arg, + 2 * sizeof(u_long))) { + kfree(erase); + return -EFAULT; + } erase->mtd = mtd; erase->callback = mtd_erase_callback; erase->priv = (unsigned long)&waitq; - /* FIXME: Allow INTERRUPTIBLE. Which means - not having the wait_queue head on the stack - - Does it? Why? Who wrote this? Was it my alter - ago - the intelligent one? Or was it the stupid - one, and now I'm being clever I don't know what - it was on about? - - dwmw2. - - It was the intelligent one. If the wq_head is - on the stack, and we leave because we got - interrupted, then the wq_head is no longer - there when the callback routine tries to - wake us up --> BOOM!. - + /* + FIXME: Allow INTERRUPTIBLE. Which means + not having the wait_queue head on the stack. + + If the wq_head is on the stack, and we + leave because we got interrupted, then the + wq_head is no longer there when the + callback routine tries to wake us up. */ current->state = TASK_UNINTERRUPTIBLE; add_wait_queue(&waitq, &wait); @@ -281,7 +292,8 @@ void *databuf; ssize_t retlen; - copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)); + if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) + return -EFAULT; if (buf.length > 0x4096) return -EINVAL; @@ -298,11 +310,13 @@ if (!databuf) return -ENOMEM; - copy_from_user(databuf, buf.ptr, buf.length); + if (copy_from_user(databuf, buf.ptr, buf.length)) + return -EFAULT; ret = (mtd->write_oob)(mtd, buf.start, buf.length, &retlen, databuf); - copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)); + if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t))) + ret = -EFAULT; kfree(databuf); break; @@ -315,7 +329,8 @@ void *databuf; ssize_t retlen; - copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf)); + if (copy_from_user(&buf, (struct mtd_oob_buf *)arg, sizeof(struct mtd_oob_buf))) + return -EFAULT; if (buf.length > 0x4096) return -EINVAL; @@ -334,19 +349,42 @@ ret = (mtd->read_oob)(mtd, buf.start, buf.length, &retlen, databuf); - copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t)); - - if (retlen) - copy_to_user(buf.ptr, databuf, retlen); - + if (copy_to_user((void *)arg + sizeof(loff_t), &retlen, sizeof(ssize_t))) + ret = -EFAULT; + else if (retlen && copy_to_user(buf.ptr, databuf, retlen)) + ret = -EFAULT; + kfree(databuf); break; } - - - - + case MEMLOCK: + { + unsigned long adrs[2]; + + if (copy_from_user(adrs ,(void *)arg, 2* sizeof(unsigned long))) + return -EFAULT; + + if (!mtd->lock) + ret = -EOPNOTSUPP; + else + ret = mtd->lock(mtd, adrs[0], adrs[1]); + } + + case MEMUNLOCK: + { + unsigned long adrs[2]; + + if (copy_from_user(adrs, (void *)arg, 2* sizeof(unsigned long))) + return -EFAULT; + + if (!mtd->unlock) + ret = -EOPNOTSUPP; + else + ret = mtd->unlock(mtd, adrs[0], adrs[1]); + } + + default: printk("Invalid ioctl %x (MEMGETINFO = %x)\n",cmd, MEMGETINFO); ret = -EINVAL; @@ -366,31 +404,84 @@ }; -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#ifdef CONFIG_DEVFS_FS +/* Notification that a new device has been added. Create the devfs entry for + * it. */ + +static void mtd_notify_add(struct mtd_info* mtd) +{ + char name[8]; + + if (!mtd) + return; + + sprintf(name, "%d", mtd->index); + devfs_rw_handle[mtd->index] = devfs_register(devfs_dir_handle, name, + DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2, + S_IFCHR | S_IRUGO | S_IWUGO, + &mtd_fops, NULL); + + sprintf(name, "%dro", mtd->index); + devfs_ro_handle[mtd->index] = devfs_register(devfs_dir_handle, name, + DEVFS_FL_DEFAULT, MTD_CHAR_MAJOR, mtd->index*2+1, + S_IFCHR | S_IRUGO | S_IWUGO, + &mtd_fops, NULL); +} + +static void mtd_notify_remove(struct mtd_info* mtd) +{ + if (!mtd) + return; + + devfs_unregister(devfs_rw_handle[mtd->index]); + devfs_unregister(devfs_ro_handle[mtd->index]); +} +#endif + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_mtdchar init_module #define cleanup_mtdchar cleanup_module #endif -#endif mod_init_t init_mtdchar(void) { - - if (register_chrdev(MTD_CHAR_MAJOR,"mtd",&mtd_fops)) { +#ifdef CONFIG_DEVFS_FS + int i; + char name[8]; + struct mtd_info* mtd; + + if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) + { + printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", + MTD_CHAR_MAJOR); + return -EAGAIN; + } + + devfs_dir_handle = devfs_mk_dir(NULL, "mtd", NULL); + + register_mtd_user(¬ifier); +#else + if (register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops)) + { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", MTD_CHAR_MAJOR); return -EAGAIN; } +#endif return 0; } mod_exit_t cleanup_mtdchar(void) { - unregister_chrdev(MTD_CHAR_MAJOR,"mtd"); +#ifdef CONFIG_DEVFS_FS + unregister_mtd_user(¬ifier); + devfs_unregister(devfs_dir_handle); + devfs_unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); +#else + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); +#endif } -#if LINUX_VERSION_CODE > 0x20300 module_init(init_mtdchar); module_exit(cleanup_mtdchar); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/mtdcore.c linux/drivers/mtd/mtdcore.c --- v2.4.0-test11/linux/drivers/mtd/mtdcore.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/mtdcore.c Mon Dec 11 14:57:58 2000 @@ -1,15 +1,11 @@ /* - * $Id: mtdcore.c,v 1.13 2000/07/13 14:27:37 dwmw2 Exp $ + * $Id: mtdcore.c,v 1.27 2000/12/10 01:10:09 dwmw2 Exp $ * - * Core registration and callback routines for MTD + * Core registration and callback routines for MTD * drivers and users. * */ -#ifdef MTD_DEBUG -#define DEBUGLVL debug -#endif - #include #include #include @@ -29,67 +25,12 @@ #include -#ifdef MTD_DEBUG -static int debug = MTD_DEBUG; -MODULE_PARM(debug, "i"); -#endif - -/* Init code required for 2.2 kernels */ - -#if LINUX_VERSION_CODE < 0x20300 - -#ifdef CONFIG_MTD_DOC1000 -extern int init_doc1000(void); -#endif -#ifdef CONFIG_MTD_DOCPROBE -extern int init_doc(void); -#endif -#ifdef CONFIG_MTD_PHYSMAP -extern int init_physmap(void); -#endif -#ifdef CONFIG_MTD_RPXLITE -extern int init_rpxlite(void); -#endif -#ifdef CONFIG_MTD_OCTAGON -extern int init_octagon5066(void); -#endif -#ifdef CONFIG_MTD_PNC2000 -extern int init_pnc2000(void); -#endif -#ifdef CONFIG_MTD_VMAX -extern int init_vmax301(void); -#endif -#ifdef CONFIG_MTD_MIXMEM -extern int init_mixmem(void); -#endif -#ifdef CONFIG_MTD_PMC551 -extern int init_pmc551(void); -#endif -#ifdef CONFIG_MTD_NORA -extern int init_nora(void); -#endif -#ifdef CONFIG_FTL -extern int init_ftl(void); -#endif -#ifdef CONFIG_NFTL -extern int init_nftl(void); -#endif -#ifdef CONFIG_MTD_BLOCK -extern int init_mtdblock(void); -#endif -#ifdef CONFIG_MTD_CHAR -extern int init_mtdchar(void); -#endif - -#endif /* LINUX_VERSION_CODE < 0x20300 */ - - static DECLARE_MUTEX(mtd_table_mutex); static struct mtd_info *mtd_table[MAX_MTD_DEVICES]; static struct mtd_notifier *mtd_notifiers = NULL; /** - * add_mtd_device - register an MTD device + * add_mtd_device - register an MTD device * @mtd: pointer to new MTD device info structure * * Add a device to the list of MTD devices present in the system, and @@ -110,6 +51,7 @@ struct mtd_notifier *not=mtd_notifiers; mtd_table[i] = mtd; + mtd->index = i; DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name); while (not) { @@ -126,7 +68,7 @@ } /** - * del_mtd_device - unregister an MTD device + * del_mtd_device - unregister an MTD device * @mtd: pointer to MTD device info structure * * Remove a device from the list of MTD devices present in the system, @@ -194,7 +136,7 @@ * @new: pointer to notifier info structure * * Removes a callback function pair from the list of 'users' to be - * notified upon addition or removal of MTD devices. Causes the + * notified upon addition or removal of MTD devices. Causes the * 'remove' callback to be immediately invoked for each MTD device * currently present in the system. */ @@ -232,7 +174,7 @@ * @mtd: last known address of the required MTD device * @num: internal device number of the required MTD device * - * Given a number and NULL address, return the num'th entry in the device + * Given a number and NULL address, return the num'th entry in the device * table, if any. Given an address and num == -1, search the device table * for a device with that address and return if it's still present. Given * both, return the num'th driver only if its address matches. Return NULL @@ -313,10 +255,10 @@ { struct mtd_info *this = mtd_table[i]; - if (!this) + if (!this) return 0; - return sprintf(buf, "mtd%d: %8.8lx \"%s\"\n", i, this->size, + return sprintf(buf, "mtd%d: %8.8lx \"%s\"\n", i, this->size, this->name); } @@ -330,7 +272,7 @@ { int len = 0, l, i; off_t begin = 0; - + down(&mtd_table_mutex); for (i=0; i< MAX_MTD_DEVICES; i++) { @@ -374,79 +316,13 @@ /*====================================================================*/ /* Init code */ -#if LINUX_VERSION_CODE < 0x20300 - -static inline void init_others(void) -{ - /* Shedloads of calls to init functions of all the - * other drivers and users of MTD, which we can - * ditch in 2.3 because of the sexy new way of - * finding init routines. - */ -#ifdef CONFIG_MTD_DOC1000 - init_doc1000(); -#endif -#ifdef CONFIG_MTD_DOCPROBE - init_doc(); /* This covers both the DiskOnChip 2000 - * and the DiskOnChip Millennium. - * Theoretically all other DiskOnChip - * devices too. */ -#endif -#ifdef CONFIG_MTD_PHYSMAP - init_physmap(); -#endif -#ifdef CONFIG_MTD_RPXLITE - init_rpxlite(); -#endif -#ifdef CONFIG_MTD_OCTAGON - init_octagon5066(); -#endif -#ifdef CONFIG_MTD_PNC2000 - init_pnc2000(); -#endif -#ifdef CONFIG_MTD_VMAX - init_vmax301(); -#endif -#ifdef CONFIGF_MTD_MIXMEM - init_mixmem(); -#endif -#ifdef CONFIG_MTD_PMC551 - init_pmc551(); -#endif -#ifdef CONFIG_MTD_NORA - init_nora(); -#endif -#ifdef CONFIG_MTD_MTDRAM - init_mtdram(); -#endif -#ifdef CONFIG_FTL - init_ftl(); -#endif -#ifdef CONFIG_NFTL - init_nftl(); -#endif -#ifdef CONFIG_MTD_BLOCK - init_mtdblock(); -#endif -#ifdef CONFIG_MTD_CHAR - init_mtdchar(); -#endif -} - -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_mtd init_module #define cleanup_mtd cleanup_module #endif -#endif /* LINUX_VERSION_CODE < 0x20300 */ - mod_init_t init_mtd(void) { - int i; - DEBUG(1, "INIT_MTD:\n"); - for (i=0; i= KERNEL_VERSION(2,2,0) if ((proc_mtd = create_proc_entry( "mtd", 0, 0 ))) @@ -454,12 +330,12 @@ #else proc_register_dynamic(&proc_root,&mtd_proc_entry); #endif - #endif -#if LINUX_VERSION_CODE < 0x20300 - init_others(); +#if LINUX_VERSION_CODE < 0x20212 + init_mtd_devices(); #endif + #ifdef CONFIG_PM mtd_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, mtd_pm_callback); #endif @@ -468,13 +344,13 @@ mod_exit_t cleanup_mtd(void) { - unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); #ifdef CONFIG_PM if (mtd_pm_dev) { pm_unregister(mtd_pm_dev); mtd_pm_dev = NULL; } #endif + #ifdef CONFIG_PROC_FS #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0) if (proc_mtd) @@ -484,10 +360,8 @@ #endif #endif } - -#if LINUX_VERSION_CODE > 0x20300 + module_init(init_mtd); module_exit(cleanup_mtd); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/mtdpart.c linux/drivers/mtd/mtdpart.c --- v2.4.0-test11/linux/drivers/mtd/mtdpart.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/mtdpart.c Mon Dec 11 14:57:58 2000 @@ -0,0 +1,228 @@ +/* + * Simple MTD partitioning layer + * + * (C) 2000 Nicolas Pitre + * + * This code is GPL + * + * $Id: mtdpart.c,v 1.7 2000/12/09 23:29:47 dwmw2 Exp $ + */ + +#include +#include +#include +#include +#include + +#include +#include + + +/* Our partition linked list */ +static LIST_HEAD(mtd_partitions); + +/* Our partition node structure */ +struct mtd_part { + struct mtd_info mtd; + struct mtd_info *master; + loff_t offset; + int index; + struct list_head list; +}; + +/* + * Given a pointer to the MTD object in the mtd_part structure, we can retrieve + * the pointer to that structure with this macro. + */ +#define PART(x) ((struct mtd_part *)(x)) + + +/* + * MTD methods which simply translate the effective address and pass through + * to the _real_ device. + */ + +static int part_read (struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct mtd_part *part = PART(mtd); + if (from >= mtd->size) + len = 0; + else if (from + len > mtd->size) + len = mtd->size - from; + return part->master->read (part->master, from + part->offset, + len, retlen, buf); +} + +static int part_write (struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct mtd_part *part = PART(mtd); + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + if (to >= mtd->size) + len = 0; + else if (to + len > mtd->size) + len = mtd->size - to; + return part->master->write (part->master, to + part->offset, + len, retlen, buf); +} + +static int part_writev (struct mtd_info *mtd, const struct iovec *vecs, + unsigned long count, loff_t to, size_t *retlen) +{ + struct mtd_part *part = PART(mtd); + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + return part->master->writev (part->master, vecs, count, + to + part->offset, retlen); +} + +static int part_readv (struct mtd_info *mtd, struct iovec *vecs, + unsigned long count, loff_t from, size_t *retlen) +{ + struct mtd_part *part = PART(mtd); + return part->master->readv (part->master, vecs, count, + from + part->offset, retlen); +} + +static int part_erase (struct mtd_info *mtd, struct erase_info *instr) +{ + struct mtd_part *part = PART(mtd); + if (!(mtd->flags & MTD_WRITEABLE)) + return -EROFS; + if (instr->addr >= mtd->size) + return -EINVAL; + instr->addr += part->offset; + return part->master->erase(part->master, instr); +} + +static int part_lock (struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct mtd_part *part = PART(mtd); + return part->master->lock(part->master, ofs + part->offset, len); +} + +static int part_unlock (struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct mtd_part *part = PART(mtd); + return part->master->unlock(part->master, ofs + part->offset, len); +} + + +/* + * This function unregisters and destroy all slave MTD objects which are + * attached to the given master MTD object. + */ + +int del_mtd_partitions(struct mtd_info *master) +{ + struct list_head *node; + struct mtd_part *slave; + + for (node = mtd_partitions.next; + node != &mtd_partitions; + node = node->next) { + slave = list_entry(node, struct mtd_part, list); + if (slave->master == master) { + struct list_head *prev = node->prev; + __list_del(prev, node->next); + del_mtd_device(&slave->mtd); + kfree(slave); + node = prev; + MOD_DEC_USE_COUNT; + } + } + + return 0; +} + + +/* + * This function, given a master MTD object and a partition table, creates + * and registers slave MTD objects which are bound to the master according to + * the partition definitions. + * (Q: should we register the master MTD object as well?) + */ + +int add_mtd_partitions(struct mtd_info *master, + struct mtd_partition *parts, + int nbparts) +{ + struct mtd_part *slave; + u_long cur_offset = 0; + int i; + + for (i = 0; i < nbparts; i++) { + /* allocate the partition structure */ + slave = kmalloc (sizeof(*slave), GFP_KERNEL); + if (!slave) { + printk ("memory allocation error while creating partitions for \"%s\"\n", + master->name); + del_mtd_partitions(master); + return -ENOMEM; + } + list_add(&slave->list, &mtd_partitions); + + /* set up the MTD object for this partition */ + slave->mtd = *master; + slave->mtd.name = parts[i].name; + slave->mtd.size = parts[i].size; + slave->mtd.flags &= ~parts[i].mask_flags; + slave->mtd.read = part_read; + slave->mtd.write = part_write; + if (slave->mtd.writev) + slave->mtd.writev = part_writev; + if (slave->mtd.readv) + slave->mtd.readv = part_readv; + if (slave->mtd.lock) + slave->mtd.lock = part_lock; + if (slave->mtd.unlock) + slave->mtd.unlock = part_unlock; + slave->mtd.erase = part_erase; + slave->master = master; + slave->offset = parts[i].offset; + slave->index = i; + + if (slave->offset == 0) + slave->offset = cur_offset; + if (slave->mtd.size == 0) + slave->mtd.size = master->size - slave->offset; + cur_offset = slave->offset + slave->mtd.size; + + /* let's do some sanity checks */ + if ((slave->mtd.flags & MTD_WRITEABLE) && + (parts[i].offset % master->erasesize)) { + slave->mtd.flags &= ~MTD_WRITEABLE; + printk ("mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-only\n", + parts[i].name); + } + if ((slave->mtd.flags & MTD_WRITEABLE) && + (parts[i].size % master->erasesize)) { + slave->mtd.flags &= ~MTD_WRITEABLE; + printk ("mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", + parts[i].name); + } + if (parts[i].offset >= master->size) { + /* let's register it anyway to preserve ordering */ + slave->offset = 0; + slave->mtd.size = 0; + printk ("mtd: partition \"%s\" is out of reach -- disabled\n", + parts[i].name); + } + if (parts[i].offset + parts[i].size > master->size) { + slave->mtd.size = master->size - parts[i].offset; + printk ("mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncated to %#lx\n", + parts[i].name, master->name, slave->mtd.size); + } + + /* register our partition */ + add_mtd_device(&slave->mtd); + MOD_INC_USE_COUNT; + } + + return 0; +} + +EXPORT_SYMBOL(add_mtd_partitions); +EXPORT_SYMBOL(del_mtd_partitions); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/nftl.c linux/drivers/mtd/nftl.c --- v2.4.0-test11/linux/drivers/mtd/nftl.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/nftl.c Mon Dec 11 14:57:58 2000 @@ -1,32 +1,35 @@ - /* Linux driver for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ /* Author: David Woodhouse */ -/* $Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $ */ +/* $Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $ */ /* - The contents of this file are distributed under the GNU Public - Licence version 2 ("GPL"). The legal note below refers only to the - _use_ of the code in some jurisdictions, and does not in any way - affect the copying, distribution and modification of this code, - which is permitted under the terms of the GPL. + The contents of this file are distributed under the GNU General + Public License version 2 ("GPL"). The author places no additional + restrictions of any kind on it. However, local legislation in some + countries may restrict the use of the algorithms implemented by this + code in certain circumstances. + + The legal note below refers only to the _use_ of the code in the + affected jurisdictions, and does not in any way affect the copying, + distribution and modification of this code, which are permitted, and + indeed required, under the terms of the GPL. Section 0 of the GPL says: - "Activities other than copying, distribution and modification are not covered by this License; they are outside its scope." You may copy, distribute and modify this code to your hearts' content - it's just that in some jurisdictions, you may only _use_ - it under the terms of the licence below. This puts it in a similar - situation to the ISDN code, which you may need telco approval to - use, and indeed any code which has uses that may be restricted in - law. For example, certain malicious uses of the networking stack - may be illegal, but that doesn't prevent the networking code from - being under GPL. + it under the terms of the patent grant below. This puts it in a + similar situation to the ISDN code, which you may need telco + approval to use, and indeed any code which has uses that may be + restricted in law. For example, certain malicious uses of the + networking stack may be illegal, but that doesn't prevent the + networking code from being under GPL. In fact the ISDN case is worse than this, because modification of - the code automatically invalidates its approval. Modificiation, + the code automatically invalidates its approval. Modification, unlike usage, _is_ one of the rights which is protected by the GPL. Happily, the law in those places where approval is required doesn't actually prevent you from modifying the code - it's just @@ -34,7 +37,7 @@ because usage isn't addressed by the GPL, that's just fine. dwmw2@infradead.org - 6/7/0 + 30/10/0 LEGAL NOTE: The NFTL format is patented by M-Systems. They have granted a licence for its use with their DiskOnChip products: @@ -51,10 +54,6 @@ #define PRERELEASE -#ifdef NFTL_DEBUG -#define DEBUGLVL debug -#endif - #include #include #include @@ -67,42 +66,28 @@ #include #include #include +#include +#ifdef CONFIG_KMOD +#include +#endif #include #include #include -#undef WE_KNOW_WTF_THIS_DOES_NOT_WORK +/* maximum number of loops while examining next block, to have a + chance to detect consistency problems (they should never happen + because of the checks done in the mounting */ + +#define MAX_LOOPS 10000 /* NFTL block device stuff */ #define MAJOR_NR NFTL_MAJOR #define DEVICE_REQUEST nftl_request #define DEVICE_OFF(device) -#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK -#define LOCAL_END_REQUEST -#endif -#include -#include - - -#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK - -static void nftl_end_request(struct request *req, int res) -{ - req->sector += req->current_nr_sectors; - req->nr_sectors -= req->current_nr_sectors; - - if (end_that_request_first( req, res, "nftl" )) - return; - end_that_request_last( req ); -} -#endif - -#ifdef NFTL_DEBUG -static int debug = NFTL_DEBUG; -MODULE_PARM(debug, "i"); -#endif +#include +#include /* Linux-specific block device functions */ @@ -110,11 +95,10 @@ * encountered, except ... */ -static int nftl_sizes[256]={0,}; +static int nftl_sizes[256] = {0,}; static int nftl_blocksizes[256] = {0,}; /* .. for the Linux partition table handling. */ - struct hd_struct part_table[256] = {{0,0},}; #if LINUX_VERSION_CODE < 0x20328 @@ -123,8 +107,8 @@ #endif static struct gendisk nftl_gendisk = { - NFTL_MAJOR, /* Major number */ - "nftl", /* Major name */ + MAJOR_NR, /* Major number */ + "nftl", /* Major name */ 4, /* Bits to shift to get real from partition */ 15, /* Number of partitions per real */ #if LINUX_VERSION_CODE < 0x20328 @@ -138,281 +122,129 @@ NULL /* next */ }; - struct NFTLrecord *NFTLs[MAX_NFTLS] = {NULL}; -static void NFTL_setup(struct mtd_info *mtd, unsigned long ofs, - struct NFTLMediaHeader *hdr) +static void NFTL_setup(struct mtd_info *mtd) { int i; - struct NFTLrecord *thisNFTL; + struct NFTLrecord *nftl; unsigned long temp; int firstfree = -1; - DEBUG(1,"NFTL_setup\n"); + DEBUG(MTD_DEBUG_LEVEL1,"NFTL_setup\n"); - for (i=0; i < MAX_NFTLS; i++) { - if (!NFTLs[i] && firstfree==-1) + for (i = 0; i < MAX_NFTLS; i++) { + if (!NFTLs[i] && firstfree == -1) firstfree = i; - else if (NFTLs[i] && NFTLs[i]->mtd == mtd && - NFTLs[i]->MediaHdr.FirstPhysicalEUN == hdr->FirstPhysicalEUN) { + else if (NFTLs[i] && NFTLs[i]->mtd == mtd) { /* This is a Spare Media Header for an NFTL we've already found */ - DEBUG(1, "Spare Media Header for NFTL %d found at %lx\n",i, ofs); - NFTLs[i]->SpareMediaUnit = ofs / mtd->erasesize; + DEBUG(MTD_DEBUG_LEVEL1, "MTD already mounted as NFTL\n"); return; } } - - - /* OK, it's a new one. Set up all the data structures. */ -#ifdef PSYCHO_DEBUG - printk("Found new NFTL nftl%c at offset %lx\n",firstfree + 'a', ofs); -#endif - if (hdr->UnitSizeFactor != 0xff) { - printk("Sorry, we don't support UnitSizeFactor of != 1 yet\n"); + if (firstfree == -1) { + printk(KERN_WARNING "No more NFTL slot available\n"); return; - } - - thisNFTL = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); - if (!thisNFTL) { + } + + nftl = kmalloc(sizeof(struct NFTLrecord), GFP_KERNEL); + if (!nftl) { printk(KERN_WARNING "Out of memory for NFTL data structures\n"); return; } - init_MUTEX(&thisNFTL->mutex); - thisNFTL->EraseSize = mtd->erasesize; - memcpy(&thisNFTL->MediaHdr, hdr, sizeof(*hdr)); - thisNFTL->mtd = mtd; - thisNFTL->MediaUnit = ofs / mtd->erasesize; - thisNFTL->SpareMediaUnit = 0xffff; - thisNFTL->numvunits = le32_to_cpu(thisNFTL->MediaHdr.FormattedSize) / 8192; - thisNFTL->nr_sects = thisNFTL->numvunits * (thisNFTL->EraseSize / 512); - thisNFTL->usecount = 0; - - thisNFTL->cylinders = 1024; - thisNFTL->heads = 16; - - temp = thisNFTL->cylinders * thisNFTL->heads; - thisNFTL->sectors = thisNFTL->nr_sects / temp; - - if (thisNFTL->nr_sects % temp) { - - thisNFTL->sectors++; - temp = thisNFTL->cylinders * thisNFTL->sectors; - thisNFTL->heads = thisNFTL->nr_sects / temp; - - if (thisNFTL->nr_sects & temp) { - thisNFTL->heads++; - temp = thisNFTL->heads * thisNFTL->sectors; - - thisNFTL->cylinders = thisNFTL->nr_sects / temp; - } - } - if (thisNFTL->nr_sects != thisNFTL->heads * thisNFTL->cylinders * - thisNFTL->sectors) { - printk(KERN_WARNING "Cannot calculate an NFTL geometry to match size of 0x%lx.\n", thisNFTL->nr_sects); - printk(KERN_WARNING "Using C:%d H:%d S:%d (== %lx sects)\n", - thisNFTL->cylinders, thisNFTL->heads , - thisNFTL->sectors, - (long)thisNFTL->cylinders * (long)thisNFTL->heads * - (long)thisNFTL->sectors ); - - /* Oh no we don't - * thisNFTL->nr_sects = thisNFTL->heads * thisNFTL->cylinders * thisNFTL->sectors; - */ - } - - thisNFTL->EUNtable = kmalloc( 2 * thisNFTL->numvunits, - GFP_KERNEL); - if (!thisNFTL->EUNtable) { - printk("ENOMEM\n"); - kfree(thisNFTL); - return; - } - memset(thisNFTL->EUNtable, 0xff, 2 * thisNFTL->numvunits); - - thisNFTL->VirtualUnitTable = kmalloc( 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) , GFP_KERNEL); - if (!thisNFTL->VirtualUnitTable) { - printk("ENOMEM\n"); - kfree(thisNFTL->EUNtable); - kfree(thisNFTL); - return; - } - memset(thisNFTL->VirtualUnitTable, 0xff, 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits)); - - thisNFTL->ReplUnitTable = kmalloc( 2 * le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) , GFP_KERNEL); - if (!thisNFTL->ReplUnitTable) { - printk("ENOMEM\n"); - kfree(thisNFTL->VirtualUnitTable); - kfree(thisNFTL->EUNtable); - kfree(thisNFTL); + init_MUTEX(&nftl->mutex); + + /* get physical parameters */ + nftl->EraseSize = mtd->erasesize; + nftl->nb_blocks = mtd->size / mtd->erasesize; + nftl->mtd = mtd; + + if (NFTL_mount(nftl) < 0) { + printk(KERN_WARNING "Could not mount NFTL device\n"); + kfree(nftl); return; - } - memset(thisNFTL->ReplUnitTable, 0xff, 2 *le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) ); - - /* Ought to check the media header for bad blocks */ - thisNFTL->lastEUN = le16_to_cpu(thisNFTL->MediaHdr.NumEraseUnits) + - le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN) - 1; - thisNFTL->numfreeEUNs = 0; + } - /* Scan each physical Erase Unit for validity and to find the - Virtual Erase Unit Chain to which it belongs */ - - for (i=le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN); - i <= thisNFTL->lastEUN; i++) { - - union nftl_uci uci; - unsigned long ofs; - size_t retlen; - ofs = i * thisNFTL->EraseSize; - - MTD_READOOB(mtd, (i * thisNFTL->EraseSize) + 512 + 8, 8, &retlen, (char *)&uci); - - if (uci.b.EraseMark != cpu_to_le16(0x3c69) || - uci.b.EraseMark1 != cpu_to_le16(0x3c69)) { - printk("EUN %d: EraseMark not 0x3c69 (0x%4.4x 0x%4.4x instead)\n", - i, le16_to_cpu(uci.b.EraseMark), le16_to_cpu(uci.b.EraseMark1)); - thisNFTL->VirtualUnitTable[i] = 0x7fff; - thisNFTL->ReplUnitTable[i] = 0xffff; - continue; - } - - MTD_READOOB(mtd, (i * thisNFTL->EraseSize) + 8, 8, &retlen, (u_char *)&uci); - - if (uci.a.VirtUnitNum != uci.a.SpareVirtUnitNum) - printk("EUN %d: VirtualUnitNumber (%x) != SpareVirtualUnitNumber (%x)\n", - i, le16_to_cpu(uci.a.VirtUnitNum), - le16_to_cpu(uci.a.SpareVirtUnitNum)); - - if (uci.a.ReplUnitNum != uci.a.SpareReplUnitNum) - printk("EUN %d: ReplacementUnitNumber (%x) != SpareReplacementUnitNumber (%x)\n", - i, le16_to_cpu(uci.a.ReplUnitNum), - le16_to_cpu(uci.a.SpareReplUnitNum)); - - /* We don't actually _do_ anything about the above, just whinge */ - - thisNFTL->VirtualUnitTable[i] = le16_to_cpu(uci.a.VirtUnitNum); - thisNFTL->ReplUnitTable[i] = le16_to_cpu(uci.a.ReplUnitNum); - - /* if (!(VUN & 0x8000) && VUN < (arraybounds)).. optimises to: */ - if (le16_to_cpu(uci.a.VirtUnitNum) < thisNFTL->numvunits) - thisNFTL->EUNtable[le16_to_cpu(uci.a.VirtUnitNum) & 0x7fff] = i; - - if (uci.a.VirtUnitNum == 0xffff) { - /* Free block */ - thisNFTL->LastFreeEUN = i; - thisNFTL->numfreeEUNs++; - } - - } - NFTLs[firstfree] = thisNFTL; - thisNFTL->LastFreeEUN = le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN); - - //#define PSYCHO_DEBUG + /* OK, it's a new one. Set up all the data structures. */ #ifdef PSYCHO_DEBUG - for (i=0; i < 10/* thisNFTL->numvunits*/; i++) { - u16 curEUN = thisNFTL->EUNtable[i]; - int sillycount=100; - - printk("Virtual Unit #%d: ",i); - if (!curEUN || curEUN == 0xffff) { - printk("Not present\n"); - continue; - } - printk("%d", curEUN); - - while ((curEUN = thisNFTL->ReplUnitTable[curEUN]) != 0xffff && --sillycount) { - printk(", %d", curEUN & 0xffff); - + printk("Found new NFTL nftl%c\n", firstfree + 'a'); +#endif + + /* linux stuff */ + nftl->usecount = 0; + nftl->cylinders = 1024; + nftl->heads = 16; + + temp = nftl->cylinders * nftl->heads; + nftl->sectors = nftl->nr_sects / temp; + if (nftl->nr_sects % temp) { + nftl->sectors++; + temp = nftl->cylinders * nftl->sectors; + nftl->heads = nftl->nr_sects / temp; + + if (nftl->nr_sects % temp) { + nftl->heads++; + temp = nftl->heads * nftl->sectors; + nftl->cylinders = nftl->nr_sects / temp; } - printk("\n"); } -#endif - /* OK. Now we deal with the fact that we're in the real world. Sometimes - things don't actually happen the way they're supposed to. Find, fix, - and whinge about the most common deviations from spec that we have - been known to encounter. - */ - /* Except that I haven't implemented that bit yet :) */ + if (nftl->nr_sects != nftl->heads * nftl->cylinders * nftl->sectors) { + printk(KERN_WARNING "Cannot calculate an NFTL geometry to " + "match size of 0x%lx.\n", nftl->nr_sects); + printk(KERN_WARNING "Using C:%d H:%d S:%d (== 0x%lx sects)\n", + nftl->cylinders, nftl->heads , nftl->sectors, + (long)nftl->cylinders * (long)nftl->heads * (long)nftl->sectors ); + /* Oh no we don't have nftl->nr_sects = nftl->heads * nftl->cylinders * nftl->sectors; */ + } + NFTLs[firstfree] = nftl; /* Finally, set up the block device sizes */ - nftl_sizes[firstfree * 16]=thisNFTL->nr_sects; -// nftl_blocksizes[firstfree*16] = 512; - part_table[firstfree * 16].nr_sects = thisNFTL->nr_sects; + nftl_sizes[firstfree * 16] = nftl->nr_sects; + //nftl_blocksizes[firstfree*16] = 512; + part_table[firstfree * 16].nr_sects = nftl->nr_sects; + + /* partition check ... */ #if LINUX_VERSION_CODE < 0x20328 resetup_one_dev(&nftl_gendisk, firstfree); #else - grok_partitions(&nftl_gendisk, firstfree, 1<<4, thisNFTL->nr_sects); + grok_partitions(&nftl_gendisk, firstfree, 1<<4, nftl->nr_sects); #endif - } - static void NFTL_unsetup(int i) { - struct NFTLrecord *thisNFTL = NFTLs[i]; + struct NFTLrecord *nftl = NFTLs[i]; - DEBUG(1, "NFTL_unsetup %d\n", i); + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_unsetup %d\n", i); NFTLs[i] = NULL; - if (thisNFTL->VirtualUnitTable) - kfree(thisNFTL->VirtualUnitTable); - if (thisNFTL->ReplUnitTable) - kfree(thisNFTL->ReplUnitTable); - if (thisNFTL->EUNtable) - kfree(thisNFTL->EUNtable); + if (nftl->ReplUnitTable) + kfree(nftl->ReplUnitTable); + if (nftl->EUNtable) + kfree(nftl->EUNtable); - kfree(thisNFTL); + kfree(nftl); } - - - /* Search the MTD device for NFTL partitions */ static void NFTL_notify_add(struct mtd_info *mtd) { - int i; - unsigned long ofs; - struct NFTLMediaHeader hdr; - - DEBUG(1, "NFTL_notify_add for %s\n", mtd->name); + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_notify_add for %s\n", mtd->name); if (mtd) { - if (!mtd->read_oob) /* If this MTD doesn't have out-of-band data, - then there's no point continuing */ - { - DEBUG(1, "No OOB data, quitting\n"); + if (!mtd->read_oob) { + /* If this MTD doesn't have out-of-band data, + then there's no point continuing */ + DEBUG(MTD_DEBUG_LEVEL1, "No OOB data, quitting\n"); return; } - DEBUG(3, "mtd->read = %p,size = %d, erasesize = %d\n", - mtd->read, mtd->size, mtd->erasesize); - for (ofs = 0; ofs < mtd->size ; ofs += mtd->erasesize) { - size_t retlen = 0; - MTD_READ(mtd, ofs, sizeof(hdr), &retlen, (u_char *)&hdr); - - if (retlen < sizeof(hdr)) - { - continue; - } - - if (!strncmp(hdr.DataOrgID, "ANAND", 6)) { - DEBUG(2, "Valid NFTL partition at ofs %ld\n", ofs); - NFTL_setup(mtd, ofs, &hdr); - } - else { - DEBUG(3,"No valid NFTL Partition at ofs %d\n", ofs); - for(i = 0; i < 6; i++) { - DEBUG(3,"%x, ", hdr.DataOrgID[i]); - } - DEBUG(3," = %s\n", hdr.DataOrgID); - DEBUG(3,"%d, %d, %d, %d\n", hdr.NumEraseUnits, hdr.FirstPhysicalEUN, - hdr.FormattedSize, hdr.UnitSizeFactor); + DEBUG(MTD_DEBUG_LEVEL3, "mtd->read = %p, size = %d, erasesize = %d\n", + mtd->read, mtd->size, mtd->erasesize); - } - } - return; + NFTL_setup(mtd); } } @@ -420,100 +252,101 @@ { int i; - for (i=0; i< MAX_NFTLS; i++) { + for (i = 0; i < MAX_NFTLS; i++) { if (NFTLs[i] && NFTLs[i]->mtd == mtd) NFTL_unsetup(i); } } - #ifdef CONFIG_NFTL_RW /* Actual NFTL access routines */ - - -static u16 NFTL_findfreeblock( struct NFTLrecord *thisNFTL, int desperate ) +/* NFTL_findfreeblock: Find a free Erase Unit on the NFTL partition. This function is used + * when the give Virtual Unit Chain + */ +static u16 NFTL_findfreeblock(struct NFTLrecord *nftl, int desperate ) { /* For a given Virtual Unit Chain: find or create a free block and add it to the chain */ /* We're passed the number of the last EUN in the chain, to save us from having to look it up again */ - - u16 pot = thisNFTL->LastFreeEUN; + u16 pot = nftl->LastFreeEUN; int silly = -1; /* Normally, we force a fold to happen before we run out of free blocks completely */ - - if (!desperate && thisNFTL->numfreeEUNs < 2) { - // printk("NFTL_findfreeblock: there are too few free EUNs\n"); + if (!desperate && nftl->numfreeEUNs < 2) { + DEBUG(MTD_DEBUG_LEVEL1, "NFTL_findfreeblock: there are too few free EUNs\n"); return 0xffff; } /* Scan for a free block */ - do { - if (thisNFTL->VirtualUnitTable[pot] == 0xffff) { - thisNFTL->LastFreeEUN = pot; - thisNFTL->numfreeEUNs--; + if (nftl->ReplUnitTable[pot] == BLOCK_FREE) { + nftl->LastFreeEUN = pot; + nftl->numfreeEUNs--; return pot; } - if (++pot > thisNFTL->lastEUN) - pot = le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN); + /* This will probably point to the MediaHdr unit itself, + right at the beginning of the partition. But that unit + (and the backup unit too) should have the UCI set + up so that it's not selected for overwriting */ + if (++pot > nftl->lastEUN) + pot = le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN); if (!silly--) { - printk("Tell Dave he fucked up. LastFreeEUN = %d, FirstEUN = %d\n", - thisNFTL->LastFreeEUN, le16_to_cpu(thisNFTL->MediaHdr.FirstPhysicalEUN)); + printk("Argh! No free blocks found! LastFreeEUN = %d, " + "FirstEUN = %d\n", nftl->LastFreeEUN, + le16_to_cpu(nftl->MediaHdr.FirstPhysicalEUN)); return 0xffff; } - - } while (pot != thisNFTL->LastFreeEUN); + } while (pot != nftl->LastFreeEUN); return 0xffff; } - - - - -static u16 NFTL_foldchain (struct NFTLrecord *thisNFTL, u16 thisVUC, unsigned pendingblock ) +static u16 NFTL_foldchain (struct NFTLrecord *nftl, unsigned thisVUC, unsigned pendingblock ) { - u16 BlockMap[thisNFTL->EraseSize / 512]; - unsigned char BlockLastState[thisNFTL->EraseSize / 512]; - unsigned char BlockFreeFound[thisNFTL->EraseSize / 512]; - u16 thisEUN; + u16 BlockMap[MAX_SECTORS_PER_UNIT]; + unsigned char BlockLastState[MAX_SECTORS_PER_UNIT]; + unsigned char BlockFreeFound[MAX_SECTORS_PER_UNIT]; + unsigned int thisEUN; int block; - int silly = -1; - u16 targetEUN = 0xffff; + int silly; + unsigned int targetEUN; struct nftl_oob oob; int inplace = 1; + size_t retlen; memset(BlockMap, 0xff, sizeof(BlockMap)); memset(BlockFreeFound, 0, sizeof(BlockFreeFound)); - thisEUN = thisNFTL->EUNtable[thisVUC]; + thisEUN = nftl->EUNtable[thisVUC]; - if (thisEUN == 0xffff) { - printk(KERN_WARNING "Trying to fold non-existent Virtual Unit Chain %d!\n", thisVUC); - return 0xffff; + if (thisEUN == BLOCK_NIL) { + printk(KERN_WARNING "Trying to fold non-existent " + "Virtual Unit Chain %d!\n", thisVUC); + return BLOCK_NIL; } /* Scan to find the Erase Unit which holds the actual data for each 512-byte block within the Chain. */ + silly = MAX_LOOPS; + targetEUN = BLOCK_NIL; + while (thisEUN <= nftl->lastEUN ) { + unsigned int status, foldmark; - while( thisEUN <= thisNFTL->lastEUN ) { - size_t retlen; - targetEUN = thisEUN; - - for (block = 0 ; block < thisNFTL->EraseSize / 512; block ++) { - - MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + (block * 512),16 , &retlen, (char *)&oob); - + for (block = 0; block < nftl->EraseSize / 512; block ++) { + MTD_READOOB(nftl->mtd, + (thisEUN * nftl->EraseSize) + (block * 512), + 16 , &retlen, (char *)&oob); if (block == 2) { - if (oob.u.c.WriteInh != 0xffffffff) { - printk("Write Inhibited on EUN %d\n", thisEUN); + foldmark = oob.u.c.FoldMark | oob.u.c.FoldMark1; + if (foldmark == FOLD_MARK_IN_PROGRESS) { + DEBUG(MTD_DEBUG_LEVEL1, + "Write Inhibited on EUN %d\n", thisEUN); inplace = 0; } else { /* There's no other reason not to do inplace, @@ -522,153 +355,139 @@ inplace = 1; } } + status = oob.b.Status | oob.b.Status1; + BlockLastState[block] = status; - BlockLastState[block] = (unsigned char) oob.b.Status & 0xff; - - switch(oob.b.Status) { - case __constant_cpu_to_le16(BLOCK_FREE): - BlockFreeFound[block]=1; + switch(status) { + case SECTOR_FREE: + BlockFreeFound[block] = 1; break; - case __constant_cpu_to_le16(BLOCK_USED): + case SECTOR_USED: if (!BlockFreeFound[block]) BlockMap[block] = thisEUN; else - printk(KERN_WARNING "BLOCK_USED found after BLOCK_FREE in Virtual Unit Chain %d for block %d\n", thisVUC, block); + printk(KERN_WARNING + "SECTOR_USED found after SECTOR_FREE " + "in Virtual Unit Chain %d for block %d\n", + thisVUC, block); break; - case __constant_cpu_to_le16(BLOCK_IGNORE): - case __constant_cpu_to_le16(BLOCK_DELETED): + case SECTOR_IGNORE: + case SECTOR_DELETED: break; default: - printk("Unknown status for block %d in EUN %d: %x\n",block,thisEUN, oob.b.Status); + printk("Unknown status for block %d in EUN %d: %x\n", + block, thisEUN, status); } } if (!silly--) { - printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC); - return 0xffff; + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", + thisVUC); + return BLOCK_NIL; } - thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff; + thisEUN = nftl->ReplUnitTable[thisEUN]; } if (inplace) { /* We're being asked to be a fold-in-place. Check - that all blocks are either present or BLOCK_FREE + that all blocks are either present or SECTOR_FREE in the target block. If not, we're going to have to fold out-of-place anyway. */ - - for (block = 0; block < thisNFTL->EraseSize / 512 ; block++) { - - if (BlockLastState[block] != (unsigned char) (cpu_to_le16(BLOCK_FREE) & 0xff) && + for (block = 0; block < nftl->EraseSize / 512 ; block++) { + if (BlockLastState[block] != SECTOR_FREE && BlockMap[block] != targetEUN) { - DEBUG(1, "Setting inplace to 0. VUC %d, block %d was %x lastEUN, and is in EUN %d (%s) %d\n", - thisVUC, block, BlockLastState[block], BlockMap[block] , BlockMap[block]==targetEUN?"==":"!=", targetEUN); - + DEBUG(MTD_DEBUG_LEVEL1, "Setting inplace to 0. VUC %d, " + "block %d was %x lastEUN, " + "and is in EUN %d (%s) %d\n", + thisVUC, block, BlockLastState[block], + BlockMap[block], + BlockMap[block]== targetEUN ? "==" : "!=", + targetEUN); inplace = 0; break; } } - if ( pendingblock >= (thisVUC * (thisNFTL->EraseSize / 512)) && - pendingblock < ((thisVUC + 1)* (thisNFTL->EraseSize / 512)) && - BlockLastState[ pendingblock - (thisVUC * (thisNFTL->EraseSize / 512))] != - (unsigned char) (cpu_to_le16(BLOCK_FREE) & 0xff)) { - DEBUG(1, "Pending write not free in EUN %d. Folding out of place.\n", targetEUN); + if (pendingblock >= (thisVUC * (nftl->EraseSize / 512)) && + pendingblock < ((thisVUC + 1)* (nftl->EraseSize / 512)) && + BlockLastState[pendingblock - (thisVUC * (nftl->EraseSize / 512))] != + SECTOR_FREE) { + DEBUG(MTD_DEBUG_LEVEL1, "Pending write not free in EUN %d. " + "Folding out of place.\n", targetEUN); inplace = 0; } - } if (!inplace) { - DEBUG(1, "Cannot fold Virtual Unit Chain %d in place. Trying out-of-place\n", thisVUC); + DEBUG(MTD_DEBUG_LEVEL1, "Cannot fold Virtual Unit Chain %d in place. " + "Trying out-of-place\n", thisVUC); /* We need to find a targetEUN to fold into. */ - targetEUN = NFTL_findfreeblock(thisNFTL, 1); - if (targetEUN == 0xffff) { - /* Ouch. Now we're screwed. We need to do a - fold-in-place of another chain to make room - for this one. We need a better way of selecting - which chain to fold, because makefreeblock will - only ask us to fold the same one again. - */ - printk(KERN_WARNING"NFTL_findfreeblock(desperate) returns 0xffff.\n"); - return 0xffff; + targetEUN = NFTL_findfreeblock(nftl, 1); + if (targetEUN == BLOCK_NIL) { + /* Ouch. Now we're screwed. We need to do a + fold-in-place of another chain to make room + for this one. We need a better way of selecting + which chain to fold, because makefreeblock will + only ask us to fold the same one again. + */ + printk(KERN_WARNING + "NFTL_findfreeblock(desperate) returns 0xffff.\n"); + return BLOCK_NIL; } - - } - + } else { + /* We put a fold mark in the chain we are folding only if + we fold in place to help the mount check code. If we do + not fold in place, it is possible to find the valid + chain by selecting the longer one */ + oob.u.c.FoldMark = oob.u.c.FoldMark1 = cpu_to_le16(FOLD_MARK_IN_PROGRESS); + oob.u.c.unused = 0xffffffff; + MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 2 * 512 + 8, + 8, &retlen, (char *)&oob.u); + } /* OK. We now know the location of every block in the Virtual Unit Chain, and the Erase Unit into which we are supposed to be copying. Go for it. */ - - DEBUG(1,"Folding chain %d into unit %d\n", thisVUC, targetEUN); - - for (block = 0; block < thisNFTL->EraseSize / 512 ; block++) { + DEBUG(MTD_DEBUG_LEVEL1,"Folding chain %d into unit %d\n", thisVUC, targetEUN); + for (block = 0; block < nftl->EraseSize / 512 ; block++) { unsigned char movebuf[512]; - struct nftl_oob oob; - size_t retlen; - - memset(&oob, 0xff, sizeof(oob)); + int ret; /* If it's in the target EUN already, or if it's pending write, do nothing */ - if (BlockMap[block] == targetEUN ||(pendingblock == (thisVUC * (thisNFTL->EraseSize / 512) + block))) { - /* Except if it's the first block, in which case we have to - set the UnitNumbers */ - if (block == 0) { - - thisNFTL->mtd->read_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) , - 16, &retlen, (char *)&oob); - - // printk("Setting VirtUnitNum on EUN %d to %x, was %x\n", targetEUN, thisVUC, - // le16_to_cpu(oob.u.a.VirtUnitNum)); - - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC & 0x7fff); - - thisNFTL->mtd->write_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) , - 16, &retlen, (char *)&oob); - } + if (BlockMap[block] == targetEUN || + (pendingblock == (thisVUC * (nftl->EraseSize / 512) + block))) { continue; } - oob.b.Status = BLOCK_USED; - - switch(block) { - case 0: - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC & 0x7fff); - // printk("Setting VirtUnitNum on EUN %d to %x\n", targetEUN, thisVUC); - - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; - break; - - case 1: - oob.u.b.WearInfo = cpu_to_le32(3); // We don't use this, but M-Systems' drivers do - oob.u.b.EraseMark = oob.u.b.EraseMark1 = cpu_to_le16(0x3c69); - break; - - case 2: - default: - oob.u.c.WriteInh = 0xffffffff; - oob.u.c.unused = 0xffffffff; - } - if (thisNFTL->mtd->read_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * BlockMap[block]) + (block * 512), - 512, &retlen, movebuf, (char *)&oob) == -EIO) { - if (thisNFTL->mtd->read_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * BlockMap[block]) + (block * 512), - 512, &retlen, movebuf, (char *)&oob) != -EIO) - printk("Error went away on retry.\n"); - } - - thisNFTL->mtd->write_ecc(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) + (block * 512), - 512, &retlen, movebuf, (char *)&oob); - - - /* FIXME: Add some error checking.... */ - thisNFTL->mtd->write_oob(thisNFTL->mtd, (thisNFTL->EraseSize * targetEUN) + (block * 512), - 16, &retlen, (char *)&oob); - - } + /* copy only in non free block (free blocks can only + happen in case of media errors or deleted blocks) */ + if (BlockMap[block] == BLOCK_NIL) + continue; + + ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + + (block * 512), 512, &retlen, movebuf, (char *)&oob); + if (ret < 0) { + ret = MTD_READECC(nftl->mtd, (nftl->EraseSize * BlockMap[block]) + + (block * 512), 512, &retlen, + movebuf, (char *)&oob); + if (ret != -EIO) + printk("Error went away on retry.\n"); + } + MTD_WRITEECC(nftl->mtd, (nftl->EraseSize * targetEUN) + (block * 512), + 512, &retlen, movebuf, (char *)&oob); + } + + /* add the header so that it is now a valid chain */ + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum + = cpu_to_le16(thisVUC); + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = 0xffff; + + MTD_WRITEOOB(nftl->mtd, (nftl->EraseSize * targetEUN) + 8, + 8, &retlen, (char *)&oob.u); /* OK. We've moved the whole lot into the new block. Now we have to free the original blocks. */ @@ -677,78 +496,37 @@ shouldn't actually lose data in this case. It's just that when we load up on a medium which has duplicate chains, we need to free one of the chains because it's not necessary any more. */ - - - thisEUN = thisNFTL->EUNtable[thisVUC]; + thisEUN = nftl->EUNtable[thisVUC]; + DEBUG(MTD_DEBUG_LEVEL1,"Want to erase\n"); - DEBUG(1,"Want to erase\n"); /* For each block in the old chain (except the targetEUN of course), free it and make it available for future use */ + while (thisEUN <= nftl->lastEUN && thisEUN != targetEUN) { + unsigned int EUNtmp; - while( thisEUN <= thisNFTL->lastEUN && thisEUN != targetEUN) { - size_t retlen; - struct erase_info *instr; - u16 EUNtmp; - - instr = kmalloc(sizeof(struct erase_info), GFP_KERNEL); - if (!instr) { - printk(KERN_WARNING "Out of memory for struct erase_info\n"); - - EUNtmp = thisEUN; - - thisEUN = thisNFTL->ReplUnitTable[EUNtmp] & 0x7fff; - thisNFTL->VirtualUnitTable[EUNtmp] = 0x7fff; - thisNFTL->ReplUnitTable[EUNtmp] = 0xffff; - } else { - memset(instr, 0, sizeof(struct erase_info)); - instr->addr = thisEUN * thisNFTL->EraseSize; - instr->len = thisNFTL->EraseSize; - - MTD_ERASE(thisNFTL->mtd, instr); - /* This is an async interface. Or will be. At which point - this code will break. */ - -#if 0 - MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + 512, 16, &retlen, (char *)&oob); - - printk("After erasing, EUN %d contains: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - thisEUN, oob.b.ECCSig[0], - oob.b.ECCSig[1], - oob.b.ECCSig[2], - oob.b.ECCSig[3], - oob.b.ECCSig[4], - oob.b.ECCSig[5]); -#endif - memset(&oob, 0xff, sizeof(oob)); - oob.u.b.WearInfo = cpu_to_le32(3); - oob.u.b.EraseMark = oob.u.b.EraseMark1 = cpu_to_le16(0x3c69); - - MTD_WRITEOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + 512, 16, &retlen, (char *)&oob); - - EUNtmp = thisEUN; - - thisEUN = thisNFTL->ReplUnitTable[EUNtmp] & 0x7fff; - thisNFTL->VirtualUnitTable[EUNtmp] = 0xffff; - thisNFTL->ReplUnitTable[EUNtmp] = 0xffff; - - thisNFTL->numfreeEUNs++; - - } - - // shifted upwards: thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff; + EUNtmp = nftl->ReplUnitTable[thisEUN]; + if (NFTL_formatblock(nftl, thisEUN) < 0) { + /* could not erase : mark block as reserved + * FixMe: Update Bad Unit Table on disk + */ + nftl->ReplUnitTable[thisEUN] = BLOCK_RESERVED; + } else { + /* correctly erased : mark it as free */ + nftl->ReplUnitTable[thisEUN] = BLOCK_FREE; + nftl->numfreeEUNs++; + } + thisEUN = EUNtmp; } /* Make this the new start of chain for thisVUC */ - thisNFTL->VirtualUnitTable[targetEUN] = thisVUC; - thisNFTL->ReplUnitTable[targetEUN] = 0xffff; + nftl->ReplUnitTable[targetEUN] = BLOCK_NIL; + nftl->EUNtable[thisVUC] = targetEUN; - thisNFTL->EUNtable[thisVUC] = targetEUN; return targetEUN; - } -u16 NFTL_makefreeblock( struct NFTLrecord *thisNFTL , unsigned pendingblock) +u16 NFTL_makefreeblock( struct NFTLrecord *nftl , unsigned pendingblock) { /* This is the part that needs some cleverness applied. For now, I'm doing the minimum applicable to actually @@ -757,23 +535,21 @@ and we also need to do some assessment of the results when the system loses power half-way through the routine. */ - u16 LongestChain = 0; u16 ChainLength = 0, thislen; u16 chain, EUN; - - for (chain=0; chain < thisNFTL->MediaHdr.FormattedSize / thisNFTL->EraseSize; chain++) { - EUN = thisNFTL->EUNtable[chain]; - + for (chain = 0; chain < nftl->MediaHdr.FormattedSize / nftl->EraseSize; chain++) { + EUN = nftl->EUNtable[chain]; thislen = 0; - while (EUN <= thisNFTL->lastEUN) { + while (EUN <= nftl->lastEUN) { thislen++; - // printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN); - EUN = thisNFTL->ReplUnitTable[EUN] & 0x7fff; + //printk("VUC %d reaches len %d with EUN %d\n", chain, thislen, EUN); + EUN = nftl->ReplUnitTable[EUN] & 0x7fff; if (thislen > 0xff00) { - printk("Endless loop in Virtual Chain %d: Unit %x\n", chain, EUN); + printk("Endless loop in Virtual Chain %d: Unit %x\n", + chain, EUN); } if (thislen > 0xff10) { /* Actually, don't return failure. Just ignore this chain and @@ -781,42 +557,38 @@ thislen = 0; break; } - } - if (thislen > ChainLength) { - // printk("New longest chain is %d with length %d\n", chain, thislen); + //printk("New longest chain is %d with length %d\n", chain, thislen); ChainLength = thislen; LongestChain = chain; } - } + } if (ChainLength < 2) { - printk(KERN_WARNING "No Virtual Unit Chains available for folding. Failing request\n"); + printk(KERN_WARNING "No Virtual Unit Chains available for folding. " + "Failing request\n"); return 0xffff; } - - return NFTL_foldchain (thisNFTL, LongestChain, pendingblock); + + return NFTL_foldchain (nftl, LongestChain, pendingblock); } /* NFTL_findwriteunit: Return the unit number into which we can write for this block. Make it available if it isn't already */ - -static inline u16 NFTL_findwriteunit(struct NFTLrecord *thisNFTL, unsigned block) +static inline u16 NFTL_findwriteunit(struct NFTLrecord *nftl, unsigned block) { u16 lastEUN; - u16 thisVUC = block / (thisNFTL->EraseSize / 512); - u16 writeEUN; - unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1); + u16 thisVUC = block / (nftl->EraseSize / 512); + unsigned int writeEUN; + unsigned long blockofs = (block * 512) & (nftl->EraseSize -1); size_t retlen; - int silly = 0x10000, silly2 = 3; + int silly, silly2 = 3; struct nftl_oob oob; - int debug=0; do { - /* Scan the media to find a unit in the VUC which has a free space for the block in question. */ @@ -824,28 +596,30 @@ /* This condition catches the 0x[7f]fff cases, as well as being a sanity check for past-end-of-media access */ - lastEUN = 0xffff; - writeEUN = thisNFTL->EUNtable[thisVUC]; - - while(writeEUN <= thisNFTL->lastEUN) { + lastEUN = BLOCK_NIL; + writeEUN = nftl->EUNtable[thisVUC]; + silly = MAX_LOOPS; + while (writeEUN <= nftl->lastEUN) { struct nftl_bci bci; size_t retlen; - + unsigned int status; + lastEUN = writeEUN; + + MTD_READOOB(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, + 8, &retlen, (char *)&bci); - MTD_READOOB(thisNFTL->mtd, (writeEUN * thisNFTL->EraseSize) - + blockofs,8, &retlen, (char *)&bci); - - if (debug) - printk("Status of block %d in EUN %d is %x\n", block , writeEUN, le16_to_cpu(bci.Status)); + DEBUG(MTD_DEBUG_LEVEL2, "Status of block %d in EUN %d is %x\n", + block , writeEUN, le16_to_cpu(bci.Status)); - switch(bci.Status) { - case __constant_cpu_to_le16(BLOCK_FREE): + status = bci.Status | bci.Status1; + switch(status) { + case SECTOR_FREE: return writeEUN; - case __constant_cpu_to_le16(BLOCK_DELETED): - case __constant_cpu_to_le16(BLOCK_USED): - case __constant_cpu_to_le16(BLOCK_IGNORE): + case SECTOR_DELETED: + case SECTOR_USED: + case SECTOR_IGNORE: break; default: // Invalid block. Don't use it any more. Must implement. @@ -853,35 +627,35 @@ } if (!silly--) { - printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", thisVUC); + printk(KERN_WARNING + "Infinite loop in Virtual Unit Chain 0x%x\n", + thisVUC); return 0xffff; } /* Skip to next block in chain */ - - writeEUN = thisNFTL->ReplUnitTable[writeEUN] & 0x7fff; + writeEUN = nftl->ReplUnitTable[writeEUN]; } /* OK. We didn't find one in the existing chain, or there is no existing chain. */ /* Try to find an already-free block */ + writeEUN = NFTL_findfreeblock(nftl, 0); - writeEUN = NFTL_findfreeblock(thisNFTL, 0); - - if (writeEUN == 0xffff) { + if (writeEUN == BLOCK_NIL) { /* That didn't work - there were no free blocks just waiting to be picked up. We're going to have to fold a chain to make room. */ /* First remember the start of this chain */ - // u16 startEUN = thisNFTL->EUNtable[thisVUC]; + //u16 startEUN = nftl->EUNtable[thisVUC]; //printk("Write to VirtualUnitChain %d, calling makefreeblock()\n", thisVUC); - writeEUN = NFTL_makefreeblock(thisNFTL, block); + writeEUN = NFTL_makefreeblock(nftl, 0xffff); - if (writeEUN == 0xffff) { + if (writeEUN == BLOCK_NIL) { /* Ouch. This should never happen - we should always be able to make some room somehow. If we get here, we've allocated more storage @@ -889,235 +663,223 @@ routine is missing something. */ printk(KERN_WARNING "Cannot make free space.\n"); - return 0xffff; + return BLOCK_NIL; } - // printk("Restarting scan\n"); - lastEUN = 0xffff; - // debug = 1; + //printk("Restarting scan\n"); + lastEUN = BLOCK_NIL; continue; -#if 0 - if (startEUN != thisNFTL->EUNtable[thisVUC]) { - /* The fold operation has moved the chain - that we're looking at. Start the scan again. - */ - continue; - } -#endif } /* We've found a free block. Insert it into the chain. */ - if (lastEUN != 0xffff) { - /* Addition to an existing chain. Make the previous - last block in the chain point to this one. - */ - - //printk("Linking EUN %d to EUN %d in VUC %d\n", - // lastEUN, writeEUN, thisVUC); - /* Both in our cache... */ - thisNFTL->ReplUnitTable[lastEUN] = writeEUN; - - - /* ... and on the flash itself */ - MTD_READOOB(thisNFTL->mtd, (lastEUN * thisNFTL->EraseSize), 16, &retlen, - (char *)&oob); + if (lastEUN != BLOCK_NIL) { + thisVUC |= 0x8000; /* It's a replacement block */ + } else { + /* The first block in a new chain */ + nftl->EUNtable[thisVUC] = writeEUN; + } - oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum = cpu_to_le16(writeEUN); + /* set up the actual EUN we're writing into */ + /* Both in our cache... */ + nftl->ReplUnitTable[writeEUN] = BLOCK_NIL; - MTD_WRITEOOB(thisNFTL->mtd, (lastEUN * thisNFTL->EraseSize), 16, &retlen, - (char *)&oob); + /* ... and on the flash itself */ + MTD_READOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); - thisVUC |= 0x8000; /* It's a replacement block */ - } else { - /* The first block in a new chain */ - thisNFTL->EUNtable[thisVUC] = writeEUN; - } + oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); - /* Now set up the actual EUN we're writing into */ + MTD_WRITEOOB(nftl->mtd, writeEUN * nftl->EraseSize + 8, 8, + &retlen, (char *)&oob.u); + /* we link the new block to the chain only after the + block is ready. It avoids the case where the chain + could point to a free block */ + if (lastEUN != BLOCK_NIL) { /* Both in our cache... */ - thisNFTL->VirtualUnitTable[writeEUN] = thisVUC; - thisNFTL->ReplUnitTable[writeEUN] = 0xffff; - + nftl->ReplUnitTable[lastEUN] = writeEUN; /* ... and on the flash itself */ - MTD_READOOB(thisNFTL->mtd, writeEUN * thisNFTL->EraseSize, 16, - &retlen, (char *)&oob); + MTD_READOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, + 8, &retlen, (char *)&oob.u); - oob.u.a.VirtUnitNum = oob.u.a.SpareVirtUnitNum = cpu_to_le16(thisVUC); + oob.u.a.ReplUnitNum = oob.u.a.SpareReplUnitNum + = cpu_to_le16(writeEUN); - MTD_WRITEOOB(thisNFTL->mtd, writeEUN * thisNFTL->EraseSize, 16, - &retlen, (char *)&oob); + MTD_WRITEOOB(nftl->mtd, (lastEUN * nftl->EraseSize) + 8, + 8, &retlen, (char *)&oob.u); + } return writeEUN; } while (silly2--); - printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", thisVUC); + printk(KERN_WARNING "Error folding to make room for Virtual Unit Chain 0x%x\n", + thisVUC); return 0xffff; } -static int NFTL_writeblock(struct NFTLrecord *thisNFTL, unsigned block, - char *buffer) +static int NFTL_writeblock(struct NFTLrecord *nftl, unsigned block, char *buffer) { u16 writeEUN; - unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1); + unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); size_t retlen; - u16 eccbuf[8]; + u8 eccbuf[6]; - // if (thisEUN == 0xffff) thisEUN = 0; + writeEUN = NFTL_findwriteunit(nftl, block); - writeEUN = NFTL_findwriteunit(thisNFTL, block); - -// printk("writeblock(%d): Write to Unit %d\n", block, writeEUN); - - if (writeEUN == 0xffff) { - printk(KERN_WARNING "NFTL_writeblock(): Cannot find block to write to\n"); + if (writeEUN == BLOCK_NIL) { + printk(KERN_WARNING + "NFTL_writeblock(): Cannot find block to write to\n"); /* If we _still_ haven't got a block to use, we're screwed */ return 1; } -// printk("Writing block %lx to EUN %x\n",block, writeEUN); - - thisNFTL->mtd->write_ecc(thisNFTL->mtd, - (writeEUN * thisNFTL->EraseSize) + blockofs, - 512, &retlen, (char *)buffer, (char *)eccbuf); - eccbuf[3] = BLOCK_USED; - eccbuf[4] = eccbuf[5] = eccbuf[6] = eccbuf[7] = 0xffff; - - thisNFTL->mtd->write_oob(thisNFTL->mtd, - (writeEUN * thisNFTL->EraseSize) + blockofs, - 16, &retlen, (char *)eccbuf); + MTD_WRITEECC(nftl->mtd, (writeEUN * nftl->EraseSize) + blockofs, + 512, &retlen, (char *)buffer, (char *)eccbuf); + /* no need to write SECTOR_USED flags since they are written in mtd_writeecc */ return 0; } - #endif /* CONFIG_NFTL_RW */ -static int NFTL_readblock(struct NFTLrecord *thisNFTL, - unsigned block, char *buffer) +static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer) { - u16 lastgoodEUN = 0xffff; - u16 thisEUN = thisNFTL->EUNtable[block / (thisNFTL->EraseSize / 512)]; - unsigned long blockofs = (block * 512) & (thisNFTL->EraseSize -1); - - int silly = -1; + u16 lastgoodEUN; + u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)]; + unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1); + unsigned int status; + int silly = MAX_LOOPS; + size_t retlen; + struct nftl_bci bci; + + lastgoodEUN = BLOCK_NIL; + + if (thisEUN != BLOCK_NIL) { + while (thisEUN < nftl->nb_blocks) { + if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs, + 8, &retlen, (char *)&bci) < 0) + status = SECTOR_IGNORE; + else + status = bci.Status | bci.Status1; + + switch (status) { + case SECTOR_FREE: + /* no modification of a sector should follow a free sector */ + goto the_end; + case SECTOR_DELETED: + lastgoodEUN = BLOCK_NIL; + break; + case SECTOR_USED: + lastgoodEUN = thisEUN; + break; + case SECTOR_IGNORE: + break; + default: + printk("Unknown status for block %d in EUN %d: %x\n", + block, thisEUN, status); + break; + } - if (thisEUN == 0xffff) thisEUN = 0; - - while(thisEUN && (thisEUN & 0x7fff) != 0x7fff) { - struct nftl_bci bci; - size_t retlen; - - MTD_READOOB(thisNFTL->mtd, (thisEUN * thisNFTL->EraseSize) + blockofs,8, &retlen, (char *)&bci); - - switch(bci.Status) { - case __constant_cpu_to_le16(BLOCK_FREE): - thisEUN = 0; - break; - case __constant_cpu_to_le16(BLOCK_USED): - lastgoodEUN = thisEUN; - break; - case __constant_cpu_to_le16(BLOCK_IGNORE): - case __constant_cpu_to_le16(BLOCK_DELETED): - break; - default: - printk("Unknown status for block %d in EUN %d: %x\n",block,thisEUN, bci.Status); + if (!silly--) { + printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n", + block / (nftl->EraseSize / 512)); + return 1; + } + thisEUN = nftl->ReplUnitTable[thisEUN]; } + } - if (!silly--) { - printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",block / (thisNFTL->EraseSize / 512)); - return 1; - } - if (thisEUN) - thisEUN = thisNFTL->ReplUnitTable[thisEUN] & 0x7fff; - } - if (lastgoodEUN == 0xffff) { + the_end: + if (lastgoodEUN == BLOCK_NIL) { + /* the requested block is not on the media, return all 0x00 */ memset(buffer, 0, 512); } else { - loff_t ptr = (lastgoodEUN * thisNFTL->EraseSize) + blockofs; + loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs; size_t retlen; u_char eccbuf[6]; - thisNFTL->mtd->read_ecc(thisNFTL->mtd, ptr, 512, &retlen, buffer, eccbuf); + if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf)) + return -EIO; } return 0; } - -static int nftl_ioctl(struct inode * inode, struct file * file, - unsigned int cmd, unsigned long arg) +static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct NFTLrecord *thisNFTL; + struct NFTLrecord *nftl; - thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; - - if (!thisNFTL) return -EINVAL; + nftl = NFTLs[MINOR(inode->i_rdev) / 16]; + if (!nftl) return -EINVAL; switch (cmd) { case HDIO_GETGEO: { struct hd_geometry g; - g.heads = thisNFTL->heads; - g.sectors = thisNFTL->sectors; - g.cylinders = thisNFTL->cylinders; + g.heads = nftl->heads; + g.sectors = nftl->sectors; + g.cylinders = nftl->cylinders; g.start = part_table[MINOR(inode->i_rdev)].start_sect; return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0; } case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; + if (!arg) return -EINVAL; return put_user(part_table[MINOR(inode->i_rdev)].nr_sects, (long *) arg); case BLKFLSBUF: - if(!capable(CAP_SYS_ADMIN)) return -EACCES; + if (!capable(CAP_SYS_ADMIN)) return -EACCES; fsync_dev(inode->i_rdev); invalidate_buffers(inode->i_rdev); - if (thisNFTL->mtd->sync) - thisNFTL->mtd->sync(thisNFTL->mtd); + if (nftl->mtd->sync) + nftl->mtd->sync(nftl->mtd); return 0; case BLKRRPART: if (!capable(CAP_SYS_ADMIN)) return -EACCES; - if (thisNFTL->usecount > 1) { - // printk("Use count %d\n", thisNFTL->usecount); - return -EBUSY; - } + if (nftl->usecount > 1) return -EBUSY; #if LINUX_VERSION_CODE < 0x20328 - resetup_one_dev(&nftl_gendisk, MINOR(inode->i_dev) / 16); + resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) / 16); #else - grok_partitions(&nftl_gendisk, MINOR(inode->i_dev) / 16, 1<<4, thisNFTL->nr_sects); + grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) / 16, + 1<<4, nftl->nr_sects); #endif return 0; - - // RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ + +#if (LINUX_VERSION_CODE < 0x20303) + RO_IOCTLS(inode->i_rdev, arg); /* ref. linux/blk.h */ +#else + case BLKROSET: + case BLKROGET: + case BLKSSZGET: + return blk_ioctl(inode->i_rdev, cmd, arg); +#endif + default: return -EINVAL; } } - void nftl_request(RQFUNC_ARG) { unsigned int dev, block, nsect; - struct NFTLrecord *thisNFTL; + struct NFTLrecord *nftl; char *buffer; struct request *req; int res; while (1) { INIT_REQUEST; /* blk.h */ - req = CURRENT; -#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK - blkdev_dequeue_request(req); - spin_unlock_irq(&io_request_lock); -#else - req = CURRENT; -#endif - DEBUG(2,"NFTL_request\n"); - DEBUG(3,"NFTL %d request, %lx, %lx", req->cmd, - req->sector, req->current_nr_sectors); + /* We can do this because the generic code knows not to + touch the request at the head of the queue */ + spin_unlock_irq(&io_request_lock); + + DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n"); + DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n", + (req->cmd == READ) ? "Read " : "Write", + req->sector, req->current_nr_sectors); + dev = MINOR(req->rq_dev); block = req->sector; nsect = req->current_nr_sectors; @@ -1125,21 +887,23 @@ res = 1; /* succeed */ if (dev >= MAX_NFTLS * 16) { - printk("fl: bad minor number: device=%s\n", + /* there is no such partition */ + printk("nftl: bad minor number: device = %s\n", kdevname(req->rq_dev)); res = 0; /* fail */ goto repeat; } - thisNFTL = NFTLs[dev / 16]; - DEBUG(3,"Waiting for mutex\n"); - down(&thisNFTL->mutex); - DEBUG(3,"Got mutex\n"); - - if (block + nsect >= part_table[dev].nr_sects) { - printk("nftl%c%d: bad access: block=%d, count=%d\n", + nftl = NFTLs[dev / 16]; + DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n"); + down(&nftl->mutex); + DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n"); + + if (block + nsect > part_table[dev].nr_sects) { + /* access past the end of device */ + printk("nftl%c%d: bad access: block = %d, count = %d\n", (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect); - up(&thisNFTL->mutex); + up(&nftl->mutex); res = 0; /* fail */ goto repeat; } @@ -1147,75 +911,80 @@ block += part_table[dev].start_sect; if (req->cmd == READ) { - DEBUG(2,"NFTL read\n"); - for ( ; nsect > 0; nsect-- , block++, buffer+= 512) { + DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x " + "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors); + + for ( ; nsect > 0; nsect-- , block++, buffer += 512) { /* Read a single sector to req->buffer + (512 * i) */ - - if (NFTL_readblock(thisNFTL, block, buffer)) { - DEBUG(2,"NFTL read request failed\n"); - up(&thisNFTL->mutex); + if (NFTL_readblock(nftl, block, buffer)) { + DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n"); + up(&nftl->mutex); res = 0; goto repeat; } } - DEBUG(2,"NFTL read request completed OK\n"); - up(&thisNFTL->mutex); + + DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n"); + up(&nftl->mutex); goto repeat; - } - else if (req->cmd == WRITE) { - DEBUG(2,"NFTL write request of 0x%x sectors @ %x (req->nr_sectors == %lx\n",nsect, block, req->nr_sectors); + } else if (req->cmd == WRITE) { + DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x " + "(req->nr_sectors == %lx)\n", nsect, block, + req->nr_sectors); #ifdef CONFIG_NFTL_RW - for ( ; nsect > 0; nsect-- , block++, buffer+= 512) { + for ( ; nsect > 0; nsect-- , block++, buffer += 512) { /* Read a single sector to req->buffer + (512 * i) */ - - if (NFTL_writeblock(thisNFTL, block, buffer)) { - DEBUG(1,"NFTL write request failed\n"); - - up(&thisNFTL->mutex); + if (NFTL_writeblock(nftl, block, buffer)) { + DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n"); + up(&nftl->mutex); res = 0; goto repeat; } } - DEBUG(2,"NFTL write request completed OK\n"); + DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n"); #else - res=0; /* Writes always fail */ + res = 0; /* Writes always fail */ #endif /* CONFIG_NFTL_RW */ - up(&thisNFTL->mutex); + up(&nftl->mutex); goto repeat; - } - else { - DEBUG(0,"NFTL ??? request\n"); - up(&thisNFTL->mutex); + } else { + DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n"); + up(&nftl->mutex); res = 0; goto repeat; } repeat: - DEBUG(3,"end_request(%d)\n", res); -#ifdef WE_KNOW_WTF_THIS_DOES_NOT_WORK + DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res); spin_lock_irq(&io_request_lock); - nftl_end_request(req, res); -#else end_request(res); -#endif } } static int nftl_open(struct inode *ip, struct file *fp) { + int nftlnum = MINOR(ip->i_rdev) / 16; struct NFTLrecord *thisNFTL; - thisNFTL = NFTLs[MINOR(ip->i_rdev) / 16]; + thisNFTL = NFTLs[nftlnum]; - DEBUG(2,"NFTL_open\n"); + DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n"); +#ifdef CONFIG_KMOD + if (!thisNFTL && nftlnum == 0) { + request_module("docprobe"); + thisNFTL = NFTLs[nftlnum]; + } +#endif if (!thisNFTL) { - DEBUG(2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", - MINOR(ip->i_rdev) / 16,ip->i_rdev,ip, fp); + DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", + nftlnum, ip->i_rdev, ip, fp); return -ENODEV; } + #ifndef CONFIG_NFTL_RW if (fp->f_mode & FMODE_WRITE) - return -EROFS; + return -EROFS; #endif /* !CONFIG_NFTL_RW */ + thisNFTL->usecount++; MOD_INC_USE_COUNT; if (!get_mtd_device(thisNFTL->mtd, -1)) { @@ -1233,8 +1002,8 @@ thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16]; - DEBUG(2, "NFTL_release\n"); - + DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n"); + fsync_dev(inode->i_rdev); if (sb) invalidate_inodes(sb); @@ -1251,19 +1020,19 @@ } #if LINUX_VERSION_CODE < 0x20326 static struct file_operations nftl_fops = { - read: block_read, - write: block_write, - ioctl: nftl_ioctl, - open: nftl_open, - release: nftl_release, - fsync: block_fsync, + read: block_read, + write: block_write, + ioctl: nftl_ioctl, + open: nftl_open, + release: nftl_release, + fsync: block_fsync, }; #else static struct block_device_operations nftl_fops = { - open: nftl_open, - release: nftl_release, - ioctl: nftl_ioctl + open: nftl_open, + release: nftl_release, + ioctl: nftl_ioctl }; #endif @@ -1275,39 +1044,39 @@ * ****************************************************************************/ -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_nftl init_module #define cleanup_nftl cleanup_module #endif -#define __exit -#endif static struct mtd_notifier nftl_notifier = {NFTL_notify_add, NFTL_notify_remove, NULL}; - /* static int __init init_nftl(void) */ int __init init_nftl(void) { int i; - printk(KERN_NOTICE "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n"); + printk(KERN_NOTICE + "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n"); #ifdef PRERELEASE - printk(KERN_INFO"$Id: nftl.c,v 1.36 2000/07/13 14:14:20 dwmw2 Exp $\n"); + printk(KERN_INFO"$Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $\n"); #endif - if (register_blkdev(NFTL_MAJOR, "nftl", &nftl_fops)){ - printk("unable to register NFTL block device\n"); + if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){ + printk("unable to register NFTL block device on major %d\n", MAJOR_NR); + return -EBUSY; } else { #if LINUX_VERSION_CODE < 0x20320 - blk_dev[MAJOR_NR].request_fn = nftl_request; + blk_dev[MAJOR_NR].request_fn = nftl_request; #else - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request); #endif - for (i=0; i < 256 ; i++) { + /* set block size to 1kB each */ + for (i = 0; i < 256; i++) { nftl_blocksizes[i] = 1024; } - blksize_size[NFTL_MAJOR] = nftl_blocksizes; + blksize_size[MAJOR_NR] = nftl_blocksizes; + nftl_gendisk.next = gendisk_head; gendisk_head = &nftl_gendisk; } @@ -1319,25 +1088,25 @@ static void __exit cleanup_nftl(void) { - struct gendisk *gd, **gdp; + struct gendisk *gd, **gdp; - unregister_mtd_user(&nftl_notifier); - - unregister_blkdev(NFTL_MAJOR, "nftl"); + unregister_mtd_user(&nftl_notifier); + unregister_blkdev(MAJOR_NR, "nftl"); + #if LINUX_VERSION_CODE < 0x20320 - blk_dev[MAJOR_NR].request_fn = 0; + blk_dev[MAJOR_NR].request_fn = 0; #else - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); + blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); #endif - for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) - if (*gdp == &nftl_gendisk) { - gd = *gdp; *gdp = gd->next; - break; - } - + + /* remove ourself from generic harddisk list + FIXME: why can't I found this partition on /proc/partition */ + for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next)) + if (*gdp == &nftl_gendisk) { + gd = *gdp; *gdp = gd->next; + break; + } } -#if LINUX_VERSION_CODE > 0x20300 module_init(init_nftl); module_exit(cleanup_nftl); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/nftlmount.c linux/drivers/mtd/nftlmount.c --- v2.4.0-test11/linux/drivers/mtd/nftlmount.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/mtd/nftlmount.c Mon Dec 11 14:57:58 2000 @@ -0,0 +1,678 @@ +/* + * NFTL mount code with extensive checks + * + * Author: Fabrice Bellard (fabrice.bellard@netgem.com) + * Copyright (C) 2000 Netgem S.A. + * + * $Id: nftlmount.c,v 1.11 2000/11/17 12:24:09 ollie Exp $ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 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 +#include +#include +#include +#include +#include +#include + +#define SECTORSIZE 512 + +/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the + * various device information of the NFTL partition and Bad Unit Table. Update + * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] + * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c + */ +static int find_boot_record(struct NFTLrecord *nftl) +{ + struct nftl_uci1 h1; + struct nftl_oob oob; + unsigned int block, boot_record_count; + int retlen; + u8 buf[SECTORSIZE]; + struct NFTLMediaHeader *mh = &nftl->MediaHdr; + + nftl->MediaUnit = BLOCK_NIL; + nftl->SpareMediaUnit = BLOCK_NIL; + boot_record_count = 0; + + /* search for a valid boot record */ + for (block = 0; block < nftl->nb_blocks; block++) { + unsigned int erase_mark; + + /* read ANAND header. To be safer with BIOS, also use erase mark as discriminant */ + if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, + 8, &retlen, (char *)&h1) < 0) + continue; + + erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); + if (erase_mark != ERASE_MARK) + continue; + + if (MTD_READECC(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, + &retlen, buf, (char *)&oob) < 0) + continue; + + memcpy(mh, buf, sizeof(struct NFTLMediaHeader)); + if (memcmp(mh->DataOrgID, "ANAND", 6) == 0) { + /* first boot record */ + if (boot_record_count == 0) { + unsigned int i; + /* header found : read the bad block table data */ + if (mh->UnitSizeFactor != 0xff) { + printk("Sorry, we don't support UnitSizeFactor " + "of != 1 yet\n"); + goto ReplUnitTable; + } + + nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); + if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) + goto ReplUnitTable; /* small consistency check */ + + nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize; + if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) + goto ReplUnitTable; /* small consistency check */ + + /* FixMe: with bad blocks, the total size available is not FormattedSize any + more !!! */ + nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); + nftl->MediaUnit = block; + + /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */ + for (i = 0; i < nftl->nb_blocks; i++) { + if ((i & (SECTORSIZE - 1)) == 0) { + /* read one sector for every SECTORSIZE of blocks */ + if (MTD_READECC(nftl->mtd, block * nftl->EraseSize + + i + SECTORSIZE, SECTORSIZE, + &retlen, buf, (char *)&oob) < 0) + goto ReplUnitTable; + } + /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */ + if (buf[i & (SECTORSIZE - 1)] != 0xff) + nftl->ReplUnitTable[i] = BLOCK_RESERVED; + } + + boot_record_count++; + } else if (boot_record_count == 1) { + nftl->SpareMediaUnit = block; + boot_record_count++; + break; + } + } + ReplUnitTable: + } + + if (boot_record_count == 0) { + /* no boot record found */ + return -1; + } else { + return 0; + } +} + +static int memcmpb(void *a, int c, int n) +{ + int i; + for (i = 0; i < n; i++) { + if (c != ((unsigned char *)a)[i]) + return 1; + } + return 0; +} + +/* check_free_sector: check if a free sector is actually FREE, i.e. All 0xff in data and oob area */ +static int check_free_sectors(struct NFTLrecord *nftl, unsigned int address, int len, + int check_oob) +{ + int i, retlen; + u8 buf[SECTORSIZE]; + + for (i = 0; i < len; i += SECTORSIZE) { + /* we want to read the sector without ECC check here since a free + sector does not have ECC syndrome on it yet */ + if (MTD_READ(nftl->mtd, address, SECTORSIZE, &retlen, buf) < 0) + return -1; + if (memcmpb(buf, 0xff, SECTORSIZE) != 0) + return -1; + + if (check_oob) { + if (MTD_READOOB(nftl->mtd, address, nftl->mtd->oobsize, + &retlen, buf) < 0) + return -1; + if (memcmpb(buf, 0xff, nftl->mtd->oobsize) != 0) + return -1; + } + address += SECTORSIZE; + } + + return 0; +} + +/* NFTL_format: format a Erase Unit by erasing ALL Erase Zones in the Erase Unit and + * Update NFTL metadata. Each erase operation is checked with check_free_sectors + * + * Return: 0 when succeed, -1 on error. + * + * ToDo: 1. Is it neceressary to check_free_sector after erasing ?? + * 2. UnitSizeFactor != 0xFF + */ +int NFTL_formatblock(struct NFTLrecord *nftl, int block) +{ + int retlen; + unsigned int nb_erases, erase_mark; + struct nftl_uci1 uci; + struct erase_info *instr = &nftl->instr; + + /* Read the Unit Control Information #1 for Wear-Leveling */ + if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, + 8, &retlen, (char *)&uci) < 0) + goto default_uci1; + + erase_mark = le16_to_cpu ((uci.EraseMark | uci.EraseMark1)); + if (erase_mark != ERASE_MARK) { + default_uci1: + uci.EraseMark = cpu_to_le16(ERASE_MARK); + uci.EraseMark1 = cpu_to_le16(ERASE_MARK); + uci.WearInfo = cpu_to_le32(0); + } + + memset(instr, 0, sizeof(struct erase_info)); + + /* XXX: use async erase interface, XXX: test return code */ + instr->addr = block * nftl->EraseSize; + instr->len = nftl->EraseSize; + MTD_ERASE(nftl->mtd, instr); + + if (instr->state == MTD_ERASE_FAILED) { + /* could not format, FixMe: We should update the BadUnitTable + both in memory and on disk */ + printk("Error while formatting block %d\n", block); + return -1; + } else { + /* increase and write Wear-Leveling info */ + nb_erases = le32_to_cpu(uci.WearInfo); + nb_erases++; + + /* wrap (almost impossible with current flashs) or free block */ + if (nb_erases == 0) + nb_erases = 1; + + /* check the "freeness" of Erase Unit before updating metadata + * FixMe: is this check really necessary ? since we have check the + * return code after the erase operation. */ + if (check_free_sectors(nftl, instr->addr, nftl->EraseSize, 1) != 0) + return -1; + + uci.WearInfo = le32_to_cpu(nb_erases); + if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, + &retlen, (char *)&uci) < 0) + return -1; + return 0; + } +} + +/* check_sectors_in_chain: Check that each sector of a Virtual Unit Chain is correct. + * Mark as 'IGNORE' each incorrect sector. This check is only done if the chain + * was being folded when NFTL was interrupted. + * + * The check_free_sectors in this function is neceressary. There is a possible + * situation that after writing the Data area, the Block Control Information is + * not updated according (due to power failure or something) which leaves the block + * in an umconsistent state. So we have to check if a block is really FREE in this + * case. */ +static void check_sectors_in_chain(struct NFTLrecord *nftl, unsigned int first_block) +{ + unsigned int block, i, status; + struct nftl_bci bci; + int sectors_per_block, retlen; + + sectors_per_block = nftl->EraseSize / SECTORSIZE; + block = first_block; + for (;;) { + for (i = 0; i < sectors_per_block; i++) { + if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i * SECTORSIZE, + 8, &retlen, (char *)&bci) < 0) + status = SECTOR_IGNORE; + else + status = bci.Status | bci.Status1; + + switch(status) { + case SECTOR_FREE: + /* verify that the sector is really free. If not, mark + as ignore */ + if (memcmpb(&bci, 0xff, 8) != 0 || + check_free_sectors(nftl, block * nftl->EraseSize + i * SECTORSIZE, + SECTORSIZE, 0) != 0) { + printk("Incorrect free sector %d in block %d: " + "marking it as ignored\n", + i, block); + + /* sector not free actually : mark it as SECTOR_IGNORE */ + bci.Status = SECTOR_IGNORE; + bci.Status1 = SECTOR_IGNORE; + MTD_WRITEOOB(nftl->mtd, + block * nftl->EraseSize + i * SECTORSIZE, + 8, &retlen, (char *)&bci); + } + break; + default: + break; + } + } + + /* proceed to next Erase Unit on the chain */ + block = nftl->ReplUnitTable[block]; + if (!(block == BLOCK_NIL || block < nftl->nb_blocks)) + printk("incorrect ReplUnitTable[] : %d\n", block); + if (block == BLOCK_NIL || block >= nftl->nb_blocks) + break; + } +} + +/* calc_chain_lenght: Walk through a Virtual Unit Chain and estimate chain length */ +static int calc_chain_length(struct NFTLrecord *nftl, unsigned int first_block) +{ + unsigned int length = 0, block = first_block; + + for (;;) { + length++; + /* avoid infinite loops, although this is guaranted not to + happen because of the previous checks */ + if (length >= nftl->nb_blocks) { + printk("nftl: length too long %d !\n", length); + break; + } + + block = nftl->ReplUnitTable[block]; + if (!(block == BLOCK_NIL || block < nftl->nb_blocks)) + printk("incorrect ReplUnitTable[] : %d\n", block); + if (block == BLOCK_NIL || block >= nftl->nb_blocks) + break; + } + return length; +} + +/* format_chain: Format an invalid Virtual Unit chain. It frees all the Erase Units in a + * Virtual Unit Chain, i.e. all the units are disconnected. + * + * It is not stricly correct to begin from the first block of the chain because + * if we stop the code, we may see again a valid chain if there was a first_block + * flag in a block inside it. But is it really a problem ? + * + * FixMe: Figure out what the last statesment means. What if power failure when we are + * in the for (;;) loop formatting blocks ?? + */ +static void format_chain(struct NFTLrecord *nftl, unsigned int first_block) +{ + unsigned int block = first_block, block1; + + printk("Formatting chain at block %d\n", first_block); + + for (;;) { + block1 = nftl->ReplUnitTable[block]; + + printk("Formatting block %d\n", block); + if (NFTL_formatblock(nftl, block) < 0) { + /* cannot format !!!! Mark it as Bad Unit, + FixMe: update the BadUnitTable on disk */ + nftl->ReplUnitTable[block] = BLOCK_RESERVED; + } else { + nftl->ReplUnitTable[block] = BLOCK_FREE; + } + + /* goto next block on the chain */ + block = block1; + + if (!(block == BLOCK_NIL || block < nftl->nb_blocks)) + printk("incorrect ReplUnitTable[] : %d\n", block); + if (block == BLOCK_NIL || block >= nftl->nb_blocks) + break; + } +} + +/* check_and_mark_free_block: Verify that a block is free in the NFTL sense (valid erase mark) or + * totally free (only 0xff). + * + * Definition: Free Erase Unit -- A properly erased/formatted Free Erase Unit should have meet the + * following critia: + * 1. */ +static int check_and_mark_free_block(struct NFTLrecord *nftl, int block) +{ + struct nftl_uci1 h1; + unsigned int erase_mark; + int i, retlen; + unsigned char buf[SECTORSIZE]; + + /* check erase mark. */ + if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, + &retlen, (char *)&h1) < 0) + return -1; + + erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); + if (erase_mark != ERASE_MARK) { + /* if no erase mark, the block must be totally free. This is + possible in two cases : empty filsystem or interrupted erase (very unlikely) */ + if (check_free_sectors (nftl, block * nftl->EraseSize, nftl->EraseSize, 1) != 0) + return -1; + + /* free block : write erase mark */ + h1.EraseMark = cpu_to_le16(ERASE_MARK); + h1.EraseMark1 = cpu_to_le16(ERASE_MARK); + h1.WearInfo = cpu_to_le32(0); + if (MTD_WRITEOOB(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, 8, + &retlen, (char *)&h1) < 0) + return -1; + } else { +#if 0 + /* if erase mark present, need to skip it when doing check */ + for (i = 0; i < nftl->EraseSize; i += SECTORSIZE) { + /* check free sector */ + if (check_free_sectors (nftl, block * nftl->EraseSize + i, + SECTORSIZE, 0) != 0) + return -1; + + if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + i, + 16, &retlen, buf) < 0) + return -1; + if (i == SECTORSIZE) { + /* skip erase mark */ + if (memcmpb(buf, 0xff, 8)) + return -1; + } else { + if (memcmpb(buf, 0xff, 16)) + return -1; + } + } +#endif + } + + return 0; +} + +/* get_fold_mark: Read fold mark from Unit Control Information #2, we use FOLD_MARK_IN_PROGRESS + * to indicate that we are in the progression of a Virtual Unit Chain folding. If the UCI #2 + * is FOLD_MARK_IN_PROGRESS when mounting the NFTL, the (previous) folding process is interrupted + * for some reason. A clean up/check of the VUC is neceressary in this case. + * + * WARNING: return 0 if read error + */ +static int get_fold_mark(struct NFTLrecord *nftl, unsigned int block) +{ + struct nftl_uci2 uci; + int retlen; + + if (MTD_READOOB(nftl->mtd, block * nftl->EraseSize + 2 * SECTORSIZE + 8, + 8, &retlen, (char *)&uci) < 0) + return 0; + + return le16_to_cpu((uci.FoldMark | uci.FoldMark1)); +} + +int NFTL_mount(struct NFTLrecord *s) +{ + int i; + unsigned int first_logical_block, logical_block, rep_block, nb_erases, erase_mark; + unsigned int block, first_block, is_first_block; + int chain_length, do_format_chain; + struct nftl_uci0 h0; + struct nftl_uci1 h1; + int retlen; + + /* XXX: will be suppressed */ + s->lastEUN = s->nb_blocks - 1; + + /* memory alloc */ + s->EUNtable = kmalloc(s->nb_blocks * sizeof(u16), GFP_KERNEL); + s->ReplUnitTable = kmalloc(s->nb_blocks * sizeof(u16), GFP_KERNEL); + if (!s->EUNtable || !s->ReplUnitTable) { + fail: + if (s->EUNtable) + kfree(s->EUNtable); + if (s->ReplUnitTable) + kfree(s->ReplUnitTable); + return -1; + } + + /* mark all blocks as potentially containing data */ + for (i = 0; i < s->nb_blocks; i++) { + s->ReplUnitTable[i] = BLOCK_NOTEXPLORED; + } + + /* search for NFTL MediaHeader and Spare NFTL Media Header */ + if (find_boot_record(s) < 0) { + printk("Could not find valid boot record\n"); + goto fail; + } + + /* mark the bios blocks (blocks before NFTL MediaHeader) as reserved */ + for (i = 0; i < s->nb_boot_blocks; i++) + s->ReplUnitTable[i] = BLOCK_RESERVED; + + /* also mark the boot records (NFTL MediaHeader) blocks as reserved */ + if (s->MediaUnit != BLOCK_NIL) + s->ReplUnitTable[s->MediaUnit] = BLOCK_RESERVED; + if (s->SpareMediaUnit != BLOCK_NIL) + s->ReplUnitTable[s->SpareMediaUnit] = BLOCK_RESERVED; + + /* init the logical to physical table */ + for (i = 0; i < s->nb_blocks; i++) { + s->EUNtable[i] = BLOCK_NIL; + } + + /* first pass : explore each block chain */ + first_logical_block = 0; + for (first_block = 0; first_block < s->nb_blocks; first_block++) { + /* if the block was not already explored, we can look at it */ + if (s->ReplUnitTable[first_block] == BLOCK_NOTEXPLORED) { + block = first_block; + chain_length = 0; + do_format_chain = 0; + + for (;;) { + /* read the block header. If error, we format the chain */ + if (MTD_READOOB(s->mtd, block * s->EraseSize + 8, 8, + &retlen, (char *)&h0) < 0 || + MTD_READOOB(s->mtd, block * s->EraseSize + SECTORSIZE + 8, 8, + &retlen, (char *)&h1) < 0) { + s->ReplUnitTable[block] = BLOCK_NIL; + do_format_chain = 1; + break; + } + + logical_block = le16_to_cpu ((h0.VirtUnitNum | h0.SpareVirtUnitNum)); + rep_block = le16_to_cpu ((h0.ReplUnitNum | h0.SpareReplUnitNum)); + nb_erases = le32_to_cpu (h1.WearInfo); + erase_mark = le16_to_cpu ((h1.EraseMark | h1.EraseMark1)); + + is_first_block = !(logical_block >> 15); + logical_block = logical_block & 0x7fff; + + /* invalid/free block test */ + if (erase_mark != ERASE_MARK || logical_block >= s->nb_blocks) { + if (chain_length == 0) { + /* if not currently in a chain, we can handle it safely */ + if (check_and_mark_free_block(s, block) < 0) { + /* not really free: format it */ + printk("Formatting block %d\n", block); + if (NFTL_formatblock(s, block) < 0) { + /* could not format: reserve the block */ + s->ReplUnitTable[block] = BLOCK_RESERVED; + } else { + s->ReplUnitTable[block] = BLOCK_FREE; + } + } else { + /* free block: mark it */ + s->ReplUnitTable[block] = BLOCK_FREE; + } + /* directly examine the next block. */ + goto examine_ReplUnitTable; + } else { + /* the block was in a chain : this is bad. We + must format all the chain */ + printk("Block %d: free but referenced in chain %d\n", + block, first_block); + s->ReplUnitTable[block] = BLOCK_NIL; + do_format_chain = 1; + break; + } + } + + /* we accept only first blocks here */ + if (chain_length == 0) { + /* this block is not the first block in chain : + ignore it, it will be included in a chain + later, or marked as not explored */ + if (!is_first_block) + goto examine_ReplUnitTable; + first_logical_block = logical_block; + } else { + if (logical_block != first_logical_block) { + printk("Block %d: incorrect logical block: %d expected: %d\n", + block, logical_block, first_logical_block); + /* the chain is incorrect : we must format it, + but we need to read it completly */ + do_format_chain = 1; + } + if (is_first_block) { + /* we accept that a block is marked as first + block while being last block in a chain + only if the chain is being folded */ + if (get_fold_mark(s, block) != FOLD_MARK_IN_PROGRESS || + rep_block != 0xffff) { + printk("Block %d: incorrectly marked as first block in chain\n", + block); + /* the chain is incorrect : we must format it, + but we need to read it completly */ + do_format_chain = 1; + } else { + printk("Block %d: folding in progress - ignoring first block flag\n", + block); + } + } + } + chain_length++; + if (rep_block == 0xffff) { + /* no more blocks after */ + s->ReplUnitTable[block] = BLOCK_NIL; + break; + } else if (rep_block >= s->nb_blocks) { + printk("Block %d: referencing invalid block %d\n", + block, rep_block); + do_format_chain = 1; + s->ReplUnitTable[block] = BLOCK_NIL; + break; + } else if (s->ReplUnitTable[rep_block] != BLOCK_NOTEXPLORED) { + /* same problem as previous 'is_first_block' test: + we accept that the last block of a chain has + the first_block flag set if folding is in + progress. We handle here the case where the + last block appeared first */ + if (s->ReplUnitTable[rep_block] == BLOCK_NIL && + s->EUNtable[first_logical_block] == rep_block && + get_fold_mark(s, first_block) == FOLD_MARK_IN_PROGRESS) { + /* EUNtable[] will be set after */ + printk("Block %d: folding in progress - ignoring first block flag\n", + rep_block); + s->ReplUnitTable[block] = rep_block; + s->EUNtable[first_logical_block] = BLOCK_NIL; + } else { + printk("Block %d: referencing block %d already in another chain\n", + block, rep_block); + /* XXX: should handle correctly fold in progress chains */ + do_format_chain = 1; + s->ReplUnitTable[block] = BLOCK_NIL; + } + break; + } else { + /* this is OK */ + s->ReplUnitTable[block] = rep_block; + block = rep_block; + } + } + + /* the chain was completely explored. Now we can decide + what to do with it */ + if (do_format_chain) { + /* invalid chain : format it */ + format_chain(s, first_block); + } else { + unsigned int first_block1, chain_to_format, chain_length1; + int fold_mark; + + /* valid chain : get foldmark */ + fold_mark = get_fold_mark(s, first_block); + if (fold_mark == 0) { + /* cannot get foldmark : format the chain */ + printk("Could read foldmark at block %d\n", first_block); + format_chain(s, first_block); + } else { + if (fold_mark == FOLD_MARK_IN_PROGRESS) + check_sectors_in_chain(s, first_block); + + /* now handle the case where we find two chains at the + same virtual address : we select the longer one, + because the shorter one is the one which was being + folded if the folding was not done in place */ + first_block1 = s->EUNtable[first_logical_block]; + if (first_block1 != BLOCK_NIL) { + /* XXX: what to do if same length ? */ + chain_length1 = calc_chain_length(s, first_block1); + printk("Two chains at blocks %d (len=%d) and %d (len=%d)\n", + first_block1, chain_length1, first_block, chain_length); + + if (chain_length >= chain_length1) { + chain_to_format = first_block1; + s->EUNtable[first_logical_block] = first_block; + } else { + chain_to_format = first_block; + } + format_chain(s, chain_to_format); + } else { + s->EUNtable[first_logical_block] = first_block; + } + } + } + } + examine_ReplUnitTable: + } + + /* second pass to format unreferenced blocks and init free block count */ + s->numfreeEUNs = 0; + s->LastFreeEUN = BLOCK_NIL; + + for (block = 0; block < s->nb_blocks; block++) { + if (s->ReplUnitTable[block] == BLOCK_NOTEXPLORED) { + printk("Unreferenced block %d, formatting it\n", block); + if (NFTL_formatblock(s, block) < 0) + s->ReplUnitTable[block] = BLOCK_RESERVED; + else + s->ReplUnitTable[block] = BLOCK_FREE; + } + if (s->ReplUnitTable[block] == BLOCK_FREE) { + s->numfreeEUNs++; + s->LastFreeEUN = block; + } + } + + return 0; +} diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/nora.c linux/drivers/mtd/nora.c --- v2.4.0-test11/linux/drivers/mtd/nora.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/nora.c Mon Dec 11 14:57:58 2000 @@ -1,5 +1,5 @@ /* - * $Id: nora.c,v 1.12 2000/07/13 10:32:33 dwmw2 Exp $ + * $Id: nora.c,v 1.17 2000/12/03 19:32:21 dwmw2 Exp $ * * This is so simple I love it. */ @@ -58,19 +58,17 @@ } struct map_info nora_map = { - "NORA", - WINDOW_SIZE, - 2, - nora_read8, - nora_read16, - nora_read32, - nora_copy_from, - nora_write8, - nora_write16, - nora_write32, - nora_copy_to, - 0, - 0 + name: "NORA", + size: WINDOW_SIZE, + buswidth: 2, + read8: nora_read8, + read16: nora_read16, + read32: nora_read32, + copy_from: nora_copy_from, + write8: nora_write8, + write16: nora_write16, + write32: nora_write32, + copy_to: nora_copy_to }; @@ -140,7 +138,7 @@ { type: MTD_NORFLASH, flags: MTD_CAP_NORFLASH, - size: 0xf00000, + size: 0x900000, erasesize: 0x20000, name: "NORA root filesystem", module: THIS_MODULE, @@ -155,9 +153,9 @@ { type: MTD_NORFLASH, flags: MTD_CAP_NORFLASH, - size: 0x1000000, + size: 0x1600000, erasesize: 0x20000, - name: "NORA main filesystem", + name: "NORA second filesystem", module: THIS_MODULE, erase: nora_mtd_erase, read: nora_mtd_read, @@ -165,16 +163,15 @@ suspend: nora_mtd_suspend, resume: nora_mtd_resume, sync: nora_mtd_sync, - priv: (void *)0x1000000 + priv: (void *)0xa00000 } }; -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_nora init_module #define cleanup_nora cleanup_module #endif -#endif int __init init_nora(void) { @@ -186,10 +183,10 @@ mymtd->module = &__this_module; #endif - add_mtd_device(&nora_mtds[3]); + add_mtd_device(&nora_mtds[2]); add_mtd_device(&nora_mtds[0]); add_mtd_device(&nora_mtds[1]); - add_mtd_device(&nora_mtds[2]); + add_mtd_device(&nora_mtds[3]); return 0; } @@ -199,10 +196,13 @@ static void __exit cleanup_nora(void) { if (mymtd) { - del_mtd_device(&nora_mtds[2]); + del_mtd_device(&nora_mtds[3]); del_mtd_device(&nora_mtds[1]); del_mtd_device(&nora_mtds[0]); - del_mtd_device(&nora_mtds[3]); + del_mtd_device(&nora_mtds[2]); map_destroy(mymtd); } } + +module_init(init_nora); +module_exit(cleanup_nora); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/octagon-5066.c linux/drivers/mtd/octagon-5066.c --- v2.4.0-test11/linux/drivers/mtd/octagon-5066.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/octagon-5066.c Mon Dec 11 14:57:58 2000 @@ -1,4 +1,4 @@ -// $Id: octagon-5066.c,v 1.10 2000/07/13 14:04:23 dwmw2 Exp $ +// $Id: octagon-5066.c,v 1.12 2000/11/27 08:50:22 dwmw2 Exp $ /* ###################################################################### Octagon 5066 MTD Driver. @@ -151,32 +151,32 @@ static struct map_info oct5066_map[2] = { { - "Octagon 5066 Socket", - 512 * 1024, - 1, - oct5066_read8, - oct5066_read16, - oct5066_read32, - oct5066_copy_from, - oct5066_write8, - oct5066_write16, - oct5066_write32, - oct5066_copy_to, - 1<<6 + name: "Octagon 5066 Socket", + size: 512 * 1024, + buswidth: 1, + read8: oct5066_read8, + read16: oct5066_read16, + read32: oct5066_read32, + copy_from: oct5066_copy_from, + write8: oct5066_write8, + write16: oct5066_write16, + write32: oct5066_write32, + copy_to: oct5066_copy_to, + map_priv_1: 1<<6 }, { - "Octagon 5066 Internal Flash", - 2 * 1024 * 1024, - 1, - oct5066_read8, - oct5066_read16, - oct5066_read32, - oct5066_copy_from, - oct5066_write8, - oct5066_write16, - oct5066_write32, - oct5066_copy_to, - 2<<6 + name: "Octagon 5066 Internal Flash", + size: 2 * 1024 * 1024, + buswidth: 1, + read8: oct5066_read8, + read16: oct5066_read16, + read32: oct5066_read32, + copy_from: oct5066_copy_from, + write8: oct5066_write8, + write16: oct5066_write16, + write32: oct5066_write32, + copy_to: oct5066_copy_to, + map_priv_1: 2<<6 } }; @@ -213,13 +213,10 @@ return 0; } -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_oct5066 init_module #define cleanup_oct5066 cleanup_module #endif -#define __exit -#endif void cleanup_oct5066(void) { @@ -284,7 +281,5 @@ return 0; } -#if LINUX_VERSION_CODE > 0x20300 module_init(init_oct5066); module_exit(cleanup_oct5066); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/physmap.c linux/drivers/mtd/physmap.c --- v2.4.0-test11/linux/drivers/mtd/physmap.c Tue Jul 11 11:23:37 2000 +++ linux/drivers/mtd/physmap.c Mon Dec 11 14:57:58 2000 @@ -1,5 +1,5 @@ /* - * $Id: physmap.c,v 1.2 2000/07/11 09:42:32 dwmw2 Exp $ + * $Id: physmap.c,v 1.8 2000/11/27 08:50:22 dwmw2 Exp $ * * Normal mappings of chips in physical memory */ @@ -15,6 +15,7 @@ #define WINDOW_ADDR CONFIG_MTD_PHYSMAP_START #define WINDOW_SIZE CONFIG_MTD_PHYSMAP_LEN +#define BUSWIDTH CONFIG_MTD_PHYSMAP_BUSWIDTH static struct mtd_info *mymtd; @@ -59,32 +60,28 @@ } struct map_info physmap_map = { - "Physically mapped flash", - WINDOW_SIZE, - 2, - physmap_read8, - physmap_read16, - physmap_read32, - physmap_copy_from, - physmap_write8, - physmap_write16, - physmap_write32, - physmap_copy_to, - 0, - 0 + name: "Physically mapped flash", + size: WINDOW_SIZE, + buswidth: BUSWIDTH, + read8: physmap_read8, + read16: physmap_read16, + read32: physmap_read32, + copy_from: physmap_copy_from, + write8: physmap_write8, + write16: physmap_write16, + write32: physmap_write32, + copy_to: physmap_copy_to }; -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_physmap init_module #define cleanup_physmap cleanup_module #endif -#endif int __init init_physmap(void) { printk(KERN_NOTICE "physmap flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_SIZE, WINDOW_ADDR); + physmap_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE); if (!physmap_map.map_priv_1) { printk("Failed to ioremap\n"); @@ -99,6 +96,7 @@ return 0; } + iounmap((void *)physmap_map.map_priv_1); return -ENXIO; } @@ -113,3 +111,7 @@ physmap_map.map_priv_1 = 0; } } + +module_init(init_physmap); +module_exit(cleanup_physmap); + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/pmc551.c linux/drivers/mtd/pmc551.c --- v2.4.0-test11/linux/drivers/mtd/pmc551.c Fri Jul 14 12:21:19 2000 +++ linux/drivers/mtd/pmc551.c Sun Dec 3 17:45:22 2000 @@ -1,17 +1,17 @@ /* - * $Id: pmc551.c,v 1.8 2000/07/14 07:53:31 dwmw2 Exp $ + * $Id: pmc551.c,v 1.11 2000/11/23 13:40:12 dwmw2 Exp $ * * PMC551 PCI Mezzanine Ram Device * * Author: - * Mark Ferrell + * Mark Ferrell * Copyright 1999,2000 Nortel Networks * - * License: + * License: * As part of this driver was derrived from the slram.c driver it falls * under the same license, which is GNU General Public License v2 * - * Description: + * Description: * This driver is intended to support the PMC551 PCI Ram device from * Ramix Inc. The PMC551 is a PMC Mezzanine module for cPCI embeded * systems. The device contains a single SROM that initally programs the @@ -24,6 +24,23 @@ * it as a block device allows us to use it as high speed swap or for a * high speed disk device of some sort. Which becomes very usefull on * diskless systems in the embeded market I might add. + * + * Notes: + * Due to what I assume is more buggy SROM, the 64M PMC551 I have + * available claims that all 4 of it's DRAM banks have 64M of ram + * configured (making a grand total of 256M onboard). This is slightly + * annoying since the BAR0 size reflects the aperture size, not the dram + * size, and the V370PDC supplies no other method for memory size + * discovery. This problem is mostly only relivant when compiled as a + * module, as the unloading of the module with an aperture size smaller + * then the ram will cause the driver to detect the onboard memory size + * to be equal to the aperture size when the module is reloaded. Soooo, + * to help, the module supports an msize option to allow the + * specification of the onboard memory, and an asize option, to allow the + * specification of the aperture size. The aperture must be equal to or + * less then the memory size, the driver will correct this if you screw + * it up. This problem is not relivant for compiled in drivers as + * compiled in drivers only init once. * * Credits: * Saeed Karamooz of Ramix INC. for the initial @@ -31,7 +48,7 @@ * questions I had concerning operation of the device. * * Most of the MTD code for this driver was originally written for the - * slram.o module in the MTD drivers package written by David Hinds + * slram.o module in the MTD drivers package written by David Hinds * which allows the mapping of system * memory into an mtd device. Since the PMC551 memory module is * accessed in the same fashion as system memory, the slram.c code @@ -44,9 +61,9 @@ * * Modified driver to utilize a sliding apature instead of mapping all * memory into kernel space which turned out to be very wastefull. * * Located a bug in the SROM's initialization sequence that made the - * memory unussable, added a fix to code to touch up the DRAM some. + * memory unusable, added a fix to code to touch up the DRAM some. * - * Bugs/FIXME's: + * Bugs/FIXME's: * * MUST fix the init function to not spin on a register * waiting for it to set .. this does not safely handle busted devices * that never reset the register correctly which will cause the system to @@ -73,6 +90,10 @@ #include #include +#ifndef CONFIG_PCI +#error Enable PCI in your kernel config +#endif + #include #include #include @@ -347,14 +368,70 @@ #ifdef CONFIG_MTD_PMC551_BUGFIX u32 dram_data; #endif - u32 size, dcmd; - u16 cmd, i; + u32 size, dcmd, cfg, dtmp; + u16 cmd, tmp, i; + u8 bcmd, counter; /* Sanity Check */ if(!dev) { return -ENODEV; } + /* + * Attempt to reset the card + * FIXME: Stop Spinning registers + */ + counter=0; + /* unlock registers */ + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, 0xA5 ); + /* read in old data */ + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); + /* bang the reset line up and down for a few */ + for(i=0;i<10;i++) { + counter=0; + bcmd &= ~0x80; + while(counter++ < 100) { + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); + } + counter=0; + bcmd |= 0x80; + while(counter++ < 100) { + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); + } + } + bcmd |= (0x40|0x20); + pci_write_config_byte(dev, PMC551_SYS_CTRL_REG, bcmd); + + /* + * Take care and turn off the memory on the device while we + * tweak the configurations + */ + pci_read_config_word(dev, PCI_COMMAND, &cmd); + tmp = cmd & ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, tmp); + + /* + * Disable existing aperture before probing memory size + */ + pci_read_config_dword(dev, PMC551_PCI_MEM_MAP0, &dcmd); + dtmp=(dcmd|PMC551_PCI_MEM_MAP_ENABLE|PMC551_PCI_MEM_MAP_REG_EN); + pci_write_config_dword(dev, PMC551_PCI_MEM_MAP0, dtmp); + /* + * Grab old BAR0 config so that we can figure out memory size + * This is another bit of kludge going on. The reason for the + * redundancy is I am hoping to retain the original configuration + * previously assigned to the card by the BIOS or some previous + * fixup routine in the kernel. So we read the old config into cfg, + * then write all 1's to the memory space, read back the result into + * "size", and then write back all the old config. + */ + pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &cfg ); +#ifndef CONFIG_MTD_PMC551_BUGFIX + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, ~0 ); + pci_read_config_dword( dev, PCI_BASE_ADDRESS_0, &size ); + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + size=~(size&PCI_BASE_ADDRESS_MEM_MASK)+1; +#else /* * Get the size of the memory by reading all the DRAM size values * and adding them up. @@ -363,7 +440,6 @@ * row mux values. We fix them here, but this will break other * memory configurations. */ -#ifdef CONFIG_MTD_PMC551_BUGFIX pci_read_config_dword(dev, PMC551_DRAM_BLK0, &dram_data); size = PMC551_DRAM_BLK_GET_SIZE(dram_data); dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); @@ -387,7 +463,6 @@ dram_data = PMC551_DRAM_BLK_SET_COL_MUX(dram_data, 0x5); dram_data = PMC551_DRAM_BLK_SET_ROW_MUX(dram_data, 0x9); pci_write_config_dword(dev, PMC551_DRAM_BLK3, dram_data); -#endif /* CONFIG_MTD_PMC551_BUGFIX */ /* * Oops .. something went wrong @@ -395,34 +470,14 @@ if( (size &= PCI_BASE_ADDRESS_MEM_MASK) == 0) { return -ENODEV; } +#endif /* CONFIG_MTD_PMC551_BUGFIX */ - /* - * Set to be prefetchable - */ - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd ); - dcmd |= 0x8; - - /* - * Put it back the way it was - */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, dcmd ); - pci_read_config_dword(dev, PCI_BASE_ADDRESS_0, &dcmd ); - - /* - * Some screen fun - */ - printk(KERN_NOTICE "pmc551: %dM (0x%x) of %sprefetchable memory at 0x%lx\n", - size/1024/1024, size, ((dcmd&0x8) == 0)?"non-":"", - PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK ); - - /* - * Turn on PCI memory and I/O bus access just for kicks - */ - pci_write_config_word( dev, PCI_COMMAND, - PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); + if ((cfg&PCI_BASE_ADDRESS_SPACE) != PCI_BASE_ADDRESS_SPACE_MEMORY) { + return -ENODEV; + } /* - * Config DRAM + * Precharge Dram */ pci_write_config_word( dev, PMC551_SDRAM_MA, 0x0400 ); pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf ); @@ -431,11 +486,16 @@ * Wait untill command has gone through * FIXME: register spinning issue */ - do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); + do { pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd ); + if(counter++ > 100)break; } while ( (PCI_COMMAND_IO) & cmd ); /* - * Must be held high for some duration of time to take effect?? + * Turn on auto refresh + * The loop is taken directly from Ramix's example code. I assume that + * this must be held high for some duration of time, but I can find no + * documentation refrencing the reasons why. + * */ for ( i = 1; i<=8 ; i++) { pci_write_config_word (dev, PMC551_SDRAM_CMD, 0x0df); @@ -444,7 +504,9 @@ * Make certain command has gone through * FIXME: register spinning issue */ - do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + counter=0; + do { pci_read_config_word(dev, PMC551_SDRAM_CMD, &cmd); + if(counter++ > 100)break; } while ( (PCI_COMMAND_IO) & cmd ); } @@ -455,7 +517,9 @@ * Wait until command completes * FIXME: register spinning issue */ - do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); + counter=0; + do { pci_read_config_word ( dev, PMC551_SDRAM_CMD, &cmd); + if(counter++ > 100)break; } while ( (PCI_COMMAND_IO) & cmd ); pci_read_config_dword ( dev, PMC551_DRAM_CFG, &dcmd); @@ -481,54 +545,97 @@ cmd &= ~PCI_STATUS_DEVSEL_MASK; pci_write_config_word( dev, PCI_STATUS, cmd ); } + /* + * Set to be prefetchable and put everything back based on old cfg. + * it's possible that the reset of the V370PDC nuked the original + * settup + */ + cfg |= PCI_BASE_ADDRESS_MEM_PREFETCH; + pci_write_config_dword( dev, PCI_BASE_ADDRESS_0, cfg ); + + /* + * Turn PCI memory and I/O bus access back on + */ + pci_write_config_word( dev, PCI_COMMAND, + PCI_COMMAND_MEMORY | PCI_COMMAND_IO ); +#ifdef CONFIG_MTD_PMC551_DEBUG + /* + * Some screen fun + */ + printk(KERN_DEBUG "pmc551: %d%c (0x%x) of %sprefetchable memory at 0x%lx\n", + (size<1024)?size:(size<1048576)?size/1024:size/1024/1024, + (size<1024)?'B':(size<1048576)?'K':'M', + size, ((dcmd&(0x1<<3)) == 0)?"non-":"", + PCI_BASE_ADDRESS(dev)&PCI_BASE_ADDRESS_MEM_MASK ); /* * Check to see the state of the memory - * FIXME: perhaps hide some of this around an #ifdef DEBUG as - * it doesn't effect or enhance cards functionality */ - pci_read_config_dword( dev, 0x74, &dcmd ); - printk(KERN_NOTICE "pmc551: DRAM_BLK3 Flags: %s,%s\n", - ((0x2&dcmd) == 0)?"RW":"RO", - ((0x1&dcmd) == 0)?"Off":"On" ); - - pci_read_config_dword( dev, 0x70, &dcmd ); - printk(KERN_NOTICE "pmc551: DRAM_BLK2 Flags: %s,%s\n", - ((0x2&dcmd) == 0)?"RW":"RO", - ((0x1&dcmd) == 0)?"Off":"On" ); - - pci_read_config_dword( dev, 0x6C, &dcmd ); - printk(KERN_NOTICE "pmc551: DRAM_BLK1 Flags: %s,%s\n", - ((0x2&dcmd) == 0)?"RW":"RO", - ((0x1&dcmd) == 0)?"Off":"On" ); - - pci_read_config_dword( dev, 0x68, &dcmd ); - printk(KERN_NOTICE "pmc551: DRAM_BLK0 Flags: %s,%s\n", - ((0x2&dcmd) == 0)?"RW":"RO", - ((0x1&dcmd) == 0)?"Off":"On" ); - - pci_read_config_word( dev, 0x4, &cmd ); - printk( KERN_NOTICE "pmc551: Memory Access %s\n", - ((0x2&cmd) == 0)?"off":"on" ); - printk( KERN_NOTICE "pmc551: I/O Access %s\n", - ((0x1&cmd) == 0)?"off":"on" ); + pci_read_config_dword( dev, PMC551_DRAM_BLK0, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK0 Flags: %s,%s\n" + "pmc551: DRAM_BLK0 Size: %d at %d\n" + "pmc551: DRAM_BLK0 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK1, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK1 Flags: %s,%s\n" + "pmc551: DRAM_BLK1 Size: %d at %d\n" + "pmc551: DRAM_BLK1 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK2, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK2 Flags: %s,%s\n" + "pmc551: DRAM_BLK2 Size: %d at %d\n" + "pmc551: DRAM_BLK2 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_dword( dev, PMC551_DRAM_BLK3, &dcmd ); + printk(KERN_DEBUG "pmc551: DRAM_BLK3 Flags: %s,%s\n" + "pmc551: DRAM_BLK3 Size: %d at %d\n" + "pmc551: DRAM_BLK3 Row MUX: %d, Col MUX: %d\n", + (((0x1<<1)&dcmd) == 0)?"RW":"RO", + (((0x1<<0)&dcmd) == 0)?"Off":"On", + PMC551_DRAM_BLK_GET_SIZE(dcmd), + ((dcmd>>20)&0x7FF), ((dcmd>>13)&0x7), ((dcmd>>9)&0xF) ); + + pci_read_config_word( dev, PCI_COMMAND, &cmd ); + printk( KERN_DEBUG "pmc551: Memory Access %s\n", + (((0x1<<1)&cmd) == 0)?"off":"on" ); + printk( KERN_DEBUG "pmc551: I/O Access %s\n", + (((0x1<<0)&cmd) == 0)?"off":"on" ); - pci_read_config_word( dev, 0x6, &cmd ); - printk( KERN_NOTICE "pmc551: Devsel %s\n", + pci_read_config_word( dev, PCI_STATUS, &cmd ); + printk( KERN_DEBUG "pmc551: Devsel %s\n", ((PCI_STATUS_DEVSEL_MASK&cmd)==0x000)?"Fast": ((PCI_STATUS_DEVSEL_MASK&cmd)==0x200)?"Medium": ((PCI_STATUS_DEVSEL_MASK&cmd)==0x400)?"Slow":"Invalid" ); - printk( KERN_NOTICE "pmc551: %sFast Back-to-Back\n", + printk( KERN_DEBUG "pmc551: %sFast Back-to-Back\n", ((PCI_COMMAND_FAST_BACK&cmd) == 0)?"Not ":"" ); + pci_read_config_byte(dev, PMC551_SYS_CTRL_REG, &bcmd ); + printk( KERN_DEBUG "pmc551: EEPROM is under %s control\n" + "pmc551: System Control Register is %slocked to PCI access\n" + "pmc551: System Control Register is %slocked to EEPROM access\n", + (bcmd&0x1)?"software":"hardware", + (bcmd&0x20)?"":"un", (bcmd&0x40)?"":"un"); +#endif return size; } /* * Kernel version specific module stuffages */ -#if LINUX_VERSION_CODE < 0x20300 +#if LINUX_VERSION_CODE < 0x20211 #ifdef MODULE #define init_pmc551 init_module #define cleanup_pmc551 cleanup_module @@ -536,11 +643,27 @@ #define __exit #endif +#if defined(MODULE) +MODULE_AUTHOR("Mark Ferrell "); +MODULE_DESCRIPTION(PMC551_VERSION); +MODULE_PARM(msize, "i"); +MODULE_PARM_DESC(msize, "memory size, 6=32M, 7=64M, 8=128M, ect.. [32M-1024M]"); +MODULE_PARM(asize, "i"); +MODULE_PARM_DESC(asize, "aperture size, must be <= memsize [1M-1024M]"); +#endif +/* + * Stuff these outside the ifdef so as to not bust compiled in driver support + */ +static int msize=0; +#if defined(CONFIG_MTD_PMC551_APERTURE_SIZE) +static int asize=CONFIG_MTD_PMC551_APERTURE_SIZE +#else +static int asize=0; +#endif /* * PMC551 Card Initialization */ -//static int __init init_pmc551(void) int __init init_pmc551(void) { struct pci_dev *PCI_Device = NULL; @@ -549,9 +672,23 @@ struct mtd_info *mtd; u32 length = 0; + if(msize) { + if (msize < 6 || msize > 11 ) { + printk(KERN_NOTICE "pmc551: Invalid memory size\n"); + return -ENODEV; + } + msize = (512*1024)< 11 ) { + printk(KERN_NOTICE "pmc551: Invalid aperture size\n"); + return -ENODEV; + } + asize = (512*1024)<priv = priv; priv->dev = PCI_Device; - priv->aperture_size = PMC551_APERTURE_SIZE; + if(asize) { + if(asize > length) { + asize=length; + printk(KERN_NOTICE "pmc551: reducing aperture size to fit memory [0x%x]\n",asize); + } else { + printk(KERN_NOTICE "pmc551: Using specified aperture size 0x%x\n", asize); + } + priv->aperture_size = asize; + } else { + priv->aperture_size = length; + } priv->start = ioremap((PCI_BASE_ADDRESS(PCI_Device) & PCI_BASE_ADDRESS_MEM_MASK), priv->aperture_size); - priv->mem_map0_base_val = (PMC551_APERTURE_VAL - | PMC551_PCI_MEM_MAP_REG_EN - | PMC551_PCI_MEM_MAP_ENABLE); + + /* + * Due to the dynamic nature of the code, we need to figure + * this out in order to stuff the register to set the proper + * aperture size. If you know of an easier way to do this then + * PLEASE help yourself. + * + * Not with bloody floating point, you don't. Consider yourself + * duly LARTed. dwmw2. + */ + { + u32 size; + u16 bits; + size = priv->aperture_size>>20; + for(bits=0;!(size&0x01)&&size>0;bits++,size=size>>1); + //size=((u32)((log10(priv->aperture_size)/.30103)-19)<<4); + priv->mem_map0_base_val = (PMC551_PCI_MEM_MAP_REG_EN + | PMC551_PCI_MEM_MAP_ENABLE + | size); +#ifdef CONFIG_MTD_PMC551_DEBUG + printk(KERN_NOTICE "pmc551: aperture set to %d[%d]\n", + size, size>>4); +#endif + } priv->curr_mem_map0_val = priv->mem_map0_base_val; pci_write_config_dword ( priv->dev, @@ -641,7 +813,10 @@ priv->aperture_size/1024/1024, priv->start, priv->start + priv->aperture_size); - printk(KERN_NOTICE "Total memory is %dM\n", length/1024/1024); + printk(KERN_NOTICE "Total memory is %d%c\n", + (length<1024)?length: + (length<1048576)?length/1024:length/1024/1024, + (length<1024)?'B':(length<1048576)?'K':'M'); priv->nextpmc551 = pmc551list; pmc551list = mtd; found++; @@ -651,8 +826,8 @@ printk(KERN_NOTICE "pmc551: not detected,\n"); return -ENODEV; } else { - return 0; printk(KERN_NOTICE "pmc551: %d pmc551 devices loaded\n", found); + return 0; } } @@ -669,7 +844,7 @@ priv = (struct mypriv *)mtd->priv; pmc551list = priv->nextpmc551; - if(priv->start) + if(priv->start) iounmap(((struct mypriv *)mtd->priv)->start); kfree (mtd->priv); @@ -681,10 +856,7 @@ printk(KERN_NOTICE "pmc551: %d pmc551 devices unloaded\n", found); } -#if LINUX_VERSION_CODE > 0x20300 +#if LINUX_VERSION_CODE >= 0x20211 module_init(init_pmc551); module_exit(cleanup_pmc551); #endif - - - diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/pnc2000.c linux/drivers/mtd/pnc2000.c --- v2.4.0-test11/linux/drivers/mtd/pnc2000.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/pnc2000.c Mon Dec 11 14:57:58 2000 @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: pnc2000.c,v 1.1 2000/07/12 09:34:32 dwmw2 Exp $ + * $Id: pnc2000.c,v 1.4 2000/11/27 08:50:22 dwmw2 Exp $ */ #include @@ -14,6 +14,7 @@ #include #include +#include #define WINDOW_ADDR 0xbf000000 @@ -64,136 +65,60 @@ } struct map_info pnc_map = { - "PNC-2000", - WINDOW_SIZE, - 4, - pnc_read8, - pnc_read16, - pnc_read32, - pnc_copy_from, - pnc_write8, - pnc_write16, - pnc_write32, - pnc_copy_to, - 0, - 0 + name: "PNC-2000", + size: WINDOW_SIZE, + buswidth: 4, + read8: pnc_read8, + read16: pnc_read16, + read32: pnc_read32, + copy_from: pnc_copy_from, + write8: pnc_write8, + write16: pnc_write16, + write32: pnc_write32, + copy_to: pnc_copy_to }; /* * MTD 'PARTITIONING' STUFF */ - -/* - * This is the _real_ MTD device for which all the others are just - * auto-relocating aliases. - */ -static struct mtd_info *mymtd; - -/* - * MTD methods which simply translate the effective address and pass through - * to the _real_ device. - */ - -static int pnc_mtd_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) -{ - return mymtd->read(mymtd, from + (unsigned long)mtd->priv, len, retlen, buf); -} - -static int pnc_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) -{ - return mymtd->write(mymtd, to + (unsigned long)mtd->priv, len, retlen, buf); -} - -static int pnc_mtd_erase (struct mtd_info *mtd, struct erase_info *instr) -{ - instr->addr += (unsigned long)mtd->priv; - return mymtd->erase(mymtd, instr); -} - -static void pnc_mtd_sync (struct mtd_info *mtd) -{ - mymtd->sync(mymtd); -} - -static int pnc_mtd_suspend (struct mtd_info *mtd) -{ - return mymtd->suspend(mymtd); -} - -static void pnc_mtd_resume (struct mtd_info *mtd) -{ - mymtd->resume(mymtd); -} - - -static struct mtd_info pnc_mtds[3] = { /* boot, kernel, fs */ +static struct mtd_partition pnc_partitions[3] = { { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x20000, - erasesize: 0x20000, name: "PNC-2000 boot firmware", - module: THIS_MODULE, - erase: pnc_mtd_erase, - read: pnc_mtd_read, - write: pnc_mtd_write, - suspend: pnc_mtd_suspend, - resume: pnc_mtd_resume, - sync: pnc_mtd_sync, - priv: (void *)0 + size: 0x20000, + offset: 0 }, { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x1a0000, - erasesize: 0x20000, name: "PNC-2000 kernel", - module: THIS_MODULE, - erase: pnc_mtd_erase, - read: pnc_mtd_read, - write: pnc_mtd_write, - suspend: pnc_mtd_suspend, - resume: pnc_mtd_resume, - sync: pnc_mtd_sync, - priv: (void *)0x20000 + size: 0x1a0000, + offset: 0x20000 }, { - type: MTD_NORFLASH, - flags: MTD_CAP_NORFLASH, - size: 0x240000, - erasesize: 0x20000, name: "PNC-2000 filesystem", - module: THIS_MODULE, - erase: pnc_mtd_erase, - read: pnc_mtd_read, - write: pnc_mtd_write, - suspend: pnc_mtd_suspend, - resume: pnc_mtd_resume, - sync: pnc_mtd_sync, - priv: (void *)0x1c0000 + size: 0x240000, + offset: 0x1c0000 } }; -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +/* + * This is the master MTD device for which all the others are just + * auto-relocating aliases. + */ +static struct mtd_info *mymtd; + +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_pnc init_module #define cleanup_pnc cleanup_module #endif -#endif int __init init_pnc(void) { - printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); + printk(KERN_NOTICE "Photron PNC-2000 flash mapping: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); mymtd = do_cfi_probe(&pnc_map); if (mymtd) { mymtd->module = THIS_MODULE; - - add_mtd_device(&pnc_mtds[0]); /* boot */ - add_mtd_device(&pnc_mtds[1]); /* kernel */ - add_mtd_device(&pnc_mtds[2]); /* file system */ - return 0; + return add_mtd_partitions(mymtd, pnc_partitions, 3); } return -ENXIO; @@ -202,9 +127,10 @@ static void __exit cleanup_pnc(void) { if (mymtd) { - del_mtd_device(&pnc_mtds[2]); - del_mtd_device(&pnc_mtds[1]); - del_mtd_device(&pnc_mtds[0]); + del_mtd_partitions(mymtd); map_destroy(mymtd); } } + +module_init(init_pnc); +module_exit(cleanup_pnc); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/rpxlite.c linux/drivers/mtd/rpxlite.c --- v2.4.0-test11/linux/drivers/mtd/rpxlite.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/rpxlite.c Mon Dec 11 14:57:58 2000 @@ -1,7 +1,7 @@ /* - * $Id: rpxlite.c,v 1.2 2000/07/04 12:16:26 dwmw2 Exp $ + * $Id: rpxlite.c,v 1.8 2000/12/09 22:00:31 dwmw2 Exp $ * - * Handle the strange 16-in-32-bit mapping on the RPXLite board + * Handle mapping of the flash on the RPX Lite and CLLF boards */ #include @@ -12,124 +12,74 @@ #include -#define WINDOW_ADDR 0x8000000 -#define WINDOW_SIZE 0x2000000 - -#define MAP_TO_ADR(x) ( ( ( x & ~1 ) << 1 ) | (x&1) ) +#define WINDOW_ADDR 0xfe000000 +#define WINDOW_SIZE 0x800000 static struct mtd_info *mymtd; __u8 rpxlite_read8(struct map_info *map, unsigned long ofs) { - return readb(map->map_priv_1 + MAP_TO_ADR(ofs)); + return readb(map->map_priv_1 * ofs); } __u16 rpxlite_read16(struct map_info *map, unsigned long ofs) { - return readw(map->map_priv_1 + MAP_TO_ADR(ofs)); + return readw(map->map_priv_1 + ofs); } __u32 rpxlite_read32(struct map_info *map, unsigned long ofs) { - return readl(map->map_priv_1 + MAP_TO_ADR(ofs)); + return readl(map->map_priv_1 + ofs); } void rpxlite_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) { - if (from & 1) { - *(__u8 *)to = readb(map->map_priv_1 + MAP_TO_ADR(from)); - from++; - len--; - } - /* Can't do this if it's not aligned */ - if (!((unsigned long)to & 1)) { - unsigned long fromadr = MAP_TO_ADR(from); - - while (len > 1) { - *(__u16 *)to = readw(map->map_priv_1 + fromadr); - to += 2; - fromadr += 4; - from += 2; - len -= 2; - } - } - while(len) { - *(__u8 *)to = readb(map->map_priv_1 + MAP_TO_ADR(from)); - to++; - from++; - len--; - } + memcpy_fromio(to, (void *)(map->map_priv_1 + from), len); } void rpxlite_write8(struct map_info *map, __u8 d, unsigned long adr) { - writeb(d, map->map_priv_1 + MAP_TO_ADR(adr)); + writeb(d, map->map_priv_1 + adr); } void rpxlite_write16(struct map_info *map, __u16 d, unsigned long adr) { - writew(d, map->map_priv_1 + MAP_TO_ADR(adr)); + writew(d, map->map_priv_1 + adr); } void rpxlite_write32(struct map_info *map, __u32 d, unsigned long adr) { - writel(d, map->map_priv_1 + MAP_TO_ADR(adr)); + writel(d, map->map_priv_1 + adr); } void rpxlite_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) { - if (to & 1) { - writeb(*(__u8 *)from, map->map_priv_1 + MAP_TO_ADR(to)); - from++; - len--; - } - /* Can't do this if it's not aligned */ - if (!((unsigned long)from & 1)) { - unsigned long toadr = map->map_priv_1 + MAP_TO_ADR(to); - - while (len > 1) { - writew(*(__u16 *)from, toadr); - from += 2; - toadr += 4; - to += 2; - len -= 2; - } - } - while(len) { - writeb(*(__u8 *)from, map->map_priv_1 + MAP_TO_ADR(to)); - to++; - from++; - len--; - } + memcpy_toio((void *)(map->map_priv_1 + to), from, len); } struct map_info rpxlite_map = { - "RPXLITE", - WINDOW_SIZE, - 2, - rpxlite_read8, - rpxlite_read16, - rpxlite_read32, - rpxlite_copy_from, - rpxlite_write8, - rpxlite_write16, - rpxlite_write32, - rpxlite_copy_to, - 0, - 0 + name: "RPX", + size: WINDOW_SIZE, + buswidth: 4, + read8: rpxlite_read8, + read16: rpxlite_read16, + read32: rpxlite_read32, + copy_from: rpxlite_copy_from, + write8: rpxlite_write8, + write16: rpxlite_write16, + write32: rpxlite_write32, + copy_to: rpxlite_copy_to }; -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_rpxlite init_module #define cleanup_rpxlite cleanup_module #endif -#endif int __init init_rpxlite(void) { - printk(KERN_NOTICE "rpxlite flash device: %x at %x\n", WINDOW_SIZE, WINDOW_ADDR); - rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 2); + printk(KERN_NOTICE "RPX Lite or CLLF flash device: %x at %x\n", WINDOW_SIZE*4, WINDOW_ADDR); + rpxlite_map.map_priv_1 = (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE * 4); if (!rpxlite_map.map_priv_1) { printk("Failed to ioremap\n"); @@ -158,3 +108,6 @@ rpxlite_map.map_priv_1 = 0; } } + +module_init(init_rpxlite); +module_exit(cleanup_rpxlite); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/mtd/vmax301.c linux/drivers/mtd/vmax301.c --- v2.4.0-test11/linux/drivers/mtd/vmax301.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/vmax301.c Mon Dec 11 14:57:58 2000 @@ -1,4 +1,4 @@ -// $Id: vmax301.c,v 1.13 2000/07/03 10:01:38 dwmw2 Exp $ +// $Id: vmax301.c,v 1.15 2000/11/27 08:50:22 dwmw2 Exp $ /* ###################################################################### Tempustech VMAX SBC301 MTD Driver. @@ -142,46 +142,43 @@ static struct map_info vmax_map[2] = { { - "VMAX301 Internal Flash", - 3*2*1024*1024, - 1, - vmax301_read8, - vmax301_read16, - vmax301_read32, - vmax301_copy_from, - vmax301_write8, - vmax301_write16, - vmax301_write32, - vmax301_copy_to, - WINDOW_START + WINDOW_LENGTH, - 0xFFFFFFFF + name: "VMAX301 Internal Flash", + size: 3*2*1024*1024, + buswidth: 1, + read8: vmax301_read8, + read16: vmax301_read16, + read32: vmax301_read32, + copy_from: vmax301_copy_from, + write8: vmax301_write8, + write16: vmax301_write16, + write32: vmax301_write32, + copy_to: vmax301_copy_to, + map_priv_1: WINDOW_START + WINDOW_LENGTH, + map_priv_2: 0xFFFFFFFF }, { - "VMAX301 Socket", - 0, - 1, - vmax301_read8, - vmax301_read16, - vmax301_read32, - vmax301_copy_from, - vmax301_write8, - vmax301_write16, - vmax301_write32, - vmax301_copy_to, - WINDOW_START + (3*WINDOW_LENGTH), - 0xFFFFFFFF + name: "VMAX301 Socket", + size: 0, + buswidth: 1, + read8: vmax301_read8, + read16: vmax301_read16, + read32: vmax301_read32, + copy_from: vmax301_copy_from, + write8: vmax301_write8, + write16: vmax301_write16, + write32: vmax301_write32, + copy_to: vmax301_copy_to, + map_priv_1: WINDOW_START + (3*WINDOW_LENGTH), + map_priv_2: 0xFFFFFFFF } }; static struct mtd_info *vmax_mtd[2] = {NULL, NULL}; -#if LINUX_VERSION_CODE < 0x20300 -#ifdef MODULE +#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE) #define init_vmax301 init_module #define cleanup_vmax301 cleanup_module #endif -#define __exit -#endif static void __exit cleanup_vmax301(void) { @@ -237,7 +234,5 @@ return 0; } -#if LINUX_VERSION_CODE > 0x20300 module_init(init_vmax301); module_exit(cleanup_vmax301); -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v2.4.0-test11/linux/drivers/net/3c503.c Sun Nov 19 18:44:09 2000 +++ linux/drivers/net/3c503.c Tue Dec 5 12:29:38 2000 @@ -88,7 +88,7 @@ int base_addr = dev->base_addr; SET_MODULE_OWNER(dev); - + if (base_addr > 0x1ff) /* Check a single specified location. */ return el2_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ @@ -319,6 +319,7 @@ static int el2_open(struct net_device *dev) { + int retval = -EAGAIN; if (dev->irq < 2) { int irqlist[] = {5, 9, 3, 4, 0}; @@ -331,18 +332,19 @@ unsigned long cookie = probe_irq_on(); outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); outb_p(0x00, E33G_IDCFR); - if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */ - && request_irq (dev->irq = *irqp, ei_interrupt, 0, ei_status.name, dev) == 0) + if (*irqp == probe_irq_off(cookie) /* It's a good IRQ line! */ + && ((retval = request_irq(dev->irq = *irqp, + ei_interrupt, 0, dev->name, dev)) == 0)) break; } } while (*++irqp); if (*irqp == 0) { outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */ - return -EAGAIN; + return retval; } } else { - if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev)) { - return -EAGAIN; + if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + return retval; } } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/3c505.h linux/drivers/net/3c505.h --- v2.4.0-test11/linux/drivers/net/3c505.h Sun Feb 13 18:20:21 2000 +++ linux/drivers/net/3c505.h Tue Dec 5 12:29:38 2000 @@ -284,7 +284,7 @@ /* flags */ unsigned long send_pcb_semaphore; - unsigned int dmaing; + unsigned long dmaing; unsigned long busy; unsigned int rx_active; /* number of receive PCBs */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/8139too.c linux/drivers/net/8139too.c --- v2.4.0-test11/linux/drivers/net/8139too.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/8139too.c Sun Dec 3 17:45:23 2000 @@ -134,6 +134,7 @@ */ +#include #include #include #include @@ -141,18 +142,21 @@ #include #include #include +#include #include #include -#define RTL8139_VERSION "0.9.11" -#define RTL8139_MODULE_NAME "8139too" -#define RTL8139_DRIVER_NAME RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION -#define PFX RTL8139_MODULE_NAME ": " +#define RTL8139_VERSION "0.9.12" +#define MODNAME "8139too" +#define RTL8139_DRIVER_NAME MODNAME " Fast Ethernet driver " RTL8139_VERSION +#define PFX MODNAME ": " -/* define to 1 to enable PIO instead of MMIO */ -#undef USE_IO_OPS +/* enable PIO instead of MMIO, if CONFIG_8139TOO_PIO is selected */ +#ifdef CONFIG_8139TOO_PIO +#define USE_IO_OPS 1 +#endif /* define to 1 to enable copious debugging info */ #undef RTL8139_DEBUG @@ -502,12 +506,11 @@ int drv_flags; struct pci_dev *pci_dev; struct net_device_stats stats; - struct timer_list timer; /* Media selection timer. */ unsigned char *rx_ring; unsigned int cur_rx; /* Index into the Rx buffer of next Rx pkt. */ unsigned int tx_flag; - atomic_t cur_tx; - atomic_t dirty_tx; + unsigned int cur_tx; + unsigned int dirty_tx; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ struct ring_info tx_info[NUM_TX_DESC]; unsigned char *tx_buf[NUM_TX_DESC]; /* Tx bounce buffers */ @@ -524,6 +527,9 @@ unsigned int mediasense:1; /* Media sensing in progress. */ spinlock_t lock; chip_t chipset; + pid_t thr_pid; + wait_queue_head_t thr_wait; + struct semaphore thr_exited; }; MODULE_AUTHOR ("Jeff Garzik "); @@ -538,7 +544,7 @@ static int mdio_read (struct net_device *dev, int phy_id, int location); static void mdio_write (struct net_device *dev, int phy_id, int location, int val); -static void rtl8139_timer (unsigned long data); +static int rtl8139_thread (void *data); static void rtl8139_tx_timeout (struct net_device *dev); static void rtl8139_init_ring (struct net_device *dev); static int rtl8139_start_xmit (struct sk_buff *skb, @@ -552,7 +558,6 @@ static void rtl8139_set_rx_mode (struct net_device *dev); static void rtl8139_hw_start (struct net_device *dev); - #ifdef USE_IO_OPS #define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg)) @@ -648,6 +653,7 @@ DPRINTK ("EXIT, returning -ENOMEM\n"); return -ENOMEM; } + SET_MODULE_OWNER(dev); tp = dev->priv; pio_start = pci_resource_start (pdev, 0); @@ -867,7 +873,9 @@ tp->pci_dev = pdev; tp->board = ent->driver_data; tp->mmio_addr = ioaddr; - tp->lock = SPIN_LOCK_UNLOCKED; + spin_lock_init (&tp->lock); + init_waitqueue_head (&tp->thr_wait); + init_MUTEX_LOCKED (&tp->thr_exited); pdev->driver_data = dev; @@ -897,7 +905,7 @@ RTL_W8_F (HltClk, 'H'); /* 'R' would leave the clock running. */ /* The lower four bits are the media type. */ - option = (board_idx > 7) ? 0 : media[board_idx]; + option = (board_idx >= ARRAY_SIZE(media)) ? 0 : media[board_idx]; if (option > 0) { tp->full_duplex = (option & 0x200) ? 1 : 0; tp->default_port = option & 15; @@ -1068,7 +1076,7 @@ static int mdio_read (struct net_device *dev, int phy_id, int location) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *mdio_addr = tp->mmio_addr + Config4; int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location; int retval = 0; @@ -1111,7 +1119,7 @@ static void mdio_write (struct net_device *dev, int phy_id, int location, int value) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *mdio_addr = tp->mmio_addr + Config4; int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value; @@ -1154,7 +1162,7 @@ static int rtl8139_open (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; int retval; #ifdef RTL8139_DEBUG void *ioaddr = tp->mmio_addr; @@ -1162,12 +1170,9 @@ DPRINTK ("ENTER\n"); - MOD_INC_USE_COUNT; - retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev); if (retval) { DPRINTK ("EXIT, returning %d\n", retval); - MOD_DEC_USE_COUNT; return retval; } @@ -1186,13 +1191,13 @@ tp->rx_ring, tp->rx_ring_dma); DPRINTK ("EXIT, returning -ENOMEM\n"); - MOD_DEC_USE_COUNT; return -ENOMEM; } tp->full_duplex = tp->duplex_lock; tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000; + tp->twistie = 1; rtl8139_init_ring (dev); rtl8139_hw_start (dev); @@ -1203,13 +1208,10 @@ dev->irq, RTL_R8 (MediaStatus), tp->full_duplex ? "full" : "half"); - /* Set the timer to switch to check for link beat and perhaps switch - to an alternate media type. */ - init_timer (&tp->timer); - tp->timer.expires = jiffies + 3 * HZ; - tp->timer.data = (unsigned long) dev; - tp->timer.function = &rtl8139_timer; - add_timer (&tp->timer); + tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES); + if (tp->thr_pid < 0) + printk (KERN_WARNING "%s: unable to start kernel thread\n", + dev->name); DPRINTK ("EXIT, returning 0\n"); return 0; @@ -1219,7 +1221,7 @@ /* Start the hardware at open or resume. */ static void rtl8139_hw_start (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; u32 i; u8 tmp; @@ -1311,14 +1313,14 @@ /* Initialize the Rx and Tx rings, along with various 'dev' bits. */ static void rtl8139_init_ring (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; int i; DPRINTK ("ENTER\n"); tp->cur_rx = 0; - atomic_set (&tp->cur_tx, 0); - atomic_set (&tp->dirty_tx, 0); + tp->cur_tx = 0; + tp->dirty_tx = 0; for (i = 0; i < NUM_TX_DESC; i++) { tp->tx_info[i].skb = NULL; @@ -1330,7 +1332,10 @@ } -#ifndef RTL_TUNE_TWISTER +/* This must be global for CONFIG_8139TOO_TUNE_TWISTER case */ +static int next_tick = 3 * HZ; + +#ifndef CONFIG_8139TOO_TUNE_TWISTER static inline void rtl8139_tune_twister (struct net_device *dev, struct rtl8139_private *tp) {} #else @@ -1338,6 +1343,7 @@ struct rtl8139_private *tp) { int linkcase; + void *ioaddr = tp->mmio_addr; DPRINTK ("ENTER\n"); @@ -1421,15 +1427,13 @@ DPRINTK ("EXIT\n"); } -#endif /* RTL_TUNE_TWISTER */ +#endif /* CONFIG_8139TOO_TUNE_TWISTER */ -static void rtl8139_timer (unsigned long data) +static inline void rtl8139_thread_iter (struct net_device *dev, + struct rtl8139_private *tp, + void *ioaddr) { - struct net_device *dev = (struct net_device *) data; - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; - void *ioaddr = tp->mmio_addr; - int next_tick = 60 * HZ; int mii_reg5; mii_reg5 = mdio_read (dev, tp->phys[0], 5); @@ -1450,6 +1454,8 @@ } } + next_tick = HZ * 60; + rtl8139_tune_twister (dev, tp); DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n", @@ -1462,9 +1468,33 @@ DPRINTK ("%s: Chip config %2.2x %2.2x.\n", dev->name, RTL_R8 (Config0), RTL_R8 (Config1)); +} + + +static int rtl8139_thread (void *data) +{ + struct net_device *dev = data; + struct rtl8139_private *tp = dev->priv; + unsigned long timeout; + + daemonize (); + sprintf (current->comm, "k8139d-%s", dev->name); + + while (1) { + timeout = next_tick; + do { + timeout = interruptible_sleep_on_timeout (&tp->thr_wait, timeout); + } while (!signal_pending (current) && (timeout > 0)); - tp->timer.expires = jiffies + next_tick; - add_timer (&tp->timer); + if (signal_pending (current)) + break; + + rtnl_lock (); + rtl8139_thread_iter (dev, tp, tp->mmio_addr); + rtnl_unlock (); + } + + up_and_exit (&tp->thr_exited, 0); } @@ -1472,8 +1502,8 @@ { int i; - atomic_set (&tp->cur_tx, 0); - atomic_set (&tp->dirty_tx, 0); + tp->cur_tx = 0; + tp->dirty_tx = 0; /* Dump the unsent Tx packets. */ for (i = 0; i < NUM_TX_DESC; i++) { @@ -1494,11 +1524,10 @@ static void rtl8139_tx_timeout (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; int i; u8 tmp8; - unsigned long flags; DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x " "media %2.2x.\n", dev->name, @@ -1516,20 +1545,17 @@ /* Emit info to figure out what went wrong. */ printk (KERN_DEBUG "%s: Tx queue start entry %d dirty entry %d.\n", - dev->name, atomic_read (&tp->cur_tx), - atomic_read (&tp->dirty_tx)); + dev->name, tp->cur_tx, tp->dirty_tx); for (i = 0; i < NUM_TX_DESC; i++) printk (KERN_DEBUG "%s: Tx descriptor %d is %8.8lx.%s\n", dev->name, i, RTL_R32 (TxStatus0 + (i * 4)), - i == atomic_read (&tp->dirty_tx) % NUM_TX_DESC ? + i == tp->dirty_tx % NUM_TX_DESC ? " (queue head)" : ""); /* Stop a shared interrupt from scavenging while we are. */ - spin_lock_irqsave (&tp->lock, flags); - + spin_lock_irq (&tp->lock); rtl8139_tx_clear (tp); - - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irq (&tp->lock); /* ...and finally, reset everything */ rtl8139_hw_start (dev); @@ -1539,27 +1565,37 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; int entry; /* Calculate the next Tx descriptor entry. */ - entry = atomic_read (&tp->cur_tx) % NUM_TX_DESC; + entry = tp->cur_tx % NUM_TX_DESC; assert (tp->tx_info[entry].skb == NULL); assert (tp->tx_info[entry].mapping == 0); tp->tx_info[entry].skb = skb; - /* tp->tx_info[entry].mapping = 0; */ - memcpy (tp->tx_buf[entry], skb->data, skb->len); + if ((long) skb->data & 3) { /* Must use alignment buffer. */ + /* tp->tx_info[entry].mapping = 0; */ + memcpy (tp->tx_buf[entry], skb->data, skb->len); + RTL_W32 (TxAddr0 + (entry * 4), + tp->tx_bufs_dma + (tp->tx_buf[entry] - tp->tx_bufs)); + } else { + tp->tx_info[entry].mapping = + pci_map_single (tp->pci_dev, skb->data, skb->len, + PCI_DMA_TODEVICE); + RTL_W32 (TxAddr0 + (entry * 4), tp->tx_info[entry].mapping); + } /* Note: the chip doesn't have auto-pad! */ - RTL_W32 (TxStatus0 + (entry * sizeof(u32)), + RTL_W32 (TxStatus0 + (entry * sizeof (u32)), tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); dev->trans_start = jiffies; - atomic_inc (&tp->cur_tx); - if ((atomic_read (&tp->cur_tx) - atomic_read (&tp->dirty_tx)) >= NUM_TX_DESC) + tp->cur_tx++; + mb(); + if ((tp->cur_tx - NUM_TX_DESC) == tp->dirty_tx) netif_stop_queue (dev); DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n", @@ -1573,16 +1609,14 @@ struct rtl8139_private *tp, void *ioaddr) { - int cur_tx, dirty_tx, tx_left; + unsigned int dirty_tx, tx_left; assert (dev != NULL); assert (tp != NULL); assert (ioaddr != NULL); - dirty_tx = atomic_read (&tp->dirty_tx); - - cur_tx = atomic_read (&tp->cur_tx); - tx_left = cur_tx - dirty_tx; + dirty_tx = tp->dirty_tx; + tx_left = tp->cur_tx - dirty_tx; while (tx_left > 0) { int entry = dirty_tx % NUM_TX_DESC; int txstatus; @@ -1632,29 +1666,27 @@ } dev_kfree_skb_irq (tp->tx_info[entry].skb); tp->tx_info[entry].skb = NULL; - dirty_tx++; - if (dirty_tx < 0) { /* handle signed int overflow */ - atomic_sub (cur_tx, &tp->cur_tx); /* XXX racy? */ - dirty_tx = cur_tx - tx_left + 1; - } - if (netif_queue_stopped (dev)) - netif_wake_queue (dev); - - cur_tx = atomic_read (&tp->cur_tx); - tx_left = cur_tx - dirty_tx; + dirty_tx++; + tx_left--; } #ifndef RTL8139_NDEBUG - if (atomic_read (&tp->cur_tx) - dirty_tx > NUM_TX_DESC) { + if (tp->cur_tx - dirty_tx > NUM_TX_DESC) { printk (KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", - dev->name, dirty_tx, atomic_read (&tp->cur_tx)); + dev->name, dirty_tx, tp->cur_tx); dirty_tx += NUM_TX_DESC; } #endif /* RTL8139_NDEBUG */ - atomic_set (&tp->dirty_tx, dirty_tx); + /* only wake the queue if we did work, and the queue is stopped */ + if (tp->dirty_tx != dirty_tx) { + tp->dirty_tx = dirty_tx; + mb(); + if (netif_queue_stopped (dev)) + netif_wake_queue (dev); + } } @@ -1879,7 +1911,7 @@ struct pt_regs *regs) { struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; int boguscnt = max_interrupt_work; void *ioaddr = tp->mmio_addr; int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */ @@ -1962,20 +1994,27 @@ static int rtl8139_close (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; - unsigned long flags; + int ret = 0; DPRINTK ("ENTER\n"); netif_stop_queue (dev); + if (tp->thr_pid >= 0) { + ret = kill_proc (tp->thr_pid, SIGTERM, 1); + if (ret) { + printk (KERN_ERR "%s: unable to signal thread\n", dev->name); + return ret; + } + down (&tp->thr_exited); + } + DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n", dev->name, RTL_R16 (IntrStatus)); - del_timer_sync (&tp->timer); - - spin_lock_irqsave (&tp->lock, flags); + spin_lock_irq (&tp->lock); /* Stop the chip's Tx and Rx DMA processes. */ RTL_W8 (ChipCmd, (RTL_R8 (ChipCmd) & ChipCmdClear)); @@ -1987,7 +2026,7 @@ tp->stats.rx_missed_errors += RTL_R32 (RxMissed); RTL_W32 (RxMissed, 0); - spin_unlock_irqrestore (&tp->lock, flags); + spin_unlock_irq (&tp->lock); synchronize_irq (); free_irq (dev->irq, dev); @@ -2006,8 +2045,6 @@ RTL_W8 (Config1, 0x03); RTL_W8 (HltClk, 'H'); /* 'R' would leave the clock running. */ - MOD_DEC_USE_COUNT; - DPRINTK ("EXIT\n"); return 0; } @@ -2015,9 +2052,8 @@ static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; u16 *data = (u16 *) & rq->ifr_data; - unsigned long flags; int rc = 0; DPRINTK ("ENTER\n"); @@ -2028,9 +2064,7 @@ /* Fall Through */ case SIOCDEVPRIVATE + 1: /* Read the specified MII register. */ - spin_lock_irqsave (&tp->lock, flags); data[3] = mdio_read (dev, data[0], data[1] & 0x1f); - spin_unlock_irqrestore (&tp->lock, flags); break; case SIOCDEVPRIVATE + 2: /* Write the specified MII register */ @@ -2039,9 +2073,7 @@ break; } - spin_lock_irqsave (&tp->lock, flags); mdio_write (dev, data[0], data[1] & 0x1f, data[2]); - spin_unlock_irqrestore (&tp->lock, flags); break; default: @@ -2056,22 +2088,14 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; DPRINTK ("ENTER\n"); - assert (tp != NULL); - if (netif_running(dev)) { - unsigned long flags; - - spin_lock_irqsave (&tp->lock, flags); - tp->stats.rx_missed_errors += RTL_R32 (RxMissed); RTL_W32 (RxMissed, 0); - - spin_unlock_irqrestore (&tp->lock, flags); } DPRINTK ("EXIT\n"); @@ -2104,7 +2128,7 @@ static void rtl8139_set_rx_mode (struct net_device *dev) { - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; u32 mc_filter[2]; /* Multicast hash filter */ int i, rx_mode; @@ -2160,7 +2184,7 @@ static void rtl8139_suspend (struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; - struct rtl8139_private *tp = (struct rtl8139_private *) dev->priv; + struct rtl8139_private *tp = dev->priv; void *ioaddr = tp->mmio_addr; unsigned long flags; @@ -2190,7 +2214,7 @@ static struct pci_driver rtl8139_pci_driver = { - name: RTL8139_MODULE_NAME, + name: MODNAME, id_table: rtl8139_pci_tbl, probe: rtl8139_init_one, remove: rtl8139_remove_one, diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/8390.c linux/drivers/net/8390.c --- v2.4.0-test11/linux/drivers/net/8390.c Mon Jun 26 18:06:55 2000 +++ linux/drivers/net/8390.c Sun Dec 3 17:45:22 2000 @@ -38,6 +38,7 @@ Paul Gortmaker : add kmod support for auto-loading of the 8390 module by all drivers that require it. Alan Cox : Spinlocking work, added 'BUG_83C690' + Paul Gortmaker : Separate out Tx timeout code from Tx path. Sources: The National Semiconductor LAN Databook, and the 3Com 3c503 databook. @@ -105,6 +106,7 @@ /* Index to functions. */ static void ei_tx_intr(struct net_device *dev); static void ei_tx_err(struct net_device *dev); +static void ei_tx_timeout(struct net_device *dev); static void ei_receive(struct net_device *dev); static void ei_rx_overrun(struct net_device *dev); @@ -161,6 +163,13 @@ printk(KERN_EMERG "%s: ei_open passed a non-existent device!\n", dev->name); return -ENXIO; } + + /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout + wrapper that does e.g. media check & then calls ei_tx_timeout. */ + if (dev->tx_timeout == NULL) + dev->tx_timeout = ei_tx_timeout; + if (dev->watchdog_timeo <= 0) + dev->watchdog_timeo = TX_TIMEOUT; /* * Grab the page lock so we own the register set, then call @@ -200,89 +209,66 @@ } /** - * ei_start_xmit - begin packet transmission - * @skb: packet to be sent - * @dev: network device to which packet is sent + * ei_tx_timeout - handle transmit time out condition + * @dev: network device which has apparently fallen asleep * - * Sends a packet to an 8390 network device. + * Called by kernel when device never acknowledges a transmit has + * completed (or failed) - i.e. never posted a Tx related interrupt. */ - -static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) + +void ei_tx_timeout(struct net_device *dev) { long e8390_base = dev->base_addr; struct ei_device *ei_local = (struct ei_device *) dev->priv; - int length, send_length, output_page; + int txsr, isr, tickssofar = jiffies - dev->trans_start; unsigned long flags; - /* - * If it has been too long since the last Tx, we assume the - * board has died and kick it. - */ - - if (netif_queue_stopped(dev)) { - /* Do timeouts, just like the 8003 driver. */ - int txsr; - int isr; - int tickssofar = jiffies - dev->trans_start; - - /* - * Need the page lock. Now see what went wrong. This bit is - * fast. - */ - - spin_lock_irqsave(&ei_local->page_lock, flags); - txsr = inb(e8390_base+EN0_TSR); - if (tickssofar < TX_TIMEOUT || (tickssofar < (TX_TIMEOUT+5) && ! (txsr & ENTSR_PTX))) - { - spin_unlock_irqrestore(&ei_local->page_lock, flags); - return 1; - } - - ei_local->stat.tx_errors++; - isr = inb(e8390_base+EN0_ISR); - if (!netif_running(dev)) { - spin_unlock_irqrestore(&ei_local->page_lock, flags); - printk(KERN_WARNING "%s: xmit on stopped card\n", dev->name); - return 1; - } - - /* - * Note that if the Tx posted a TX_ERR interrupt, then the - * error will have been handled from the interrupt handler - * and not here. Error statistics are handled there as well. - */ + ei_local->stat.tx_errors++; - printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", - dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : - (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); + spin_lock_irqsave(&ei_local->page_lock, flags); + txsr = inb(e8390_base+EN0_TSR); + isr = inb(e8390_base+EN0_ISR); + spin_unlock_irqrestore(&ei_local->page_lock, flags); - if (!isr && !ei_local->stat.tx_packets) - { - /* The 8390 probably hasn't gotten on the cable yet. */ - ei_local->interface_num ^= 1; /* Try a different xcvr. */ - } + printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", + dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : + (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar); - /* - * Play shuffle the locks, a reset on some chips takes a few - * mS. We very rarely hit this point. - */ - - spin_unlock_irqrestore(&ei_local->page_lock, flags); + if (!isr && !ei_local->stat.tx_packets) + { + /* The 8390 probably hasn't gotten on the cable yet. */ + ei_local->interface_num ^= 1; /* Try a different xcvr. */ + } - /* Ugly but a reset can be slow, yet must be protected */ + /* Ugly but a reset can be slow, yet must be protected */ - disable_irq_nosync(dev->irq); - spin_lock(&ei_local->page_lock); + disable_irq_nosync(dev->irq); + spin_lock(&ei_local->page_lock); - /* Try to restart the card. Perhaps the user has fixed something. */ - ei_reset_8390(dev); - NS8390_init(dev, 1); + /* Try to restart the card. Perhaps the user has fixed something. */ + ei_reset_8390(dev); + NS8390_init(dev, 1); - spin_unlock(&ei_local->page_lock); - enable_irq(dev->irq); - dev->trans_start = jiffies; - } + spin_unlock(&ei_local->page_lock); + enable_irq(dev->irq); + netif_wake_queue(dev); +} +/** + * ei_start_xmit - begin packet transmission + * @skb: packet to be sent + * @dev: network device to which packet is sent + * + * Sends a packet to an 8390 network device. + */ + +static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + long e8390_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *) dev->priv; + int length, send_length, output_page; + unsigned long flags; + length = skb->len; /* Mask interrupts from the ethercard. @@ -1147,6 +1133,7 @@ EXPORT_SYMBOL(ei_open); EXPORT_SYMBOL(ei_close); EXPORT_SYMBOL(ei_interrupt); +EXPORT_SYMBOL(ei_tx_timeout); EXPORT_SYMBOL(ethdev_init); EXPORT_SYMBOL(NS8390_init); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.4.0-test11/linux/drivers/net/acenic.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/acenic.c Mon Dec 11 12:39:45 2000 @@ -2223,7 +2223,7 @@ /* * Setup the bottom half rx ring refill handler */ - ap->immediate.next = NULL; + INIT_LIST_HEAD(&ap->immediate.list); ap->immediate.sync = 0; ap->immediate.routine = (void *)(void *)ace_bh; ap->immediate.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/aironet4500.h linux/drivers/net/aironet4500.h --- v2.4.0-test11/linux/drivers/net/aironet4500.h Tue Jul 11 11:12:23 2000 +++ linux/drivers/net/aironet4500.h Mon Dec 11 13:00:51 2000 @@ -1487,7 +1487,7 @@ volatile int ejected; volatile int bh_running; volatile int bh_active; - volatile int tx_chain_active; + volatile long tx_chain_active; volatile u16 enabled_interrupts; volatile u16 waiting_interrupts; volatile int interrupt_count; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c --- v2.4.0-test11/linux/drivers/net/aironet4500_core.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/aironet4500_core.c Mon Dec 11 12:39:45 2000 @@ -2868,7 +2868,7 @@ priv->command_semaphore_on = 0; priv->unlock_command_postponed = 0; - priv->immediate_bh.next = NULL; + INIT_LIST_HEAD(&priv->immediate_bh.list); priv->immediate_bh.sync = 0; priv->immediate_bh.routine = (void *)(void *)awc_bh; priv->immediate_bh.data = dev; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/apne.c linux/drivers/net/apne.c --- v2.4.0-test11/linux/drivers/net/apne.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/apne.c Mon Nov 27 17:11:26 2000 @@ -384,9 +384,8 @@ /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_get_8390_hdr " - "[DMAstat:%d][irqlock:%d][intr:%ld].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + "[DMAstat:%d][irqlock:%d][intr:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); return; } @@ -433,9 +432,8 @@ /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_block_input " - "[DMAstat:%d][irqlock:%d][intr:%ld].\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + "[DMAstat:%d][irqlock:%d][intr:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); return; } ei_status.dmaing |= 0x01; @@ -482,9 +480,8 @@ /* This *shouldn't* happen. If it does, it's the last thing you'll see */ if (ei_status.dmaing) { printk("%s: DMAing conflict in ne_block_output." - "[DMAstat:%d][irqlock:%d][intr:%ld]\n", - dev->name, ei_status.dmaing, ei_status.irqlock, - dev->interrupt); + "[DMAstat:%d][irqlock:%d][intr:%d]\n", + dev->name, ei_status.dmaing, ei_status.irqlock, dev->irq); return; } ei_status.dmaing |= 0x01; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c --- v2.4.0-test11/linux/drivers/net/appletalk/cops.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/appletalk/cops.c Sun Dec 3 17:45:22 2000 @@ -50,7 +50,6 @@ #include #include -#include #include #include @@ -220,8 +219,10 @@ int __init cops_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; - + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); + if(base_addr == 0 && io) base_addr=io; @@ -235,13 +236,9 @@ * Dayna cards don't autoprobe well at all, but if your card is * at IRQ 5 & IO 0x240 we find it every time. ;) JS */ - for(i=0; cops_portlist[i]; i++) { - int ioaddr = cops_portlist[i]; - if(check_region(ioaddr, COPS_IO_EXTENT)) - continue; - if(cops_probe1(dev, ioaddr) == 0) + for(i=0; cops_portlist[i]; i++) + if(cops_probe1(dev, cops_portlist[i]) == 0) return 0; - } return -ENODEV; } @@ -254,13 +251,17 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr) { struct cops_local *lp; - static unsigned version_printed = 0; - + static unsigned version_printed; int board = board_type; + int retval; if(cops_debug && version_printed++ == 0) printk("%s", version); + /* Grab the region so no one else tries to probe our ioports. */ + if (!request_region(ioaddr, COPS_IO_EXTENT, dev->name)) + return -EBUSY; + /* * Since this board has jumpered interrupts, allocate the interrupt * vector now. There is no point in waiting since no other device @@ -273,13 +274,14 @@ case 0: /* COPS AutoIRQ routine */ dev->irq = cops_irq(ioaddr, board); - if(!dev->irq) - return -EINVAL; /* No IRQ found on this port */ - break; + if(!dev->irq) { + retval = -EINVAL; /* No IRQ found on this port */ + goto err_out; + } case 1: - return -EINVAL; - break; + retval = -EINVAL; + goto err_out; /* Fixup for users that don't know that IRQ 2 is really * IRQ 9, or don't know which one to set. @@ -301,17 +303,22 @@ } /* Reserve any actual interrupt. */ - if(dev->irq && request_irq(dev->irq, &cops_interrupt, 0, cardname, dev)) - return -EINVAL; + if(dev->irq) { + retval = request_irq(dev->irq, &cops_interrupt, 0, dev->name, dev); + if (retval) + goto err_out; + } - /* Grab the region so no one else tries to probe our ioports. */ - request_region(ioaddr, COPS_IO_EXTENT, cardname); - dev->base_addr = ioaddr; + dev->base_addr = ioaddr; /* Initialize the private device structure. */ dev->priv = kmalloc(sizeof(struct cops_local), GFP_KERNEL); - if(dev->priv == NULL) - return -ENOMEM; + if(dev->priv == NULL) { + if (dev->irq) + free_irq(dev->irq, dev); + retval = -ENOMEM; + goto err_out; + } lp = (struct cops_local *)dev->priv; memset(lp, 0, sizeof(struct cops_local)); @@ -347,6 +354,10 @@ } return 0; + +err_out: + release_region(ioaddr, COPS_IO_EXTENT); + return retval; } static int __init cops_irq (int ioaddr, int board) @@ -426,10 +437,6 @@ cops_jumpstart(dev); /* Start the card up. */ netif_start_queue(dev); -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - return 0; } @@ -990,10 +997,6 @@ del_timer(&cops_timer); netif_stop_queue(dev); -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - return 0; } @@ -1039,8 +1042,7 @@ { /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ unregister_netdev(&cops0_dev); - if(cops0_dev.priv) - kfree(cops0_dev.priv); + kfree(cops0_dev.priv); if(cops0_dev.irq) free_irq(cops0_dev.irq, &cops0_dev); release_region(cops0_dev.base_addr, COPS_IO_EXTENT); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/appletalk/ipddp.c linux/drivers/net/appletalk/ipddp.c --- v2.4.0-test11/linux/drivers/net/appletalk/ipddp.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/appletalk/ipddp.c Sun Dec 3 17:45:22 2000 @@ -62,22 +62,12 @@ static int ipddp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); -static int ipddp_open(struct net_device *dev) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static int ipddp_close(struct net_device *dev) -{ - MOD_DEC_USE_COUNT; - return 0; -} - static int __init ipddp_init(struct net_device *dev) { static unsigned version_printed = 0; + SET_MODULE_OWNER(dev); + if (ipddp_debug && version_printed++ == 0) printk("%s", version); @@ -100,8 +90,6 @@ return -ENOMEM; memset(dev->priv,0,sizeof(struct net_device_stats)); - dev->open = ipddp_open; - dev->stop = ipddp_close; dev->get_stats = ipddp_get_stats; dev->do_ioctl = ipddp_ioctl; @@ -298,7 +286,7 @@ } } -static struct net_device dev_ipddp = { init: ipddp_init }; +static struct net_device dev_ipddp; MODULE_PARM(ipddp_mode, "i"); @@ -306,6 +294,7 @@ { int err; + dev_ipddp.init = ipddp_init; err=dev_alloc_name(&dev_ipddp, "ipddp%d"); if(err < 0) return err; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/appletalk/ltpc.c linux/drivers/net/appletalk/ltpc.c --- v2.4.0-test11/linux/drivers/net/appletalk/ltpc.c Fri Aug 4 18:18:48 2000 +++ linux/drivers/net/appletalk/ltpc.c Sun Dec 3 17:45:22 2000 @@ -206,11 +206,7 @@ static int irq=0; static int dma=0; -#ifdef MODULE #include -#include -#endif - #include #include #include @@ -710,22 +706,6 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev); static struct net_device_stats *ltpc_get_stats(struct net_device *dev); -static int ltpc_open(struct net_device *dev) -{ -#ifdef MODULE - MOD_INC_USE_COUNT; -#endif - return 0; -} - -static int ltpc_close(struct net_device *dev) -{ -#ifdef MODULE - MOD_DEC_USE_COUNT; -#endif - return 0; -} - static int read_30 ( struct net_device *dev) { lt_command c; @@ -921,9 +901,6 @@ memset(dev->priv, 0, sizeof(struct ltpc_private)); dev->get_stats = ltpc_get_stats; - dev->open = ltpc_open; - dev->stop = ltpc_close; - /* add the ltpc-specific things */ dev->do_ioctl = <pc_ioctl; @@ -1008,7 +985,7 @@ /* initialization stuff */ -int __init ltpc_probe_dma(int base) +static int __init ltpc_probe_dma(int base) { int dma = 0; int timeout; @@ -1087,6 +1064,8 @@ unsigned long flags; unsigned long f; + SET_MODULE_OWNER(dev); + save_flags(flags); /* probe for the I/O port address */ @@ -1273,11 +1252,7 @@ __setup("ltpc=", ltpc_setup); #endif /* MODULE */ -static struct net_device dev_ltpc = { - "", - 0, 0, 0, 0, - 0x0, 0, - 0, 0, 0, NULL, ltpc_probe }; +static struct net_device dev_ltpc; #ifdef MODULE MODULE_PARM(debug, "i"); @@ -1295,6 +1270,7 @@ "ltpc: Autoprobing is not recommended for modules\n"); /* Find a name for this unit */ + dev_ltpc.init = ltpc_probe; err=dev_alloc_name(&dev_ltpc,"lt%d"); if(err<0) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/arlan.c linux/drivers/net/arlan.c --- v2.4.0-test11/linux/drivers/net/arlan.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/arlan.c Tue Dec 5 12:29:38 2000 @@ -205,7 +205,7 @@ priv->card_polling_interval = 1; if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) - printk(KERN_DEBUG "arlan_command, %lx lock %x commandByte %x waiting %x incoming %x \n", + printk(KERN_DEBUG "arlan_command, %lx lock %lx commandByte %x waiting %x incoming %x \n", jiffies, priv->command_lock, READSHMB(arlan->commandByte), priv->waiting_command_mask, command_p); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/arlan.h linux/drivers/net/arlan.h --- v2.4.0-test11/linux/drivers/net/arlan.h Tue Jul 11 11:12:23 2000 +++ linux/drivers/net/arlan.h Mon Dec 11 13:01:00 2000 @@ -388,7 +388,7 @@ volatile int tx_chain_active; volatile int timer_chain_active; volatile int interrupt_ack_requested; - volatile int command_lock; + volatile long command_lock; volatile int rx_command_needed; volatile int tx_command_needed; volatile int waiting_command_mask; @@ -398,8 +398,8 @@ volatile int under_reset; volatile int under_config; volatile int rx_command_given; - volatile int tx_command_given; - volatile int interrupt_processing_active; + volatile long tx_command_given; + volatile long interrupt_processing_active; volatile long long last_tx_time; volatile long long last_rx_time; volatile long long last_rx_int_ack_time; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c --- v2.4.0-test11/linux/drivers/net/bagetlance.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/bagetlance.c Tue Dec 5 12:29:38 2000 @@ -224,9 +224,9 @@ /* copy function */ void *(*memcpy_f)( void *, const void *, size_t ); struct net_device_stats stats; -/* These two must be ints for set_bit() */ - int tx_full; - int lock; +/* These two must be longs for set_bit() */ + long tx_full; + long lock; }; /* I/O register access macros */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/daynaport.c linux/drivers/net/daynaport.c --- v2.4.0-test11/linux/drivers/net/daynaport.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/daynaport.c Sun Dec 3 17:48:19 2000 @@ -44,8 +44,6 @@ #include #include "8390.h" -extern int console_loglevel; - int ns8390_probe1(struct net_device *dev, int word16, char *name, int id, int prom, struct nubus_dev *ndev); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c --- v2.4.0-test11/linux/drivers/net/dgrs.c Mon Jun 19 13:30:58 2000 +++ linux/drivers/net/dgrs.c Tue Dec 5 12:29:38 2000 @@ -130,6 +130,14 @@ #include "dgrs_asstruct.h" #include "dgrs_bcomm.h" +#if LINUX_VERSION_CODE >= 0x20400 +static struct pci_device_id dgrs_pci_tbl[] __initdata = { + { SE6_PCI_VENDOR_ID, SE6_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, dgrs_pci_tbl); +#endif /* LINUX_VERSION_CODE >= 0x20400 */ + /* * Firmware. Compiled separately for local compilation, * but #included for Linux distribution. @@ -788,9 +796,6 @@ dgrs_open( struct net_device *dev ) { netif_start_queue(dev); - - MOD_INC_USE_COUNT; - return (0); } @@ -800,9 +805,6 @@ static int dgrs_close( struct net_device *dev ) { netif_stop_queue(dev); - - MOD_DEC_USE_COUNT; - return (0); } @@ -1268,6 +1270,7 @@ priv->devtbl[0] = dev; dev->init = dgrs_probe1; + SET_MODULE_OWNER(dev); ether_setup(dev); priv->next_dev = dgrs_root_dev; dgrs_root_dev = dev; @@ -1303,6 +1306,7 @@ privN->chan = i+1; priv->devtbl[i] = devN; devN->init = dgrs_initclone; + SET_MODULE_OWNER(dev); ether_setup(devN); privN->next_dev = dgrs_root_dev; dgrs_root_dev = devN; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c --- v2.4.0-test11/linux/drivers/net/dmfe.c Tue Jul 11 11:12:23 2000 +++ linux/drivers/net/dmfe.c Tue Dec 5 12:29:38 2000 @@ -393,6 +393,7 @@ dev = init_etherdev(NULL, sizeof(*db)); if (dev == NULL) goto err_out; + SET_MODULE_OWNER(dev); /* IO range check */ if (!request_region(pci_iobase, CHK_IO_SIZE(pdev, dev_rev), dev->name)) { @@ -461,12 +462,14 @@ static int dmfe_open(struct net_device *dev) { + int ret; struct dmfe_board_info *db = dev->priv; DMFE_DBUG(0, "dmfe_open", 0); - if (request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev)) - return -EAGAIN; + ret = request_irq(dev->irq, &dmfe_interrupt, SA_SHIRQ, dev->name, dev); + if (ret) + return ret; /* Allocated Tx/Rx descriptor memory */ db->desc_pool_ptr = kmalloc(sizeof(struct tx_desc) * DESC_ALL_CNT + 0x20, GFP_KERNEL | GFP_DMA); @@ -511,9 +514,6 @@ /* Initilize DM910X board */ dmfe_init_dm910x(dev); - /* Active System Interface */ - MOD_INC_USE_COUNT; - /* set and active a timer process */ init_timer(&db->timer); db->timer.expires = DMFE_TIMER_WUT; @@ -657,7 +657,7 @@ DELAY_5US; /* deleted timer */ - del_timer(&db->timer); + del_timer_sync(&db->timer); /* free interrupt */ free_irq(dev->irq, dev); @@ -668,8 +668,6 @@ /* free all descriptor memory and buffer memory */ kfree(db->desc_pool_ptr); kfree(db->buf_pool_ptr); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/dummy.c linux/drivers/net/dummy.c --- v2.4.0-test11/linux/drivers/net/dummy.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/dummy.c Sun Dec 3 17:45:22 2000 @@ -39,18 +39,6 @@ static int dummy_xmit(struct sk_buff *skb, struct net_device *dev); static struct net_device_stats *dummy_get_stats(struct net_device *dev); -static int dummy_open(struct net_device *dev) -{ - MOD_INC_USE_COUNT; - return 0; -} - -static int dummy_close(struct net_device *dev) -{ - MOD_DEC_USE_COUNT; - return 0; -} - /* fake multicast ability */ static void set_multicast_list(struct net_device *dev) { @@ -74,8 +62,6 @@ memset(dev->priv, 0, sizeof(struct net_device_stats)); dev->get_stats = dummy_get_stats; - dev->open = dummy_open; - dev->stop = dummy_close; dev->set_multicast_list = set_multicast_list; /* Fill in the fields of the device structure with ethernet-generic values. */ @@ -107,12 +93,17 @@ return dev->priv; } -static struct net_device dev_dummy = { init: dummy_init }; +static struct net_device dev_dummy; static int __init dummy_init_module(void) { + int err; + + dev_dummy.init = dummy_init; + SET_MODULE_OWNER(&dev_dummy); + /* Find a name for this unit */ - int err=dev_alloc_name(&dev_dummy,"dummy%d"); + err=dev_alloc_name(&dev_dummy,"dummy%d"); if(err<0) return err; if (register_netdev(&dev_dummy) != 0) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/e2100.c linux/drivers/net/e2100.c --- v2.4.0-test11/linux/drivers/net/e2100.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/e2100.c Tue Dec 5 12:29:38 2000 @@ -96,7 +96,7 @@ #define E21_TX_START_PG E21_RX_STOP_PG /* First page of TX buffer */ int e2100_probe(struct net_device *dev); -int e21_probe1(struct net_device *dev, int ioaddr); +static int e21_probe1(struct net_device *dev, int ioaddr); static int e21_open(struct net_device *dev); static void e21_reset_8390(struct net_device *dev); @@ -122,6 +122,8 @@ int *port; int base_addr = dev->base_addr; + SET_MODULE_OWNER(dev); + if (base_addr > 0x1ff) /* Check a single specified location. */ return e21_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ @@ -134,14 +136,14 @@ return -ENODEV; } -int __init e21_probe1(struct net_device *dev, int ioaddr) +static int __init e21_probe1(struct net_device *dev, int ioaddr) { int i, status, retval; unsigned char *station_addr = dev->dev_addr; static unsigned version_printed = 0; - if (!request_region(ioaddr, E21_IO_EXTENT, "e2100")) - return -ENODEV; + if (!request_region(ioaddr, E21_IO_EXTENT, dev->name)) + return -EBUSY; /* First check the station address for the Ctron prefix. */ if (inb(ioaddr + E21_SAPROM + 0) != 0x00 @@ -255,10 +257,10 @@ e21_open(struct net_device *dev) { short ioaddr = dev->base_addr; + int retval; - if (request_irq(dev->irq, ei_interrupt, 0, "e2100", dev)) { - return -EBUSY; - } + if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) + return retval; /* Set the interrupt line and memory base on the hardware. */ inb(ioaddr + E21_IRQ_LOW); @@ -270,7 +272,6 @@ outb(0, ioaddr + E21_ASIC + ((dev->mem_start >> 17) & 7)); ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -368,8 +369,6 @@ /* Double-check that the memory has been turned off, because really really bad things happen if it isn't. */ mem_off(ioaddr); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/eepro.c linux/drivers/net/eepro.c --- v2.4.0-test11/linux/drivers/net/eepro.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/eepro.c Tue Dec 5 12:29:38 2000 @@ -533,8 +533,9 @@ int __init eepro_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + SET_MODULE_OWNER(dev); #ifdef PnPWakeup /* XXXX for multiple cards should this only be run once? */ @@ -643,7 +644,7 @@ probes on the ISA bus. A good device probe avoids doing writes, and verifies that the correct device exists and functions. */ -int eepro_probe1(struct net_device *dev, short ioaddr) +static int eepro_probe1(struct net_device *dev, short ioaddr) { unsigned short station_addr[6], id, counter; int i,j, irqMask; @@ -1078,7 +1079,6 @@ /* enabling rx */ eepro_en_rx(ioaddr); - MOD_INC_USE_COUNT; return 0; } @@ -1234,7 +1234,6 @@ /* Update the statistics here. What statistics? */ - MOD_DEC_USE_COUNT; return 0; } @@ -1732,7 +1731,7 @@ static struct net_device dev_eepro[MAX_EEPRO]; static int io[MAX_EEPRO]; -static int irq[MAX_EEPRO] = { [0 ... MAX_EEPRO-1] = 0 }; +static int irq[MAX_EEPRO]; static int mem[MAX_EEPRO] = { /* Size of the rx buffer in KB */ [0 ... MAX_EEPRO-1] = RCV_DEFAULT_RAM/1024 }; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c --- v2.4.0-test11/linux/drivers/net/eepro100.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/eepro100.c Mon Nov 27 17:58:32 2000 @@ -29,21 +29,25 @@ static const char *version = "eepro100.c:v1.09j-t 9/29/99 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/eepro100.html\n" -"eepro100.c: $Revision: 1.33 $ 2000/05/24 Modified by Andrey V. Savochkin and others\n"; +"eepro100.c: $Revision: 1.35 $ 2000/11/17 Modified by Andrey V. Savochkin and others\n"; /* A few user-configurable values that apply to all boards. First set is undocumented and spelled per Intel recommendations. */ -static int congenb; /* Enable congestion control in the DP83840. */ +static int congenb /* = 0 */; /* Enable congestion control in the DP83840. */ static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */ static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */ /* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */ static int txdmacount = 128; -static int rxdmacount; +static int rxdmacount /* = 0 */; /* Set the copy breakpoint for the copy-only-tiny-buffer Rx method. Lower values use more memory, but are faster. */ +#if defined(__alpha__) || defined(__sparc__) +static int rx_copybreak = 1518; +#else static int rx_copybreak = 200; +#endif /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ static int max_interrupt_work = 20; @@ -136,26 +140,6 @@ } #endif /* CONFIG_EEPRO100_PM */ -#ifndef pci_resource_start -#define pci_resource_start(p, n) (p)->resource[n].start -#define pci_resource_len(p, n) ((p)->resource[n].end - (p)->resource[n].start) -#endif - -/* Because of changes in this area the driver may not compile for kernels - 2.3.43 - 2.3.47. --SAW */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) -#define netif_wake_queue(dev) do { \ - clear_bit(0, (void*)&dev->tbusy); \ - mark_bh(NET_BH); \ - } while(0) -#define netif_start_queue(dev) clear_bit(0, (void*)&dev->tbusy) -#define netif_stop_queue(dev) set_bit(0, (void*)&dev->tbusy) -#define netif_running(dev) dev->start -#define netdevice_start(dev) dev->start = 1 -#define netdevice_stop(dev) dev->start = 0 -#define netif_set_tx_timeout(dev, tf, tm) -#define dev_kfree_skb_irq(x) dev_kfree_skb(x) -#else #define netdevice_start(dev) #define netdevice_stop(dev) #define netif_set_tx_timeout(dev, tf, tm) \ @@ -163,51 +147,8 @@ (dev)->tx_timeout = (tf); \ (dev)->watchdog_timeo = (tm); \ } while(0) -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47) #define netif_device_attach(dev) netif_start_queue(dev) #define netif_device_detach(dev) netif_stop_queue(dev) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) -typedef u32 dma_addr_t; -static void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - ret = kmalloc(size, GFP_ATOMIC); - if (ret != NULL) { - *dma_handle = virt_to_bus(ret); - } - return ret; -} - -void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - kfree(vaddr); -} - -#define PCI_DMA_FROMDEVICE 0 -#define PCI_DMA_TODEVICE 0 - -extern inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, - size_t size, int direction) -{ - return virt_to_bus(ptr); -} - -extern inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, - size_t size, int direction) -{ -} - -extern inline void pci_dma_sync_single(struct pci_dev *hwdev, - dma_addr_t dma_handle, - size_t size, int direction) -{ -} -#endif #ifndef PCI_DEVICE_ID_INTEL_ID1029 #define PCI_DEVICE_ID_INTEL_ID1029 0x1029 @@ -450,6 +391,7 @@ TxUnderrun=0x1000, StatusComplete=0x8000, }; +#define CONFIG_DATA_SIZE 22 struct TxFD { /* Transmit frame descriptor set. */ s32 status; u32 link; /* void * */ @@ -461,6 +403,8 @@ s32 tx_buf_size0; /* Length of Tx frame. */ u32 tx_buf_addr1; /* void *, frame to be transmitted. */ s32 tx_buf_size1; /* Length of Tx frame. */ + /* the structure must have space for at least CONFIG_DATA_SIZE starting + * from tx_desc_addr field */ }; /* Multicast filter setting block. --SAW */ @@ -546,12 +490,12 @@ /* The parameters for a CmdConfigure operation. There are so many options that it would be difficult to document each bit. We mostly use the default or recommended settings. */ -const char i82557_config_cmd[22] = { +const char i82557_config_cmd[CONFIG_DATA_SIZE] = { 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0, 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */ 0x3f, 0x05, }; -const char i82558_config_cmd[22] = { +const char i82558_config_cmd[CONFIG_DATA_SIZE] = { 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */ 0, 0x2E, 0, 0x60, 0x08, 0x88, 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */ @@ -571,11 +515,10 @@ static int eepro100_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); static void eepro100_remove_one (struct pci_dev *pdev); - #ifdef CONFIG_EEPRO100_PM static void eepro100_suspend (struct pci_dev *pdev); static void eepro100_resume (struct pci_dev *pdev); -#endif /* CONFIG_EEPRO100_PM */ +#endif static int do_eeprom_cmd(long ioaddr, int cmd, int cmd_len); static int mdio_read(long ioaddr, int phy_id, int location); @@ -611,9 +554,9 @@ unsigned long ioaddr; int irq; int acpi_idle_state = 0, pm; - static int cards_found; + static int cards_found /* = 0 */; - static int did_version; /* Already printed version info. */ + static int did_version /* = 0 */; /* Already printed version info. */ if (speedo_debug > 0 && did_version++ == 0) printk(version); @@ -755,6 +698,7 @@ This takes less than 10usec and will easily finish before the next action. */ outl(PortReset, ioaddr + SCBPort); + udelay(10); if (eeprom[3] & 0x0100) product = "OEM i82557/i82558 10/100 Ethernet"; @@ -841,6 +785,7 @@ #endif /* kernel_bloat */ outl(PortReset, ioaddr + SCBPort); + udelay(10); /* Return the chip to its original power state. */ pci_set_power_state(pdev, acpi_idle_state); @@ -856,7 +801,8 @@ sp->tx_ring = tx_ring_space; sp->tx_ring_dma = tx_ring_dma; sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE); - sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE); + sp->lstats_dma = cpu_to_le32(TX_RING_ELEM_DMA(sp, TX_RING_SIZE)); + init_timer(&sp->timer); /* used in ioctl() */ sp->full_duplex = option >= 0 && (option & 0x10) ? 1 : 0; if (card_idx >= 0) { @@ -921,7 +867,7 @@ io_outw(EE_ENB, ee_addr); udelay(2); /* Terminate the EEPROM access. */ - io_outw(EE_ENB & ~EE_CS, ee_addr); udelay(4); + io_outw(EE_ENB & ~EE_CS, ee_addr); return retval; } @@ -960,6 +906,7 @@ { struct speedo_private *sp = (struct speedo_private *)dev->priv; long ioaddr = dev->base_addr; + int retval; if (speedo_debug > 1) printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq); @@ -977,9 +924,10 @@ sp->in_interrupt = 0; /* .. we can safely take handler calls during init. */ - if (request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev)) { + retval = request_irq(dev->irq, &speedo_interrupt, SA_SHIRQ, dev->name, dev); + if (retval) { MOD_DEC_USE_COUNT; - return -EBUSY; + return retval; } dev->if_port = sp->default_port; @@ -1030,7 +978,6 @@ to an alternate media type 2) to monitor Rx activity, and restart the Rx process if the receiver hangs. */ - init_timer(&sp->timer); sp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */ sp->timer.data = (unsigned long)dev; sp->timer.function = &speedo_timer; /* timer handler */ @@ -1055,29 +1002,32 @@ /* Set the segment registers to '0'. */ wait_for_cmd_done(ioaddr + SCBCmd); outl(0, ioaddr + SCBPointer); + inl(ioaddr + SCBPointer); /* XXX */ outb(RxAddrLoad, ioaddr + SCBCmd); wait_for_cmd_done(ioaddr + SCBCmd); outb(CUCmdBase, ioaddr + SCBCmd); - wait_for_cmd_done(ioaddr + SCBCmd); /* Load the statistics block and rx ring addresses. */ + wait_for_cmd_done(ioaddr + SCBCmd); outl(sp->lstats_dma, ioaddr + SCBPointer); + inl(ioaddr + SCBPointer); /* XXX */ outb(CUStatsAddr, ioaddr + SCBCmd); sp->lstats->done_marker = 0; - wait_for_cmd_done(ioaddr + SCBCmd); if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) { if (speedo_debug > 2) printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n", dev->name); } else { + wait_for_cmd_done(ioaddr + SCBCmd); outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE], ioaddr + SCBPointer); outb(RxStart, ioaddr + SCBCmd); - wait_for_cmd_done(ioaddr + SCBCmd); } + wait_for_cmd_done(ioaddr + SCBCmd); outb(CUDumpStats, ioaddr + SCBCmd); + udelay(30); /* Fill the first command with our physical address. */ { @@ -1143,14 +1093,19 @@ /* We haven't received a packet in a Long Time. We might have been bitten by the receiver hang bug. This can be cleared by sending a set multicast list command. */ - if (speedo_debug > 2) + if (speedo_debug > 3) printk(KERN_DEBUG "%s: Sending a multicast list set command" - " from a timer routine.\n", dev->name); + " from a timer routine," + " m=%d, j=%ld, l=%ld.\n", + dev->name, sp->rx_mode, jiffies, sp->last_rx_time); set_rx_mode(dev); } /* We must continue to monitor the media. */ sp->timer.expires = RUN_AT(2*HZ); /* 2.0 sec. */ add_timer(&sp->timer); +#if defined(timer_exit) + timer_exit(&sp->timer); +#endif } static void speedo_show_state(struct net_device *dev) @@ -1182,13 +1137,15 @@ (unsigned)sp->rx_ringp[i]->status : 0); #if 0 - long ioaddr = dev->base_addr; - int phy_num = sp->phy[0] & 0x1f; - for (i = 0; i < 16; i++) { - /* FIXME: what does it mean? --SAW */ - if (i == 6) i = 21; - printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n", - dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i)); + { + long ioaddr = dev->base_addr; + int phy_num = sp->phy[0] & 0x1f; + for (i = 0; i < 16; i++) { + /* FIXME: what does it mean? --SAW */ + if (i == 6) i = 21; + printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n", + dev->name, phy_num, i, mdio_read(ioaddr, phy_num, i)); + } } #endif @@ -1200,6 +1157,7 @@ { struct speedo_private *sp = (struct speedo_private *)dev->priv; struct RxFD *rxf, *last_rxf = NULL; + dma_addr_t last_rxf_dma = 0 /* to shut up the compiler */; int i; sp->cur_rx = 0; @@ -1214,26 +1172,31 @@ rxf = (struct RxFD *)skb->tail; sp->rx_ringp[i] = rxf; sp->rx_ring_dma[i] = - pci_map_single(sp->pdev, rxf, PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); + pci_map_single(sp->pdev, rxf, + PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_BIDIRECTIONAL); skb_reserve(skb, sizeof(struct RxFD)); if (last_rxf) { last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]); - pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[i-1], sizeof(struct RxFD), PCI_DMA_TODEVICE); + pci_dma_sync_single(sp->pdev, last_rxf_dma, + sizeof(struct RxFD), PCI_DMA_TODEVICE); } last_rxf = rxf; + last_rxf_dma = sp->rx_ring_dma[i]; rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */ rxf->link = 0; /* None yet. */ /* This field unused by i82557. */ rxf->rx_buf_addr = 0xffffffff; rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); - pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[i], sizeof(struct RxFD), PCI_DMA_TODEVICE); + pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[i], + sizeof(struct RxFD), PCI_DMA_TODEVICE); } sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE); /* Mark the last entry as end-of-list. */ last_rxf->status = cpu_to_le32(0xC0000002); /* '2' is flag value only. */ - pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1], sizeof(struct RxFD), PCI_DMA_TODEVICE); + pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1], + sizeof(struct RxFD), PCI_DMA_TODEVICE); sp->last_rxf = last_rxf; - sp->last_rxf_dma = sp->rx_ring_dma[RX_RING_SIZE-1]; + sp->last_rxf_dma = last_rxf_dma; } static void speedo_purge_tx(struct net_device *dev) @@ -1304,9 +1267,6 @@ sp->dirty_tx, sp->cur_tx, sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status); - /* Trigger a stats dump to give time before the reset. */ - speedo_get_stats(dev); - speedo_show_state(dev); #if 0 if ((status & 0x00C0) != 0x0080 @@ -1322,14 +1282,7 @@ #else { #endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) - start_bh_atomic(); - /* Ensure that timer routine doesn't run! */ - del_timer(&sp->timer); - end_bh_atomic(); -#else /* LINUX_VERSION_CODE */ del_timer_sync(&sp->timer); -#endif /* LINUX_VERSION_CODE */ /* Reset the Tx and Rx units. */ outl(PortReset, ioaddr + SCBPort); /* We may get spurious interrupts here. But I don't think that they @@ -1367,25 +1320,6 @@ long ioaddr = dev->base_addr; int entry; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) - if (test_bit(0, (void*)&dev->tbusy) != 0) { - int tickssofar = jiffies - dev->trans_start; - if (tickssofar < TX_TIMEOUT - 2) - return 1; - if (tickssofar < TX_TIMEOUT) { - /* Reap sent packets from the full Tx queue. */ - unsigned long flags; - spin_lock_irqsave(&sp->lock, flags); - wait_for_cmd_done(ioaddr + SCBCmd); - outw(SCBTriggerIntr, ioaddr + SCBCmd); - spin_unlock_irqrestore(&sp->lock, flags); - return 1; - } - speedo_tx_timeout(dev); - return 1; - } -#endif - { /* Prevent interrupts from changing the Tx ring from underneath us. */ unsigned long flags; @@ -1636,7 +1570,7 @@ /* Clear all interrupt sources. */ /* Will change from 0xfc00 to 0xff00 when we start handling FCP and ER interrupts --Dragan */ - outl(0xfc00, ioaddr + SCBStatus); + outw(0xfc00, ioaddr + SCBStatus); break; } } while (1); @@ -1668,7 +1602,8 @@ skb->dev = dev; skb_reserve(skb, sizeof(struct RxFD)); rxf->rx_buf_addr = 0xffffffff; - pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], sizeof(struct RxFD), PCI_DMA_TODEVICE); + pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], + sizeof(struct RxFD), PCI_DMA_TODEVICE); return rxf; } @@ -1681,7 +1616,8 @@ rxf->count = cpu_to_le32(PKT_BUF_SZ << 16); sp->last_rxf->link = cpu_to_le32(rxf_dma); sp->last_rxf->status &= cpu_to_le32(~0xC0000000); - pci_dma_sync_single(sp->pdev, sp->last_rxf_dma, sizeof(struct RxFD), PCI_DMA_TODEVICE); + pci_dma_sync_single(sp->pdev, sp->last_rxf_dma, + sizeof(struct RxFD), PCI_DMA_TODEVICE); sp->last_rxf = rxf; sp->last_rxf_dma = rxf_dma; } @@ -1742,7 +1678,6 @@ { struct speedo_private *sp = (struct speedo_private *)dev->priv; int entry = sp->cur_rx % RX_RING_SIZE; - int status; int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx; int alloc_ok = 1; @@ -1750,16 +1685,16 @@ printk(KERN_DEBUG " In speedo_rx().\n"); /* If we own the next entry, it's a new packet. Send it up. */ while (sp->rx_ringp[entry] != NULL) { + int status; int pkt_len; pci_dma_sync_single(sp->pdev, sp->rx_ring_dma[entry], sizeof(struct RxFD), PCI_DMA_FROMDEVICE); + status = le32_to_cpu(sp->rx_ringp[entry]->status); + pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; - if(!((status = le32_to_cpu(sp->rx_ringp[entry]->status)) & RxComplete)) { + if (!(status & RxComplete)) break; - } - - pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff; if (--rx_work_limit < 0) break; @@ -1812,7 +1747,6 @@ pkt_len); #endif } else { - void *temp; /* Pass up the already-filled skbuff. */ skb = sp->rx_skbuff[entry]; if (skb == NULL) { @@ -1821,7 +1755,7 @@ break; } sp->rx_skbuff[entry] = NULL; - temp = skb_put(skb, pkt_len); + skb_put(skb, pkt_len); sp->rx_ringp[entry] = NULL; pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry], PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE); @@ -1862,7 +1796,7 @@ dev->name, inw(ioaddr + SCBStatus)); /* Shut off the media monitoring timer. */ - del_timer(&sp->timer); + del_timer_sync(&sp->timer); /* Shutting down the chip nicely fails to disable flow control. So.. */ outl(PortPartialReset, ioaddr + SCBPort); @@ -1922,10 +1856,6 @@ update the stats with the previous dump results, and then trigger a new dump. - These problems are mitigated by the current /proc implementation, which - calls this routine first to judge the output length, and then to emit the - output. - Oh, and incoming frames are dropped while executing dump-stats! */ static struct net_device_stats * @@ -1968,6 +1898,7 @@ u16 *data = (u16 *)&rq->ifr_data; int phy = sp->phy[0] & 0x1f; int saved_acpi; + int t; switch(cmd) { case SIOCDEVPRIVATE: /* Get the address of the PHY in use. */ @@ -1978,30 +1909,20 @@ They are currently serialized only with MDIO access from the timer routine. 2000/05/09 SAW */ saved_acpi = pci_set_power_state(sp->pdev, 0); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) - start_bh_atomic(); + t = del_timer_sync(&sp->timer); data[3] = mdio_read(ioaddr, data[0], data[1]); - end_bh_atomic(); -#else /* LINUX_VERSION_CODE */ - del_timer_sync(&sp->timer); - data[3] = mdio_read(ioaddr, data[0], data[1]); - add_timer(&sp->timer); /* may be set to the past --SAW */ -#endif /* LINUX_VERSION_CODE */ + if (t) + add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; saved_acpi = pci_set_power_state(sp->pdev, 0); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) - start_bh_atomic(); - mdio_write(ioaddr, data[0], data[1], data[2]); - end_bh_atomic(); -#else /* LINUX_VERSION_CODE */ - del_timer_sync(&sp->timer); + t = del_timer_sync(&sp->timer); mdio_write(ioaddr, data[0], data[1], data[2]); - add_timer(&sp->timer); /* may be set to the past --SAW */ -#endif /* LINUX_VERSION_CODE */ + if (t) + add_timer(&sp->timer); /* may be set to the past --SAW */ pci_set_power_state(sp->pdev, saved_acpi); return 0; default: @@ -2060,7 +1981,7 @@ cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE)); config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr; /* Construct a full CmdConfig frame. */ - memcpy(config_cmd_data, i82558_config_cmd, sizeof(i82558_config_cmd)); + memcpy(config_cmd_data, i82558_config_cmd, CONFIG_DATA_SIZE); config_cmd_data[1] = (txfifo << 4) | rxfifo; config_cmd_data[4] = rxdmacount; config_cmd_data[5] = txdmacount + 0x80; @@ -2186,7 +2107,8 @@ mc_setup_frm->link = cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE)); - pci_dma_sync_single(sp->pdev, mc_blk->frame_dma, mc_blk->len, PCI_DMA_TODEVICE); + pci_dma_sync_single(sp->pdev, mc_blk->frame_dma, + mc_blk->len, PCI_DMA_TODEVICE); wait_for_cmd_done(ioaddr + SCBCmd); clear_suspend(last_cmd); @@ -2207,9 +2129,7 @@ sp->rx_mode = new_rx_mode; } - #ifdef CONFIG_EEPRO100_PM - static void eepro100_suspend(struct pci_dev *pdev) { struct net_device *dev = pdev->driver_data; @@ -2241,7 +2161,6 @@ sp->flow_ctrl = sp->partner = 0; set_rx_mode(dev); } - #endif /* CONFIG_EEPRO100_PM */ static void __devexit eepro100_remove_one (struct pci_dev *pdev) @@ -2284,7 +2203,6 @@ id_table: eepro100_pci_tbl, probe: eepro100_init_one, remove: eepro100_remove_one, - #ifdef CONFIG_EEPRO100_PM suspend: eepro100_suspend, resume: eepro100_resume, diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c --- v2.4.0-test11/linux/drivers/net/eexpress.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/eexpress.c Tue Dec 5 12:29:38 2000 @@ -344,6 +344,8 @@ static unsigned short ports[] = { 0x300,0x310,0x270,0x320,0x340,0 }; unsigned short ioaddr = dev->base_addr; + SET_MODULE_OWNER(dev); + dev->if_port = 0xff; /* not set */ #ifdef CONFIG_MCA @@ -420,7 +422,7 @@ static int eexp_open(struct net_device *dev) { - int irq = dev->irq; + int ret; unsigned short ioaddr = dev->base_addr; struct net_local *lp = (struct net_local *)dev->priv; @@ -428,11 +430,11 @@ printk(KERN_DEBUG "%s: eexp_open()\n", dev->name); #endif - if (!irq || !irqrmap[irq]) + if (!dev->irq || !irqrmap[dev->irq]) return -ENXIO; - if (request_irq(irq,&eexp_irq,0,"EtherExpress",dev)) - return -EAGAIN; + ret = request_irq(dev->irq,&eexp_irq,0,dev->name,dev); + if (ret) return ret; request_region(ioaddr, EEXP_IO_EXTENT, "EtherExpress"); request_region(ioaddr+0x4000, 16, "EtherExpress shadow"); @@ -445,7 +447,6 @@ } eexp_hw_init586(dev); - MOD_INC_USE_COUNT; netif_start_queue(dev); #if NET_DEBUG > 6 printk(KERN_DEBUG "%s: leaving eexp_open()\n", dev->name); @@ -477,7 +478,6 @@ release_region(ioaddr+0x8000, 16); release_region(ioaddr+0xc000, 16); - MOD_DEC_USE_COUNT; return 0; } @@ -1625,14 +1625,9 @@ #define EEXP_MAX_CARDS 4 /* max number of cards to support */ -static struct net_device dev_eexp[EEXP_MAX_CARDS] = -{ - { "", - 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, express_probe }, -}; - -static int irq[EEXP_MAX_CARDS] = {0, }; -static int io[EEXP_MAX_CARDS] = {0, }; +static struct net_device dev_eexp[EEXP_MAX_CARDS]; +static int irq[EEXP_MAX_CARDS]; +static int io[EEXP_MAX_CARDS]; MODULE_PARM(io, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(EEXP_MAX_CARDS) "i"); @@ -1649,6 +1644,7 @@ struct net_device *dev = &dev_eexp[this_dev]; dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; + dev->init = express_probe; if (io[this_dev] == 0) { if (this_dev) break; printk(KERN_NOTICE "eexpress.c: Module autoprobe not recommended, give io=xx.\n"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/eql.c linux/drivers/net/eql.c --- v2.4.0-test11/linux/drivers/net/eql.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/eql.c Sun Dec 3 17:45:22 2000 @@ -201,6 +201,8 @@ /* static unsigned num_masters = 0; */ equalizer_t *eql = 0; + SET_MODULE_OWNER(dev); + if ( version_printed++ == 0 && eql_debug > 0) printk(version); /* @@ -259,8 +261,6 @@ equalizer_t *eql = (equalizer_t *) dev->priv; slave_queue_t *new_queue; - MOD_INC_USE_COUNT; - #ifdef EQL_DEBUG if (eql_debug >= 5) printk ("%s: open\n", dev->name); @@ -284,7 +284,6 @@ return 0; } - MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -310,7 +309,6 @@ eql_delete_slave_queue (eql->queue); - MOD_DEC_USE_COUNT; return 0; } @@ -985,14 +983,12 @@ } } -static struct net_device dev_eql = -{ - name: "eql", - init: eql_init, -}; +static struct net_device dev_eql; static int __init eql_init_module(void) { + strcpy(dev_eql.name, "eql"); + dev_eql.init = eql_init; if (register_netdev(&dev_eql) != 0) { printk("eql: register_netdev() returned non-zero.\n"); return -EIO; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/es3210.c linux/drivers/net/es3210.c --- v2.4.0-test11/linux/drivers/net/es3210.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/es3210.c Tue Dec 5 12:29:38 2000 @@ -62,7 +62,7 @@ #include "8390.h" int es_probe(struct net_device *dev); -int es_probe1(struct net_device *dev, int ioaddr); +static int es_probe1(struct net_device *dev, int ioaddr); static int es_open(struct net_device *dev); static int es_close(struct net_device *dev); @@ -128,6 +128,8 @@ { unsigned short ioaddr = dev->base_addr; + SET_MODULE_OWNER(dev); + if (ioaddr > 0x1ff) /* Check a single specified location. */ return es_probe1(dev, ioaddr); else if (ioaddr > 0) /* Don't probe at all. */ @@ -148,7 +150,7 @@ return -ENODEV; } -int __init es_probe1(struct net_device *dev, int ioaddr) +static int __init es_probe1(struct net_device *dev, int ioaddr) { int i, retval; unsigned long eisa_id; @@ -357,9 +359,6 @@ static int es_open(struct net_device *dev) { ei_open(dev); - - MOD_INC_USE_COUNT; - return 0; } @@ -370,24 +369,13 @@ printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - - MOD_DEC_USE_COUNT; - return 0; } #ifdef MODULE #define MAX_ES_CARDS 4 /* Max number of ES3210 cards per module */ #define NAMELEN 8 /* # of chars for storing dev->name */ -static struct net_device dev_es3210[MAX_ES_CARDS] = { - { - "", /* device name is inserted by net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - +static struct net_device dev_es3210[MAX_ES_CARDS]; static int io[MAX_ES_CARDS]; static int irq[MAX_ES_CARDS]; static int mem[MAX_ES_CARDS]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c --- v2.4.0-test11/linux/drivers/net/eth16i.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/eth16i.c Mon Dec 11 13:38:29 2000 @@ -440,8 +440,10 @@ { int i; int ioaddr; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + SET_MODULE_OWNER(dev); + if(eth16i_debug > 4) printk(KERN_DEBUG "Probing started for %s\n", cardname); @@ -979,8 +981,6 @@ outw(ETH16I_INTR_ON, ioaddr + TX_INTR_REG); netif_start_queue(dev); - MOD_INC_USE_COUNT; - return 0; } @@ -1006,8 +1006,6 @@ /* outw(0xffff, ioaddr + TX_STATUS_REG); */ outb(0x00, ioaddr + CONFIG_REG_1); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ethertap.c linux/drivers/net/ethertap.c --- v2.4.0-test11/linux/drivers/net/ethertap.c Thu May 4 11:31:21 2000 +++ linux/drivers/net/ethertap.c Mon Dec 11 13:38:29 2000 @@ -67,6 +67,8 @@ int __init ethertap_probe(struct net_device *dev) { + SET_MODULE_OWNER(dev); + memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6); if (dev->mem_start & 0xf) ethertap_debug = dev->mem_start & 0x7; @@ -116,13 +118,9 @@ if (ethertap_debug > 2) printk("%s: Doing ethertap_open()...", dev->name); - MOD_INC_USE_COUNT; - lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx); - if (lp->nl == NULL) { - MOD_DEC_USE_COUNT; + if (lp->nl == NULL) return -ENOBUFS; - } netif_start_queue(dev); return 0; } @@ -324,7 +322,6 @@ sock_release(sk->socket); } - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c --- v2.4.0-test11/linux/drivers/net/ewrk3.c Fri Aug 11 15:57:57 2000 +++ linux/drivers/net/ewrk3.c Mon Dec 11 13:38:29 2000 @@ -350,6 +350,8 @@ int tmp = num_ewrk3s, status = -ENODEV; u_long iobase = dev->base_addr; + SET_MODULE_OWNER(dev); + if ((iobase == 0) && loading_module) { printk("Autoprobing is not supported when loading a module based driver.\n"); status = -EIO; @@ -681,8 +683,6 @@ return -EINVAL; } - MOD_INC_USE_COUNT; - return status; } @@ -1132,8 +1132,6 @@ if (!lp->hard_strapped) { free_irq(dev->irq, dev); } - MOD_DEC_USE_COUNT; - return 0; } @@ -1860,15 +1858,7 @@ } #ifdef MODULE -static char devicename[9] = -{0,}; -static struct net_device thisEthwrk = -{ - devicename, /* device name is inserted by /linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x300, 5, /* I/O address, IRQ */ - 0, 0, 0, NULL, ewrk3_probe}; - +static struct net_device thisEthwrk; static int io = 0x300; /* <--- EDIT THESE LINES FOR YOUR CONFIGURATION */ static int irq = 5; /* or use the insmod io= irq= options */ @@ -1879,6 +1869,7 @@ { thisEthwrk.base_addr = io; thisEthwrk.irq = irq; + thisEthwrk.init = ewrk3_probe; if (register_netdev(&thisEthwrk) != 0) return -EIO; return 0; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c --- v2.4.0-test11/linux/drivers/net/fmv18x.c Sun Nov 19 18:44:10 2000 +++ linux/drivers/net/fmv18x.c Mon Dec 11 13:38:29 2000 @@ -134,6 +134,8 @@ int i; int base_addr = dev->base_addr; + SET_MODULE_OWNER(dev); + if (base_addr > 0x1ff) /* Check a single specified location. */ return fmv18x_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ @@ -319,8 +321,6 @@ /* Enable both Tx and Rx interrupts */ outw(0x8182, ioaddr+TX_INTR); - MOD_INC_USE_COUNT; - return 0; } @@ -568,8 +568,6 @@ /* Power-down the chip. Green, green, green! */ outb(0x00, ioaddr + CONFIG_1); - - MOD_DEC_USE_COUNT; /* Set the ethernet adaptor disable IRQ */ outb(0x00, ioaddr + FJ_CONFIG1); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hamachi.c linux/drivers/net/hamachi.c --- v2.4.0-test11/linux/drivers/net/hamachi.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/hamachi.c Mon Dec 11 13:38:29 2000 @@ -580,6 +580,7 @@ iounmap((char *)ioaddr); return -ENOMEM; } + SET_MODULE_OWNER(dev); #ifdef TX_CHECKSUM printk("check that skbcopy in ip_queue_xmit isn't happening\n"); @@ -787,12 +788,9 @@ u_int32_t rx_int_var, tx_int_var; u_int16_t fifo_info; - MOD_INC_USE_COUNT; - - if (request_irq(dev->irq, &hamachi_interrupt, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + i = request_irq(dev->irq, &hamachi_interrupt, SA_SHIRQ, dev->name, dev); + if (i) + return i; if (hamachi_debug > 1) printk(KERN_DEBUG "%s: hamachi_open() irq %d.\n", @@ -1753,8 +1751,6 @@ } writeb(0x00, ioaddr + LEDCtrl); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hamradio/6pack.h linux/drivers/net/hamradio/6pack.h --- v2.4.0-test11/linux/drivers/net/hamradio/6pack.h Wed Aug 18 11:38:51 1999 +++ linux/drivers/net/hamradio/6pack.h Sun Dec 3 17:45:22 2000 @@ -101,7 +101,8 @@ int mtu; /* Our mtu (to spot changes!) */ int buffsize; /* Max buffers sizes */ - unsigned char flags; /* Flag values/ mode etc */ + unsigned long flags; /* Flag values/ mode etc */ + /* long req'd for set_bit --RR */ unsigned char mode; /* 6pack mode */ /* 6pack stuff */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c --- v2.4.0-test11/linux/drivers/net/hamradio/baycom_epp.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/hamradio/baycom_epp.c Mon Dec 11 13:23:31 2000 @@ -1023,7 +1023,8 @@ struct baycom_state *bc; struct parport *pp; const struct tq_struct run_bh = { - 0, 0, (void *)(void *)epp_bh, dev + routine: (void *)(void *)epp_bh, + data: dev }; unsigned int i, j; unsigned char tmp[128]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c --- v2.4.0-test11/linux/drivers/net/hamradio/hdlcdrv.c Thu May 4 11:31:21 2000 +++ linux/drivers/net/hamradio/hdlcdrv.c Mon Dec 11 13:41:41 2000 @@ -287,7 +287,7 @@ /* ---------------------------------------------------------------------- */ -static void inline do_kiss_params(struct hdlcdrv_state *s, +static inline void do_kiss_params(struct hdlcdrv_state *s, unsigned char *data, unsigned long len) { @@ -889,14 +889,7 @@ /* --------------------------------------------------------------------- */ -#ifdef MODULE - -MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); -MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder"); - -/* --------------------------------------------------------------------- */ - -int __init init_module(void) +static int __init hdlcdrv_init_driver(void) { printk(KERN_INFO "hdlcdrv: (C) 1996-2000 Thomas Sailer HB9JNX/AE4WA\n"); printk(KERN_INFO "hdlcdrv: version 0.8 compiled " __TIME__ " " __DATE__ "\n"); @@ -905,10 +898,16 @@ /* --------------------------------------------------------------------- */ -void cleanup_module(void) +static void __exit hdlcdrv_cleanup_driver(void) { printk(KERN_INFO "hdlcdrv: cleanup\n"); } -#endif /* MODULE */ +/* --------------------------------------------------------------------- */ + +MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu"); +MODULE_DESCRIPTION("Packet Radio network interface HDLC encoder/decoder"); +module_init(hdlcdrv_init_driver); +module_exit(hdlcdrv_cleanup_driver); + /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hamradio/mkiss.h linux/drivers/net/hamradio/mkiss.h --- v2.4.0-test11/linux/drivers/net/hamradio/mkiss.h Wed Aug 18 11:38:50 1999 +++ linux/drivers/net/hamradio/mkiss.h Sun Dec 3 17:45:22 2000 @@ -42,7 +42,8 @@ int buffsize; /* Max buffers sizes */ - unsigned char flags; /* Flag values/ mode etc */ + unsigned long flags; /* Flag values/ mode etc */ + /* long req'd: used by set_bit --RR */ #define AXF_INUSE 0 /* Channel in use */ #define AXF_ESCAPE 1 /* ESC received */ #define AXF_ERROR 2 /* Parity, etc. error */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c --- v2.4.0-test11/linux/drivers/net/hp-plus.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/hp-plus.c Mon Dec 11 13:38:29 2000 @@ -120,7 +120,9 @@ int __init hp_plus_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); if (base_addr > 0x1ff) /* Check a single specified location. */ return hpp_probe1(dev, base_addr); @@ -270,7 +272,6 @@ outw(Perf_Page, ioaddr + HP_PAGING); ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -285,7 +286,6 @@ outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset, ioaddr + HPP_OPTION); - MOD_DEC_USE_COUNT; return 0; } @@ -402,17 +402,9 @@ #ifdef MODULE #define MAX_HPP_CARDS 4 /* Max number of HPP cards per module */ -static struct net_device dev_hpp[MAX_HPP_CARDS] = { - { - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_HPP_CARDS] = { 0, }; -static int irq[MAX_HPP_CARDS] = { 0, }; +static struct net_device dev_hpp[MAX_HPP_CARDS]; +static int io[MAX_HPP_CARDS]; +static int irq[MAX_HPP_CARDS]; MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HPP_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_HPP_CARDS) "i"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hp.c linux/drivers/net/hp.c --- v2.4.0-test11/linux/drivers/net/hp.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/hp.c Mon Dec 11 13:38:29 2000 @@ -57,7 +57,7 @@ #define HP_16BSTOP_PG 0xFF /* Same, for 16 bit cards. */ int hp_probe(struct net_device *dev); -int hp_probe1(struct net_device *dev, int ioaddr); +static int hp_probe1(struct net_device *dev, int ioaddr); static int hp_open(struct net_device *dev); static int hp_close(struct net_device *dev); @@ -83,7 +83,9 @@ int __init hp_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); if (base_addr > 0x1ff) /* Check a single specified location. */ return hp_probe1(dev, base_addr); @@ -97,14 +99,14 @@ return -ENODEV; } -int __init hp_probe1(struct net_device *dev, int ioaddr) +static int __init hp_probe1(struct net_device *dev, int ioaddr) { int i, retval, board_id, wordmode; const char *name; static unsigned version_printed; if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) - return -ENODEV; + return -EBUSY; /* Check for the HP physical address, 08 00 09 xx xx xx. */ /* This really isn't good enough: we may pick up HP LANCE boards @@ -206,7 +208,6 @@ hp_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -214,7 +215,6 @@ hp_close(struct net_device *dev) { ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } @@ -373,17 +373,9 @@ #ifdef MODULE #define MAX_HP_CARDS 4 /* Max number of HP cards per module */ -static struct net_device dev_hp[MAX_HP_CARDS] = { - { - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_HP_CARDS] = { 0, }; -static int irq[MAX_HP_CARDS] = { 0, }; +static struct net_device dev_hp[MAX_HP_CARDS]; +static int io[MAX_HP_CARDS]; +static int irq[MAX_HP_CARDS]; MODULE_PARM(io, "1-" __MODULE_STRING(MAX_HP_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_HP_CARDS) "i"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hp100.c linux/drivers/net/hp100.c --- v2.4.0-test11/linux/drivers/net/hp100.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/hp100.c Mon Dec 11 13:38:29 2000 @@ -274,6 +274,17 @@ #define HP100_PCI_IDS_SIZE (sizeof(hp100_pci_ids)/sizeof(struct hp100_pci_id)) +#if LINUX_VERSION_CODE >= 0x20400 +static struct pci_device_id hp100_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585B, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_ENET100VG4, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_COMPEX2, PCI_DEVICE_ID_COMPEX2_100VG, PCI_ANY_ID, PCI_ANY_ID, }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, hp100_pci_tbl); +#endif /* LINUX_VERSION_CODE >= 0x20400 */ + static int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO; static int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX; static int hp100_mode = 1; @@ -761,6 +772,7 @@ /* Reset statistics (counters) */ hp100_clear_stats( lp, ioaddr ); + SET_MODULE_OWNER(dev); ether_setup( dev ); /* If busmaster mode is wanted, a dma-capable memory area is needed for @@ -1154,8 +1166,6 @@ return -EAGAIN; } - MOD_INC_USE_COUNT; - dev->trans_start = jiffies; netif_start_queue(dev); @@ -1201,7 +1211,6 @@ printk( "hp100: %s: close LSW = 0x%x\n", dev->name, hp100_inw(OPTION_LSW) ); #endif - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/hplance.c linux/drivers/net/hplance.c --- v2.4.0-test11/linux/drivers/net/hplance.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/hplance.c Tue Dec 5 12:31:01 2000 @@ -116,6 +116,7 @@ return -ENOMEM; memset(dev->priv, 0, sizeof(struct hplance_private)); #endif + SET_MODULE_OWNER(dev); printk("%s: HP LANCE; select code %d, addr", dev->name, scode); @@ -212,7 +213,6 @@ /* enable interrupts at board level. */ writeb(LE_IE, &(hpregs->status)); - MOD_INC_USE_COUNT; return 0; } @@ -222,7 +222,6 @@ struct hplance_reg *hpregs = (struct hplance_reg *)lp->base; writeb(0,&(hpregs->status)); /* disable interrupts at boardlevel */ lance_close(dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ibmlana.c linux/drivers/net/ibmlana.c --- v2.4.0-test11/linux/drivers/net/ibmlana.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/ibmlana.c Mon Dec 11 13:38:29 2000 @@ -87,9 +87,7 @@ #include #include -#ifdef MODULE #include -#endif #include #include @@ -877,9 +875,6 @@ dev->interrupt = 0; dev->tbusy = 0; dev->start = 1; -#endif - -#ifdef MODULE MOD_INC_USE_COUNT; #endif @@ -897,7 +892,7 @@ free_irq(dev->irq, dev); dev->irq = 0; -#ifdef MODULE +#if (LINUX_VERSION_CODE < 0x02032a) MOD_DEC_USE_COUNT; #endif @@ -1043,6 +1038,10 @@ ibmlana_priv *priv; ibmlana_medium medium; +#if (LINUX_VERSION_CODE >= 0x02032a) + SET_MODULE_OWNER(dev); +#endif + /* can't work without an MCA bus ;-) */ if (MCA_bus == 0) @@ -1192,14 +1191,11 @@ #define DEVMAX 5 -static struct IBMLANA_NETDEV moddevs[DEVMAX] = { - { init: ibmlana_probe }, { init: ibmlana_probe }, - { init: ibmlana_probe }, { init: ibmlana_probe }, - { init: ibmlana_probe } -}; - -int irq = 0; -int io = 0; +static struct IBMLANA_NETDEV moddevs[DEVMAX]; +static int irq; +static int io; +MODULE_PARM(irq, "i"); +MODULE_PARM(io, "i"); int init_module(void) { @@ -1207,7 +1203,9 @@ startslot = 0; for (z = 0; z < DEVMAX; z++) { - strcpy(moddevs[z].name, " "); + moddevs[z].init = ibmlana_probe; + moddevs[z].irq = irq; + moddevs[z].base_addr = io; res = register_netdev(moddevs + z); if (res != 0) return (z > 0) ? 0 : -EIO; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c --- v2.4.0-test11/linux/drivers/net/ioc3-eth.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/ioc3-eth.c Tue Nov 28 21:42:04 2000 @@ -69,7 +69,7 @@ #include /* 32 RX buffers. This is tunable in the range of 16 <= x < 512. */ -#define RX_BUFFS 32 +#define RX_BUFFS 64 /* Private ioctls that de facto are well known and used for examply by mii-tool. */ @@ -96,6 +96,7 @@ int tx_pi; /* TX producer index */ int txqlen; u32 emcr, ehar_h, ehar_l; + struct timer_list negtimer; spinlock_t ioc3_lock; }; @@ -104,7 +105,7 @@ static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev); static void ioc3_timeout(struct net_device *dev); static inline unsigned int ioc3_hash(const unsigned char *addr); -static void ioc3_stop(struct net_device *dev); +static inline void ioc3_stop(struct net_device *dev); static void ioc3_init(struct net_device *dev); static const char ioc3_str[] = "IOC3 Ethernet"; @@ -381,17 +382,20 @@ ioc3->micr = (phy << MICR_PHYADDR_SHIFT) | reg | MICR_READTRIG; while (ioc3->micr & MICR_BUSY); - return ioc3->midr & MIDR_DATA_MASK; + return ioc3->midr_r & MIDR_DATA_MASK; } static void mii_write(struct ioc3 *ioc3, int phy, int reg, u16 data) { while (ioc3->micr & MICR_BUSY); - ioc3->midr = data; + ioc3->midr_w = data; ioc3->micr = (phy << MICR_PHYADDR_SHIFT) | reg; while (ioc3->micr & MICR_BUSY); } +static int ioc3_mii_init(struct net_device *dev, struct ioc3_private *ip, + struct ioc3 *ioc3); + static struct net_device_stats *ioc3_get_stats(struct net_device *dev) { struct ioc3_private *ip = (struct ioc3_private *) dev->priv; @@ -426,6 +430,8 @@ skb->protocol = eth_type_trans(skb, dev); netif_rx(skb); + ip->rx_skbs[rx_entry] = NULL; /* Poison */ + new_skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); if (!new_skb) { /* Ouch, drop packet and just recycle packet @@ -545,6 +551,7 @@ ioc3_stop(dev); ioc3_init(dev); + ioc3_mii_init(dev, ip, ioc3); dev->trans_start = jiffies; netif_wake_queue(dev); @@ -563,6 +570,7 @@ u32 eisr; eisr = ioc3->eisr & enabled; + while (eisr) { ioc3->eisr = eisr; ioc3->eisr; /* Flush */ @@ -579,46 +587,43 @@ } } -/* One day this will do the autonegotiation. */ -int ioc3_mii_init(struct net_device *dev, struct ioc3_private *ip, - struct ioc3 *ioc3) +static void negotiate(unsigned long data) { - u16 word, mii0, mii_status, mii2, mii3, mii4; - u32 vendor, model, rev; + struct net_device *dev = (struct net_device *) data; + struct ioc3_private *ip = (struct ioc3_private *) dev->priv; + struct ioc3 *ioc3 = ip->regs; + + mod_timer(&ip->negtimer, jiffies + 20 * HZ); +} + +static int ioc3_mii_init(struct net_device *dev, struct ioc3_private *ip, + struct ioc3 *ioc3) +{ + u16 word, mii0; int i, phy; spin_lock_irq(&ip->ioc3_lock); phy = -1; for (i = 0; i < 32; i++) { word = mii_read(ioc3, i, 2); - if ((word != 0xffff) & (word != 0x0000)) { + if ((word != 0xffff) && (word != 0x0000)) { phy = i; break; /* Found a PHY */ } } if (phy == -1) { spin_unlock_irq(&ip->ioc3_lock); - printk("Didn't find a PHY, goodbye.\n"); return -ENODEV; } ip->phy = phy; - mii0 = mii_read(ioc3, phy, 0); - mii_status = mii_read(ioc3, phy, 1); - mii2 = mii_read(ioc3, phy, 2); - mii3 = mii_read(ioc3, phy, 3); - mii4 = mii_read(ioc3, phy, 4); - vendor = (mii2 << 12) | (mii3 >> 4); - model = (mii3 >> 4) & 0x3f; - rev = mii3 & 0xf; - printk("Ok, using PHY %d, vendor 0x%x, model %d, rev %d.\n", - phy, vendor, model, rev); - printk(KERN_INFO "%s: MII transceiver found at MDIO address " - "%d, config %4.4x status %4.4x.\n", - dev->name, phy, mii0, mii_status); - /* Autonegotiate 100mbit and fullduplex. */ - mii_write(ioc3, phy, 0, mii0 | 0x3100); + mii0 = mii_read(ioc3, ip->phy, 0); + mii_write(ioc3, ip->phy, 0, mii0 | 0x3100); + + ip->negtimer.function = &negotiate; + ip->negtimer.data = (unsigned long) dev; + mod_timer(&ip->negtimer, jiffies); /* Run it now */ spin_unlock_irq(&ip->ioc3_lock); @@ -670,22 +675,26 @@ struct sk_buff *skb; int rx_entry, n_entry; - ioc3_clean_tx_ring(ip); - ip->txr = NULL; - free_pages((unsigned long)ip->txr, 2); - - n_entry = ip->rx_ci; - rx_entry = ip->rx_pi; + if (ip->txr) { + ioc3_clean_tx_ring(ip); + free_pages((unsigned long)ip->txr, 2); + ip->txr = NULL; + } + + if (ip->rxr) { + n_entry = ip->rx_ci; + rx_entry = ip->rx_pi; + + while (n_entry != rx_entry) { + skb = ip->rx_skbs[n_entry]; + if (skb) + dev_kfree_skb_any(skb); - while (n_entry != rx_entry) { - skb = ip->rx_skbs[n_entry]; - if (skb) - dev_kfree_skb_any(skb); - - n_entry = (n_entry + 1) & 511; + n_entry = (n_entry + 1) & 511; + } + free_page((unsigned long)ip->rxr); + ip->rxr = NULL; } - free_page((unsigned long)ip->rxr); - ip->rxr = NULL; } static void @@ -698,7 +707,7 @@ if (ip->rxr == NULL) { /* Allocate and initialize rx ring. 4kb = 512 entries */ - ip->rxr = (unsigned long *) get_free_page(GFP_KERNEL); + ip->rxr = (unsigned long *) get_free_page(GFP_KERNEL|GFP_ATOMIC); rxr = (unsigned long *) ip->rxr; /* Now the rx buffers. The RX ring may be larger but @@ -707,7 +716,7 @@ for (i = 0; i < RX_BUFFS; i++) { struct sk_buff *skb; - skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, 0); + skb = ioc3_alloc_skb(RX_BUF_ALLOC_SIZE, GFP_ATOMIC); if (!skb) { show_free_areas(); continue; @@ -729,7 +738,7 @@ if (ip->txr == NULL) { /* Allocate and initialize tx rings. 16kb = 128 bufs. */ - ip->txr = (struct ioc3_etxd *)__get_free_pages(GFP_KERNEL, 2); + ip->txr = (struct ioc3_etxd *)__get_free_pages(GFP_KERNEL|GFP_ATOMIC, 2); ip->tx_pi = 0; ip->tx_ci = 0; } @@ -741,6 +750,7 @@ { unsigned long ring; + ioc3_free_rings(ip); ioc3_alloc_rings(dev, ip, ioc3); ioc3_clean_rx_ring(ip); @@ -824,7 +834,7 @@ ioc3->eier; } -static void ioc3_stop(struct net_device *dev) +static inline void ioc3_stop(struct net_device *dev) { struct ioc3_private *ip = dev->priv; struct ioc3 *ioc3 = ip->regs; @@ -863,6 +873,7 @@ { struct ioc3_private *ip = dev->priv; + del_timer(&ip->negtimer); netif_stop_queue(dev); ioc3_stop(dev); /* Flush */ @@ -875,14 +886,23 @@ return 0; } -static void ioc3_pci_init(struct pci_dev *pdev) +static int ioc3_pci_init(struct pci_dev *pdev) { + u16 mii0, mii_status, mii2, mii3, mii4; struct net_device *dev = NULL; // XXX struct ioc3_private *ip; struct ioc3 *ioc3; unsigned long ioc3_base, ioc3_size; + u32 vendor, model, rev; + int phy; + + dev = init_etherdev(0, sizeof(struct ioc3_private)); + + if (!dev) + return -ENOMEM; - dev = init_etherdev(dev, 0); + ip = dev->priv; + memset(ip, 0, sizeof(*ip)); /* * This probably needs to be register_netdevice, or call @@ -891,9 +911,6 @@ */ netif_device_attach(dev); - ip = (struct ioc3_private *) kmalloc(sizeof(*ip), GFP_KERNEL); - memset(ip, 0, sizeof(*ip)); - dev->priv = ip; dev->irq = pdev->irq; ioc3_base = pdev->resource[0].start; @@ -906,12 +923,38 @@ ioc3_stop(dev); ip->emcr = 0; ioc3_init(dev); + + init_timer(&ip->negtimer); ioc3_mii_init(dev, ip, ioc3); + phy = ip->phy; + if (phy == -1) { + printk(KERN_CRIT"%s: Didn't find a PHY, goodbye.\n", dev->name); + ioc3_stop(dev); + free_irq(dev->irq, dev); + ioc3_free_rings(ip); + + return -ENODEV; + } + + mii0 = mii_read(ioc3, phy, 0); + mii_status = mii_read(ioc3, phy, 1); + mii2 = mii_read(ioc3, phy, 2); + mii3 = mii_read(ioc3, phy, 3); + mii4 = mii_read(ioc3, phy, 4); + vendor = (mii2 << 12) | (mii3 >> 4); + model = (mii3 >> 4) & 0x3f; + rev = mii3 & 0xf; + printk(KERN_INFO"Using PHY %d, vendor 0x%x, model %d, rev %d.\n", + phy, vendor, model, rev); + printk(KERN_INFO "%s: MII transceiver found at MDIO address " + "%d, config %4.4x status %4.4x.\n", + dev->name, phy, mii0, mii_status); + ioc3_ssram_disc(ip); printk("IOC3 SSRAM has %d kbyte.\n", ip->emcr & EMCR_BUFSIZ ? 128 : 64); - ioc3_get_eaddr(dev, ioc3); + ioc3_get_eaddr(dev, ioc3); /* The IOC3-specific entries in the device structure. */ dev->open = ioc3_open; @@ -922,6 +965,8 @@ dev->get_stats = ioc3_get_stats; dev->do_ioctl = ioc3_ioctl; dev->set_multicast_list = ioc3_set_multicast_list; + + return 0; } static int __init ioc3_probe(void) @@ -938,7 +983,8 @@ while ((pdev = pci_find_device(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, pdev))) { - ioc3_pci_init(pdev); + if (ioc3_pci_init(pdev)) + return -ENOMEM; cards++; } } @@ -1018,10 +1064,14 @@ static void ioc3_timeout(struct net_device *dev) { + struct ioc3_private *ip = dev->priv; + struct ioc3 *ioc3 = ip->regs; + printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name); ioc3_stop(dev); ioc3_init(dev); + ioc3_mii_init(dev, ip, ioc3); dev->trans_start = jiffies; netif_wake_queue(dev); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.4.0-test11/linux/drivers/net/irda/irtty.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/irda/irtty.c Mon Nov 27 18:07:31 2000 @@ -960,7 +960,7 @@ ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRTTY_MAGIC, return -1;); - IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); /* Disable interrupts & save flags */ save_flags(flags); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c --- v2.4.0-test11/linux/drivers/net/irda/nsc-ircc.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/irda/nsc-ircc.c Mon Nov 27 18:07:31 2000 @@ -708,9 +708,12 @@ switch_bank(iobase, BANK0); /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ - switch_bank(iobase, BANK0); + switch_bank(iobase, BANK0); outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); - + + outb(0x03, iobase+LCR); /* 8 bit word length */ + outb(MCR_SIR, iobase+MCR); /* Start at SIR-mode, also clears LSR*/ + /* Set FIFO size to 32 */ switch_bank(iobase, BANK2); outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); @@ -723,7 +726,7 @@ switch_bank(iobase, BANK6); outb(0x20, iobase+0); /* Set 32 bits FIR CRC */ outb(0x0a, iobase+1); /* Set MIR pulse width */ - outb(0x0d, iobase+2); /* Set SIR pulse width */ + outb(0x0d, iobase+2); /* Set SIR pulse width to 1.6us */ outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */ MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name); @@ -804,8 +807,6 @@ dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ - IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", - dongle_types[dongle_id]); break; case 0x05: /* Reserved, but this is what the Thinkpad reports */ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", @@ -892,8 +893,7 @@ dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ - IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", - dongle_types[dongle_id]); + break; case 0x05: /* Reserved */ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/isa-skeleton.c linux/drivers/net/isa-skeleton.c --- v2.4.0-test11/linux/drivers/net/isa-skeleton.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/isa-skeleton.c Mon Dec 11 13:38:29 2000 @@ -121,8 +121,8 @@ /* Example routines you must write ;->. */ #define tx_done(dev) 1 -extern void hardware_send_packet(short ioaddr, char *buf, int length); -extern void chipset_init(struct net_device *dev, int startp); +static void hardware_send_packet(short ioaddr, char *buf, int length); +static void chipset_init(struct net_device *dev, int startp); /* * Check for a network adaptor of this type, and return '0' iff one exists. @@ -135,7 +135,9 @@ netcard_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); if (base_addr > 0x1ff) /* Check a single specified location. */ return netcard_probe1(dev, base_addr); @@ -360,8 +362,6 @@ */ netif_start_queue(dev); - MOD_INC_USE_COUNT; - return 0; } @@ -574,8 +574,6 @@ /* Update the statistics here. */ - MOD_DEC_USE_COUNT; - return 0; } @@ -589,11 +587,8 @@ struct net_local *lp = (struct net_local *)dev->priv; short ioaddr = dev->base_addr; - cli(); /* Update the statistics from the device registers. */ lp->stats.rx_missed_errors = inw(ioaddr+1); - sti(); - return &lp->stats; } @@ -633,7 +628,7 @@ #ifdef MODULE -static struct net_device this_device = { init: netcard_probe }; +static struct net_device this_device; static int io = 0x300; static int irq; static int dma; @@ -652,6 +647,7 @@ this_device.irq = irq; this_device.dma = dma; this_device.mem_start = mem; + this_device.init = netcard_probe; if ((result = register_netdev(&this_device)) != 0) return result; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.4.0-test11/linux/drivers/net/lance.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/lance.c Tue Dec 5 12:43:48 2000 @@ -37,7 +37,6 @@ static const char *version = "lance.c:v1.15ac 1999/11/13 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n"; -#include #include #include #include diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c --- v2.4.0-test11/linux/drivers/net/lasi_82596.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/lasi_82596.c Wed Dec 6 11:46:39 2000 @@ -0,0 +1,1549 @@ +/* lasi_82596.c -- driver for the intel 82596 ethernet controller, as + munged into HPPA boxen . + + This driver is based upon 82596.c, original credits are below... + but there were too many hoops which HP wants jumped through to + keep this code in there in a sane manner. + + 3 primary sources of the mess -- + 1) hppa needs *lots* of cacheline flushing to keep this kind of + MMIO running. + + 2) The 82596 needs to see all of its pointers as their physical + address. Thus virt_to_bus/bus_to_virt are *everywhere*. + + 3) The implementation HP is using seems to be significantly pickier + about when and how the command and RX units are started. some + command ordering was changed. + + Examination of the mach driver leads one to believe that there + might be a saner way to pull this off... anyone who feels like a + full rewrite can be my guest. + + Split 02/13/2000 Sam Creasey (sammy@oh.verio.com) + + 02/01/2000 Initial modifications for parisc by Helge Deller (deller@gmx.de) + 03/02/2000 changes for better/correct(?) cache-flushing (deller) +*/ + +/* 82596.c: A generic 82596 ethernet driver for linux. */ +/* + Based on Apricot.c + Written 1994 by Mark Evans. + This driver is for the Apricot 82596 bus-master interface + + Modularised 12/94 Mark Evans + + + Modified to support the 82596 ethernet chips on 680x0 VME boards. + by Richard Hirst + Renamed to be 82596.c + + 980825: Changed to receive directly in to sk_buffs which are + allocated at open() time. Eliminates copy on incoming frames + (small ones are still copied). Shared data now held in a + non-cached page, so we can run on 68060 in copyback mode. + + TBD: + * look at deferring rx frames rather than discarding (as per tulip) + * handle tx ring full as per tulip + * performace test to tune rx_copybreak + + Most of my modifications relate to the braindead big-endian + implementation by Intel. When the i596 is operating in + 'big-endian' mode, it thinks a 32 bit value of 0x12345678 + should be stored as 0x56781234. This is a real pain, when + you have linked lists which are shared by the 680x0 and the + i596. + + Driver skeleton + Written 1993 by Donald Becker. + Copyright 1993 United States Government as represented by the Director, + National Security Agency. This software may only be used and distributed + according to the terms of the GNU Public License as modified by SRC, + incorporated herein by reference. + + The author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + */ + +static const char *version = "82596.c $Revision: 1.14 $\n"; + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* DEBUG flags + */ + +#define DEB_INIT 0x0001 +#define DEB_PROBE 0x0002 +#define DEB_SERIOUS 0x0004 +#define DEB_ERRORS 0x0008 +#define DEB_MULTI 0x0010 +#define DEB_TDR 0x0020 +#define DEB_OPEN 0x0040 +#define DEB_RESET 0x0080 +#define DEB_ADDCMD 0x0100 +#define DEB_STATUS 0x0200 +#define DEB_STARTTX 0x0400 +#define DEB_RXADDR 0x0800 +#define DEB_TXADDR 0x1000 +#define DEB_RXFRAME 0x2000 +#define DEB_INTS 0x4000 +#define DEB_STRUCT 0x8000 +#define DEB_ANY 0xffff + + +#define DEB(x,y) if (i596_debug & (x)) y + + +#define CHECK_WBACK(addr,len) \ + do { if (!dma_consistent) dma_cache_wback((unsigned long)addr,len); } while (0) + +#define CHECK_INV(addr,len) \ + do { if (!dma_consistent) dma_cache_inv((unsigned long)addr,len); } while(0) + +#define CHECK_WBACK_INV(addr,len) \ + do { if (!dma_consistent) dma_cache_wback_inv((unsigned long)addr,len); } while (0) + + +#define PA_I82596_RESET 0 /* Offsets relative to LASI-LAN-Addr.*/ +#define PA_CPU_PORT_L_ACCESS 4 +#define PA_CHANNEL_ATTENTION 8 + + +/* + * Define various macros for Channel Attention, word swapping etc., dependent + * on architecture. MVME and BVME are 680x0 based, otherwise it is Intel. + */ + +#ifdef __BIG_ENDIAN +#define WSWAPrfd(x) ((struct i596_rfd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPrbd(x) ((struct i596_rbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPiscp(x) ((struct i596_iscp *)(((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPscb(x) ((struct i596_scb *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPcmd(x) ((struct i596_cmd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPtbd(x) ((struct i596_tbd *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define WSWAPchar(x) ((char *) (((u32)(x)<<16) | ((((u32)(x)))>>16))) +#define ISCP_BUSY 0x00010000 +#define MACH_IS_APRICOT 0 +#else +#define WSWAPrfd(x) ((struct i596_rfd *)(x)) +#define WSWAPrbd(x) ((struct i596_rbd *)(x)) +#define WSWAPiscp(x) ((struct i596_iscp *)(x)) +#define WSWAPscb(x) ((struct i596_scb *)(x)) +#define WSWAPcmd(x) ((struct i596_cmd *)(x)) +#define WSWAPtbd(x) ((struct i596_tbd *)(x)) +#define WSWAPchar(x) ((char *)(x)) +#define ISCP_BUSY 0x0001 +#define MACH_IS_APRICOT 1 +#endif + +/* + * The MPU_PORT command allows direct access to the 82596. With PORT access + * the following commands are available (p5-18). The 32-bit port command + * must be word-swapped with the most significant word written first. + * This only applies to VME boards. + */ +#define PORT_RESET 0x00 /* reset 82596 */ +#define PORT_SELFTEST 0x01 /* selftest */ +#define PORT_ALTSCP 0x02 /* alternate SCB address */ +#define PORT_ALTDUMP 0x03 /* Alternate DUMP address */ + +static int i596_debug = (DEB_SERIOUS|DEB_PROBE); + +MODULE_AUTHOR("Richard Hirst"); +MODULE_DESCRIPTION("i82596 driver"); +MODULE_PARM(i596_debug, "i"); + + +/* Copy frames shorter than rx_copybreak, otherwise pass on up in + * a full sized sk_buff. Value of 100 stolen from tulip.c (!alpha). + */ +static int rx_copybreak = 100; + +#define PKT_BUF_SZ 1536 +#define MAX_MC_CNT 64 + +#define I596_TOTAL_SIZE 17 + +#define I596_NULL ((void *)0xffffffff) + +#define CMD_EOL 0x8000 /* The last command of the list, stop. */ +#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ +#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ + +#define CMD_FLEX 0x0008 /* Enable flexible memory model */ + +enum commands { + CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, + CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7 +}; + +#define STAT_C 0x8000 /* Set to 0 after execution */ +#define STAT_B 0x4000 /* Command being executed */ +#define STAT_OK 0x2000 /* Command executed ok */ +#define STAT_A 0x1000 /* Command aborted */ + +#define CUC_START 0x0100 +#define CUC_RESUME 0x0200 +#define CUC_SUSPEND 0x0300 +#define CUC_ABORT 0x0400 +#define RX_START 0x0010 +#define RX_RESUME 0x0020 +#define RX_SUSPEND 0x0030 +#define RX_ABORT 0x0040 + +#define TX_TIMEOUT 5 + +#define OPT_SWAP_PORT 0x0001 /* Need to wordswp on the MPU port */ + + +struct i596_reg { + unsigned short porthi; + unsigned short portlo; + unsigned long ca; +}; + +#define EOF 0x8000 +#define SIZE_MASK 0x3fff + +struct i596_tbd { + unsigned short size; + unsigned short pad; + struct i596_tbd *next; + char *data; + long cache_pad[5]; /* Total 32 bytes... */ +}; + +/* The command structure has two 'next' pointers; v_next is the address of + * the next command as seen by the CPU, b_next is the address of the next + * command as seen by the 82596. The b_next pointer, as used by the 82596 + * always references the status field of the next command, rather than the + * v_next field, because the 82596 is unaware of v_next. It may seem more + * logical to put v_next at the end of the structure, but we cannot do that + * because the 82596 expects other fields to be there, depending on command + * type. + */ + +struct i596_cmd { + struct i596_cmd *v_next; /* Address from CPUs viewpoint */ + unsigned short status; + unsigned short command; + struct i596_cmd *b_next; /* Address from i596 viewpoint */ +}; + +struct tx_cmd { + struct i596_cmd cmd; + struct i596_tbd *tbd; + unsigned short size; + unsigned short pad; + struct sk_buff *skb; /* So we can free it after tx */ + dma_addr_t dma_addr; + long cache_pad[1]; /* Total 32 bytes... */ +}; + +struct tdr_cmd { + struct i596_cmd cmd; + unsigned short status; + unsigned short pad; +}; + +struct mc_cmd { + struct i596_cmd cmd; + short mc_cnt; + char mc_addrs[MAX_MC_CNT*6]; +}; + +struct sa_cmd { + struct i596_cmd cmd; + char eth_addr[8]; +}; + +struct cf_cmd { + struct i596_cmd cmd; + char i596_config[16]; +}; + +struct i596_rfd { + unsigned short stat; + unsigned short cmd; + struct i596_rfd *b_next; /* Address from i596 viewpoint */ + struct i596_rbd *rbd; + unsigned short count; + unsigned short size; + struct i596_rfd *v_next; /* Address from CPUs viewpoint */ + struct i596_rfd *v_prev; + long cache_pad[2]; /* Total 32 bytes... */ +}; + +struct i596_rbd { + unsigned short count; + unsigned short zero1; + struct i596_rbd *b_next; + unsigned char *b_data; /* Address from i596 viewpoint */ + unsigned short size; + unsigned short zero2; + struct sk_buff *skb; + struct i596_rbd *v_next; + struct i596_rbd *b_addr; /* This rbd addr from i596 view */ + unsigned char *v_data; /* Address from CPUs viewpoint */ + /* Total 32 bytes... */ +}; + +/* These values as chosen so struct i596_private fits in one page... */ + +#define TX_RING_SIZE 32 +#define RX_RING_SIZE 16 + +struct i596_scb { + unsigned short status; + unsigned short command; + struct i596_cmd *cmd; + struct i596_rfd *rfd; + unsigned long crc_err; + unsigned long align_err; + unsigned long resource_err; + unsigned long over_err; + unsigned long rcvdt_err; + unsigned long short_err; + unsigned short t_on; + unsigned short t_off; +}; + +struct i596_iscp { + unsigned long stat; + struct i596_scb *scb; +}; + +struct i596_scp { + unsigned long sysbus; + unsigned long pad; + struct i596_iscp *iscp; +}; + +struct i596_private { + volatile struct i596_scp scp __attribute__((aligned(32))); + volatile struct i596_iscp iscp __attribute__((aligned(32))); + volatile struct i596_scb scb __attribute__((aligned(32))); + struct sa_cmd sa_cmd __attribute__((aligned(32))); + struct cf_cmd cf_cmd __attribute__((aligned(32))); + struct tdr_cmd tdr_cmd __attribute__((aligned(32))); + struct mc_cmd mc_cmd __attribute__((aligned(32))); + struct i596_rfd rfds[RX_RING_SIZE] __attribute__((aligned(32))); + struct i596_rbd rbds[RX_RING_SIZE] __attribute__((aligned(32))); + struct tx_cmd tx_cmds[TX_RING_SIZE] __attribute__((aligned(32))); + struct i596_tbd tbds[TX_RING_SIZE] __attribute__((aligned(32))); + unsigned long stat; + int last_restart; + struct i596_rfd *rfd_head; + struct i596_rbd *rbd_head; + struct i596_cmd *cmd_tail; + struct i596_cmd *cmd_head; + int cmd_backlog; + unsigned long last_cmd; + struct net_device_stats stats; + int next_tx_cmd; + int options; + spinlock_t lock; + dma_addr_t dma_addr; +}; + +char init_setup[] = +{ + 0x8E, /* length, prefetch on */ + 0xC8, /* fifo to 8, monitor off */ + 0x80, /* don't save bad frames */ + 0x2E, /* No source address insertion, 8 byte preamble */ + 0x00, /* priority and backoff defaults */ + 0x60, /* interframe spacing */ + 0x00, /* slot time LSB */ + 0xf2, /* slot time and retries */ + 0x00, /* promiscuous mode */ + 0x00, /* collision detect */ + 0x40, /* minimum frame length */ + 0xff, + 0x00, + 0x7f /* *multi IA */ }; + +static int dma_consistent = 1; /* Zero if pci_alloc_consistent() fails */ + +static int i596_open(struct net_device *dev); +static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs); +static int i596_close(struct net_device *dev); +static struct net_device_stats *i596_get_stats(struct net_device *dev); +static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd); +static void i596_tx_timeout (struct net_device *dev); +static void print_eth(unsigned char *buf, char *str); +static void set_multicast_list(struct net_device *dev); + +static int rx_ring_size = RX_RING_SIZE; +static int ticks_limit = 100; +static int max_cmd_backlog = TX_RING_SIZE-1; + + +static inline void CA(struct net_device *dev) +{ + gsc_writel(0, (void*)(dev->base_addr + PA_CHANNEL_ATTENTION)); +} + + +static inline void MPU_PORT(struct net_device *dev, int c, volatile void *x) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + + u32 v = (u32) (c) | (u32) (x); + + if (lp->options & OPT_SWAP_PORT) + v = ((u32) (v) << 16) | ((u32) (v) >> 16); + + gsc_writel(v & 0xffff, (void*)(dev->base_addr + PA_CPU_PORT_L_ACCESS)); + udelay(1); + gsc_writel(v >> 16, (void*)(dev->base_addr + PA_CPU_PORT_L_ACCESS)); +} + + +static inline int wait_istat(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) +{ + CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); + while (--delcnt && lp->iscp.stat) { + udelay(10); + CHECK_INV(&(lp->iscp), sizeof(struct i596_iscp)); + } + if (!delcnt) { + printk("%s: %s, iscp.stat %04lx, didn't clear\n", + dev->name, str, lp->iscp.stat); + return -1; + } + else + return 0; +} + + +static inline int wait_cmd(struct net_device *dev, struct i596_private *lp, int delcnt, char *str) +{ + CHECK_INV(&(lp->scb), sizeof(struct i596_scb)); + while (--delcnt && lp->scb.command) { + udelay(10); + CHECK_INV(&(lp->scb), sizeof(struct i596_scb)); + } + if (!delcnt) { + printk("%s: %s, status %4.4x, cmd %4.4x.\n", + dev->name, str, lp->scb.status, lp->scb.command); + return -1; + } + else + return 0; +} + + +static void i596_display_data(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + struct i596_cmd *cmd; + struct i596_rfd *rfd; + struct i596_rbd *rbd; + + printk("lp and scp at %p, .sysbus = %08lx, .iscp = %p\n", + &lp->scp, lp->scp.sysbus, lp->scp.iscp); + printk("iscp at %p, iscp.stat = %08lx, .scb = %p\n", + &lp->iscp, lp->iscp.stat, lp->iscp.scb); + printk("scb at %p, scb.status = %04x, .command = %04x," + " .cmd = %p, .rfd = %p\n", + &lp->scb, lp->scb.status, lp->scb.command, + lp->scb.cmd, lp->scb.rfd); + printk(" errors: crc %lx, align %lx, resource %lx," + " over %lx, rcvdt %lx, short %lx\n", + lp->scb.crc_err, lp->scb.align_err, lp->scb.resource_err, + lp->scb.over_err, lp->scb.rcvdt_err, lp->scb.short_err); + cmd = lp->cmd_head; + while (cmd != I596_NULL) { + printk("cmd at %p, .status = %04x, .command = %04x, .b_next = %p\n", + cmd, cmd->status, cmd->command, cmd->b_next); + cmd = cmd->v_next; + } + rfd = lp->rfd_head; + printk("rfd_head = %p\n", rfd); + do { + printk (" %p .stat %04x, .cmd %04x, b_next %p, rbd %p," + " count %04x\n", + rfd, rfd->stat, rfd->cmd, rfd->b_next, rfd->rbd, + rfd->count); + rfd = rfd->v_next; + } while (rfd != lp->rfd_head); + rbd = lp->rbd_head; + printk("rbd_head = %p\n", rbd); + do { + printk(" %p .count %04x, b_next %p, b_data %p, size %04x\n", + rbd, rbd->count, rbd->b_next, rbd->b_data, rbd->size); + rbd = rbd->v_next; + } while (rbd != lp->rbd_head); + CHECK_INV(lp, sizeof(struct i596_private)); +} + + +#if defined(ENABLE_MVME16x_NET) || defined(ENABLE_BVME6000_NET) +static void i596_error(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + volatile unsigned char *pcc2 = (unsigned char *) 0xfff42000; + + pcc2[0x28] = 1; + pcc2[0x2b] = 0x1d; + printk("%s: Error interrupt\n", dev->name); + i596_display_data(dev); +} +#endif + +#define virt_to_dma(lp,v) ((char *)(v)-(char *)(lp)+(char *)((lp)->dma_addr)) + +static inline void init_rx_bufs(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *)dev->priv; + int i; + struct i596_rfd *rfd; + struct i596_rbd *rbd; + + /* First build the Receive Buffer Descriptor List */ + + for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { + dma_addr_t dma_addr; + struct sk_buff *skb = dev_alloc_skb(PKT_BUF_SZ + 4); + + if (skb == NULL) + panic("82596: alloc_skb() failed"); + skb_reserve(skb, 2); + dma_addr = pci_map_single(NULL, skb->tail,PKT_BUF_SZ, + PCI_DMA_FROMDEVICE); + skb->dev = dev; + rbd->v_next = rbd+1; + rbd->b_next = WSWAPrbd(virt_to_dma(lp,rbd+1)); + rbd->b_addr = WSWAPrbd(virt_to_dma(lp,rbd)); + rbd->skb = skb; + rbd->v_data = skb->tail; + rbd->b_data = WSWAPchar(dma_addr); + rbd->size = PKT_BUF_SZ; + } + lp->rbd_head = lp->rbds; + rbd = lp->rbds + rx_ring_size - 1; + rbd->v_next = lp->rbds; + rbd->b_next = WSWAPrbd(virt_to_dma(lp,lp->rbds)); + + /* Now build the Receive Frame Descriptor List */ + + for (i = 0, rfd = lp->rfds; i < rx_ring_size; i++, rfd++) { + rfd->rbd = I596_NULL; + rfd->v_next = rfd+1; + rfd->v_prev = rfd-1; + rfd->b_next = WSWAPrfd(virt_to_dma(lp,rfd+1)); + rfd->cmd = CMD_FLEX; + } + lp->rfd_head = lp->rfds; + lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); + rfd = lp->rfds; + rfd->rbd = lp->rbd_head; + rfd->v_prev = lp->rfds + rx_ring_size - 1; + rfd = lp->rfds + rx_ring_size - 1; + rfd->v_next = lp->rfds; + rfd->b_next = WSWAPrfd(virt_to_dma(lp,lp->rfds)); + rfd->cmd = CMD_EOL|CMD_FLEX; + + CHECK_WBACK_INV(lp, sizeof(struct i596_private)); +} + +static inline void remove_rx_bufs(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *)dev->priv; + struct i596_rbd *rbd; + int i; + + for (i = 0, rbd = lp->rbds; i < rx_ring_size; i++, rbd++) { + if (rbd->skb == NULL) + break; + pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + dev_kfree_skb(rbd->skb); + } +} + + +static void rebuild_rx_bufs(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + int i; + + /* Ensure rx frame/buffer descriptors are tidy */ + + for (i = 0; i < rx_ring_size; i++) { + lp->rfds[i].rbd = I596_NULL; + lp->rfds[i].cmd = CMD_FLEX; + } + lp->rfds[rx_ring_size-1].cmd = CMD_EOL|CMD_FLEX; + lp->rfd_head = lp->rfds; + lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); + lp->rbd_head = lp->rbds; + lp->rfds[0].rbd = WSWAPrbd(virt_to_dma(lp,lp->rbds)); + + CHECK_WBACK_INV(lp, sizeof(struct i596_private)); +} + + +static int init_i596_mem(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + unsigned long flags; + + disable_irq(dev->irq); /* disable IRQs from LAN */ + DEB(DEB_INIT, + printk("RESET 82596 port: %08lX (with IRQ%d disabled)\n", + dev->base_addr + PA_I82596_RESET, + dev->irq)); + + gsc_writel(0, (void*)(dev->base_addr + PA_I82596_RESET)); /* Hard Reset */ + udelay(100); /* Wait 100us - seems to help */ + + /* change the scp address */ + + lp->last_cmd = jiffies; + + + lp->scp.sysbus = 0x0000006c; + lp->scp.iscp = WSWAPiscp(virt_to_dma(lp,&(lp->iscp))); + lp->iscp.scb = WSWAPscb(virt_to_dma(lp,&(lp->scb))); + lp->iscp.stat = ISCP_BUSY; + lp->cmd_backlog = 0; + + lp->cmd_head = lp->scb.cmd = I596_NULL; + + DEB(DEB_INIT,printk("%s: starting i82596.\n", dev->name)); + + CHECK_WBACK(&(lp->scp), sizeof(struct i596_scp)); + CHECK_WBACK(&(lp->iscp), sizeof(struct i596_iscp)); + + MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_dma(lp,&lp->scp)); + + CA(dev); + + if (wait_istat(dev,lp,1000,"initialization timed out")) + goto failed; + DEB(DEB_INIT,printk("%s: i82596 initialization successful\n", dev->name)); + + /* Ensure rx frame/buffer descriptors are tidy */ + rebuild_rx_bufs(dev); + + lp->scb.command = 0; + CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + + enable_irq(dev->irq); /* enable IRQs from LAN */ + + DEB(DEB_INIT,printk("%s: queuing CmdConfigure\n", dev->name)); + memcpy(lp->cf_cmd.i596_config, init_setup, 14); + lp->cf_cmd.cmd.command = CmdConfigure; + CHECK_WBACK(&(lp->cf_cmd), sizeof(struct cf_cmd)); + i596_add_cmd(dev, &lp->cf_cmd.cmd); + + DEB(DEB_INIT,printk("%s: queuing CmdSASetup\n", dev->name)); + memcpy(lp->sa_cmd.eth_addr, dev->dev_addr, 6); + lp->sa_cmd.cmd.command = CmdSASetup; + CHECK_WBACK(&(lp->sa_cmd), sizeof(struct sa_cmd)); + i596_add_cmd(dev, &lp->sa_cmd.cmd); + + DEB(DEB_INIT,printk("%s: queuing CmdTDR\n", dev->name)); + lp->tdr_cmd.cmd.command = CmdTDR; + CHECK_WBACK(&(lp->tdr_cmd), sizeof(struct tdr_cmd)); + i596_add_cmd(dev, &lp->tdr_cmd.cmd); + + spin_lock_irqsave (&lp->lock, flags); + + if (wait_cmd(dev,lp,1000,"timed out waiting to issue RX_START")) { + spin_unlock_irqrestore (&lp->lock, flags); + goto failed; + } + DEB(DEB_INIT,printk("%s: Issuing RX_START\n", dev->name)); + lp->scb.command = RX_START; + lp->scb.rfd = WSWAPrfd(virt_to_dma(lp,lp->rfds)); + CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + + CA(dev); + + spin_unlock_irqrestore (&lp->lock, flags); + + if (wait_cmd(dev,lp,1000,"RX_START not processed")) + goto failed; + DEB(DEB_INIT,printk("%s: Receive unit started OK\n", dev->name)); + + return 0; + +failed: + printk("%s: Failed to initialise 82596\n", dev->name); + MPU_PORT(dev, PORT_RESET, 0); + return -1; +} + + +static inline int i596_rx(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *)dev->priv; + struct i596_rfd *rfd; + struct i596_rbd *rbd; + int frames = 0; + + DEB(DEB_RXFRAME,printk ("i596_rx(), rfd_head %p, rbd_head %p\n", + lp->rfd_head, lp->rbd_head)); + + + rfd = lp->rfd_head; /* Ref next frame to check */ + + CHECK_INV(rfd, sizeof(struct i596_rfd)); + while ((rfd->stat) & STAT_C) { /* Loop while complete frames */ + if (rfd->rbd == I596_NULL) + rbd = I596_NULL; + else if (rfd->rbd == lp->rbd_head->b_addr) { + rbd = lp->rbd_head; + CHECK_INV(rbd, sizeof(struct i596_rbd)); + } + else { + printk("%s: rbd chain broken!\n", dev->name); + /* XXX Now what? */ + rbd = I596_NULL; + } + DEB(DEB_RXFRAME, printk(" rfd %p, rfd.rbd %p, rfd.stat %04x\n", + rfd, rfd->rbd, rfd->stat)); + + if (rbd != I596_NULL && ((rfd->stat) & STAT_OK)) { + /* a good frame */ + int pkt_len = rbd->count & 0x3fff; + struct sk_buff *skb = rbd->skb; + int rx_in_place = 0; + + DEB(DEB_RXADDR,print_eth(rbd->v_data, "received")); + frames++; + + /* Check if the packet is long enough to just accept + * without copying to a properly sized skbuff. + */ + + if (pkt_len > rx_copybreak) { + struct sk_buff *newskb; + dma_addr_t dma_addr; + + pci_unmap_single(NULL,(dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + /* Get fresh skbuff to replace filled one. */ + newskb = dev_alloc_skb(PKT_BUF_SZ + 4); + if (newskb == NULL) { + skb = NULL; /* drop pkt */ + goto memory_squeeze; + } + skb_reserve(newskb, 2); + + /* Pass up the skb already on the Rx ring. */ + skb_put(skb, pkt_len); + rx_in_place = 1; + rbd->skb = newskb; + newskb->dev = dev; + dma_addr = pci_map_single(NULL, newskb->tail, PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + rbd->v_data = newskb->tail; + rbd->b_data = WSWAPchar(dma_addr); + CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); + } + else + skb = dev_alloc_skb(pkt_len + 2); +memory_squeeze: + if (skb == NULL) { + /* XXX tulip.c can defer packets here!! */ + printk ("%s: i596_rx Memory squeeze, dropping packet.\n", dev->name); + lp->stats.rx_dropped++; + } + else { + skb->dev = dev; + if (!rx_in_place) { + /* 16 byte align the data fields */ + pci_dma_sync_single(NULL, (dma_addr_t)WSWAPchar(rbd->b_data), PKT_BUF_SZ, PCI_DMA_FROMDEVICE); + skb_reserve(skb, 2); + memcpy(skb_put(skb,pkt_len), rbd->v_data, pkt_len); + } + skb->len = pkt_len; + skb->protocol=eth_type_trans(skb,dev); + netif_rx(skb); + lp->stats.rx_packets++; + lp->stats.rx_bytes+=pkt_len; + } + } + else { + DEB(DEB_ERRORS, printk("%s: Error, rfd.stat = 0x%04x\n", + dev->name, rfd->stat)); + lp->stats.rx_errors++; + if ((rfd->stat) & 0x0001) + lp->stats.collisions++; + if ((rfd->stat) & 0x0080) + lp->stats.rx_length_errors++; + if ((rfd->stat) & 0x0100) + lp->stats.rx_over_errors++; + if ((rfd->stat) & 0x0200) + lp->stats.rx_fifo_errors++; + if ((rfd->stat) & 0x0400) + lp->stats.rx_frame_errors++; + if ((rfd->stat) & 0x0800) + lp->stats.rx_crc_errors++; + if ((rfd->stat) & 0x1000) + lp->stats.rx_length_errors++; + } + + /* Clear the buffer descriptor count and EOF + F flags */ + + if (rbd != I596_NULL && (rbd->count & 0x4000)) { + rbd->count = 0; + lp->rbd_head = rbd->v_next; + CHECK_WBACK_INV(rbd, sizeof(struct i596_rbd)); + } + + /* Tidy the frame descriptor, marking it as end of list */ + + rfd->rbd = I596_NULL; + rfd->stat = 0; + rfd->cmd = CMD_EOL|CMD_FLEX; + rfd->count = 0; + + /* Remove end-of-list from old end descriptor */ + + rfd->v_prev->cmd = CMD_FLEX; + + /* Update record of next frame descriptor to process */ + + lp->scb.rfd = rfd->b_next; + lp->rfd_head = rfd->v_next; + CHECK_WBACK_INV(rfd->v_prev, sizeof(struct i596_rfd)); + CHECK_WBACK_INV(rfd, sizeof(struct i596_rfd)); + rfd = lp->rfd_head; + CHECK_INV(rfd, sizeof(struct i596_rfd)); + } + + DEB(DEB_RXFRAME,printk ("frames %d\n", frames)); + + return 0; +} + + +static inline void i596_cleanup_cmd(struct net_device *dev, struct i596_private *lp) +{ + struct i596_cmd *ptr; + + while (lp->cmd_head != I596_NULL) { + ptr = lp->cmd_head; + lp->cmd_head = ptr->v_next; + lp->cmd_backlog--; + + switch ((ptr->command) & 0x7) { + case CmdTx: + { + struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; + struct sk_buff *skb = tx_cmd->skb; + pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); + + dev_kfree_skb(skb); + + lp->stats.tx_errors++; + lp->stats.tx_aborted_errors++; + + ptr->v_next = ptr->b_next = I596_NULL; + tx_cmd->cmd.command = 0; /* Mark as free */ + break; + } + default: + ptr->v_next = ptr->b_next = I596_NULL; + } + CHECK_WBACK_INV(ptr, sizeof(struct i596_cmd)); + } + + wait_cmd(dev,lp,100,"i596_cleanup_cmd timed out"); + lp->scb.cmd = I596_NULL; + CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); +} + + +static inline void i596_reset(struct net_device *dev, struct i596_private *lp, int ioaddr) +{ + unsigned long flags; + + DEB(DEB_RESET,printk("i596_reset\n")); + + spin_lock_irqsave (&lp->lock, flags); + + wait_cmd(dev,lp,100,"i596_reset timed out"); + + netif_stop_queue(dev); + + /* FIXME: this command might cause an lpmc */ + lp->scb.command = CUC_ABORT | RX_ABORT; + CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CA(dev); + + /* wait for shutdown */ + wait_cmd(dev,lp,1000,"i596_reset 2 timed out"); + spin_unlock_irqrestore (&lp->lock, flags); + + i596_cleanup_cmd(dev,lp); + i596_rx(dev); + + netif_start_queue(dev); + init_i596_mem(dev); +} + + +static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + int ioaddr = dev->base_addr; + unsigned long flags; + + DEB(DEB_ADDCMD,printk("i596_add_cmd cmd_head %p\n", lp->cmd_head)); + + cmd->status = 0; + cmd->command |= (CMD_EOL | CMD_INTR); + cmd->v_next = cmd->b_next = I596_NULL; + CHECK_WBACK(cmd, sizeof(struct i596_cmd)); + + spin_lock_irqsave (&lp->lock, flags); + + if (lp->cmd_head != I596_NULL) { + lp->cmd_tail->v_next = cmd; + lp->cmd_tail->b_next = WSWAPcmd(virt_to_dma(lp,&cmd->status)); + CHECK_WBACK(lp->cmd_tail, sizeof(struct i596_cmd)); + } else { + lp->cmd_head = cmd; + wait_cmd(dev,lp,100,"i596_add_cmd timed out"); + lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&cmd->status)); + lp->scb.command = CUC_START; + CHECK_WBACK(&(lp->scb), sizeof(struct i596_scb)); + CA(dev); + } + lp->cmd_tail = cmd; + lp->cmd_backlog++; + + spin_unlock_irqrestore (&lp->lock, flags); + + if (lp->cmd_backlog > max_cmd_backlog) { + unsigned long tickssofar = jiffies - lp->last_cmd; + + if (tickssofar < ticks_limit) + return; + + printk("%s: command unit timed out, status resetting.\n", dev->name); +#if 1 + i596_reset(dev, lp, ioaddr); +#endif + } +} + +#if 0 +/* this function makes a perfectly adequate probe... but we have a + device list */ +static int i596_test(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + volatile int *tint; + u32 data; + + tint = (volatile int *)(&(lp->scp)); + data = virt_to_dma(lp,tint); + + tint[1] = -1; + CHECK_WBACK(tint,PAGE_SIZE); + + MPU_PORT(dev, 1, data); + + for(data = 1000000; data; data--) { + CHECK_INV(tint,PAGE_SIZE); + if(tint[1] != -1) + break; + + } + + printk("i596_test result %d\n", tint[1]); + +} +#endif + + +static int i596_open(struct net_device *dev) +{ + int res = 0; + + DEB(DEB_OPEN,printk("%s: i596_open() irq %d.\n", dev->name, dev->irq)); + + if (request_irq(dev->irq, &i596_interrupt, 0, "i82596", dev)) { + printk("%s: IRQ %d not free\n", dev->name, dev->irq); + return -EAGAIN; + } + + request_region(dev->base_addr, 12, dev->name); + + init_rx_bufs(dev); + + netif_start_queue(dev); + + MOD_INC_USE_COUNT; + + /* Initialize the 82596 memory */ + if (init_i596_mem(dev)) { + res = -EAGAIN; + free_irq(dev->irq, dev); + } + + return res; +} + +static void i596_tx_timeout (struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + int ioaddr = dev->base_addr; + + /* Transmitter timeout, serious problems. */ + DEB(DEB_ERRORS,printk("%s: transmit timed out, status resetting.\n", + dev->name)); + + lp->stats.tx_errors++; + + /* Try to restart the adaptor */ + if (lp->last_restart == lp->stats.tx_packets) { + DEB(DEB_ERRORS,printk ("Resetting board.\n")); + /* Shutdown and restart */ + i596_reset (dev, lp, ioaddr); + } else { + /* Issue a channel attention signal */ + DEB(DEB_ERRORS,printk ("Kicking board.\n")); + lp->scb.command = CUC_START | RX_START; + CHECK_WBACK_INV(&(lp->scb), sizeof(struct i596_scb)); + CA (dev); + lp->last_restart = lp->stats.tx_packets; + } + + dev->trans_start = jiffies; + netif_wake_queue (dev); +} + + +static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + struct tx_cmd *tx_cmd; + struct i596_tbd *tbd; + short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; + dev->trans_start = jiffies; + + DEB(DEB_STARTTX,printk("%s: i596_start_xmit(%x,%x) called\n", dev->name, + skb->len, (unsigned int)skb->data)); + + netif_stop_queue(dev); + + tx_cmd = lp->tx_cmds + lp->next_tx_cmd; + tbd = lp->tbds + lp->next_tx_cmd; + + if (tx_cmd->cmd.command) { + DEB(DEB_ERRORS,printk ("%s: xmit ring full, dropping packet.\n", + dev->name)); + lp->stats.tx_dropped++; + + dev_kfree_skb(skb); + } else { + if (++lp->next_tx_cmd == TX_RING_SIZE) + lp->next_tx_cmd = 0; + tx_cmd->tbd = WSWAPtbd(virt_to_dma(lp,tbd)); + tbd->next = I596_NULL; + + tx_cmd->cmd.command = CMD_FLEX | CmdTx; + tx_cmd->skb = skb; + + tx_cmd->pad = 0; + tx_cmd->size = 0; + tbd->pad = 0; + tbd->size = EOF | length; + + tx_cmd->dma_addr = pci_map_single(NULL, skb->data, skb->len, + PCI_DMA_TODEVICE); + tbd->data = WSWAPchar(tx_cmd->dma_addr); + + DEB(DEB_TXADDR,print_eth(skb->data, "tx-queued")); + CHECK_WBACK_INV(tx_cmd, sizeof(struct tx_cmd)); + CHECK_WBACK_INV(tbd, sizeof(struct i596_tbd)); + i596_add_cmd(dev, &tx_cmd->cmd); + + lp->stats.tx_packets++; + lp->stats.tx_bytes += length; + } + + netif_start_queue(dev); + + return 0; +} + +static void print_eth(unsigned char *add, char *str) +{ + int i; + + printk("i596 0x%p, ", add); + for (i = 0; i < 6; i++) + printk(" %02X", add[i + 6]); + printk(" -->"); + for (i = 0; i < 6; i++) + printk(" %02X", add[i]); + printk(" %02X%02X, %s\n", add[12], add[13], str); +} + + +#define LAN_PROM_ADDR 0xF0810000 + +static int __init i82596_probe(struct net_device *dev, int options) +{ + int i; + struct i596_private *lp; + char eth_addr[6]; + dma_addr_t dma_addr; + + /* This lot is ensure things have been cache line aligned. */ + if (sizeof(struct i596_rfd) != 32) { + printk("82596: sizeof(struct i596_rfd) = %d\n", + sizeof(struct i596_rfd)); + return -ENODEV; + } + if (sizeof(struct i596_rbd) != 32) { + printk("82596: sizeof(struct i596_rbd) = %d\n", + sizeof(struct i596_rbd)); + return -ENODEV; + } + if (sizeof(struct tx_cmd) != 32) { + printk("82596: sizeof(struct tx_cmd) = %d\n", + sizeof(struct tx_cmd)); + return -ENODEV; + } + if (sizeof(struct i596_tbd) != 32) { + printk("82596: sizeof(struct i596_tbd) = %d\n", + sizeof(struct i596_tbd)); + return -ENODEV; + } + if (sizeof(struct i596_private) > 4096) { + printk("82596: sizeof(struct i596_private) = %d\n", + sizeof(struct i596_private)); + return -ENODEV; + } + + /* FIXME: + Currently this works only, if set-up from lasi.c. + This should be changed to use probing too ! + */ + + if (!dev->base_addr || !dev->irq) + return -ENODEV; + + if (!pdc_lan_station_id( (char*)ð_addr, (void*)dev->base_addr)) { + for(i=0;i<6;i++) + eth_addr[i] = gsc_readb(LAN_PROM_ADDR+i); + printk("82596.c: MAC of HP700 LAN blindely read from the prom!\n"); + } + + dev->mem_start = (int)pci_alloc_consistent( NULL, + sizeof(struct i596_private), &dma_addr); + if (!dev->mem_start) { + printk("%s: Couldn't get consistent shared memory\n", dev->name); + dma_consistent = 0; + dev->mem_start = (int)__get_free_pages(GFP_ATOMIC, 0); + if (!dev->mem_start) { + printk("%s: Couldn't get shared memory\n", dev->name); +#ifdef ENABLE_APRICOT + release_region(dev->base_addr, I596_TOTAL_SIZE); +#endif + return -ENOMEM; + } + dma_addr = virt_to_bus(dev->mem_start); + } + + ether_setup(dev); + DEB(DEB_PROBE,printk("%s: 82596 at %#3lx,", dev->name, dev->base_addr)); + + for (i = 0; i < 6; i++) + DEB(DEB_PROBE,printk(" %2.2X", dev->dev_addr[i] = eth_addr[i])); + + DEB(DEB_PROBE,printk(" IRQ %d.\n", dev->irq)); + + DEB(DEB_PROBE,printk(version)); + + /* The 82596-specific entries in the device structure. */ + dev->open = i596_open; + dev->stop = i596_close; + dev->hard_start_xmit = i596_start_xmit; + dev->get_stats = i596_get_stats; + dev->set_multicast_list = set_multicast_list; + dev->tx_timeout = i596_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + + dev->priv = (void *)(dev->mem_start); + + lp = (struct i596_private *) dev->priv; + DEB(DEB_INIT,printk ("%s: lp at 0x%08lx (%d bytes), lp->scb at 0x%08lx\n", + dev->name, (unsigned long)lp, + sizeof(struct i596_private), (unsigned long)&lp->scb)); + memset((void *) lp, 0, sizeof(struct i596_private)); + +#if 0 + kernel_set_cachemode((void *)(dev->mem_start), 4096, IOMAP_NOCACHE_SER); +#endif + lp->options = options; + lp->scb.command = 0; + lp->scb.cmd = I596_NULL; + lp->scb.rfd = I596_NULL; + lp->lock = SPIN_LOCK_UNLOCKED; + lp->dma_addr = dma_addr; + + CHECK_WBACK_INV(dev->mem_start, sizeof(struct i596_private)); + + return 0; +} + + +int __init lasi_i82596_probe(struct net_device *dev) +{ + return i82596_probe(dev, 0); +} + + +int __init asp_i82596_probe(struct net_device *dev) +{ + return i82596_probe(dev, OPT_SWAP_PORT); +} + + +static void i596_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + struct net_device *dev = dev_id; + struct i596_private *lp; + unsigned short status, ack_cmd = 0; + + if (dev == NULL) { + printk("i596_interrupt(): irq %d for unknown device.\n", irq); + return; + } + + lp = (struct i596_private *) dev->priv; + + spin_lock (&lp->lock); + + wait_cmd(dev,lp,100,"i596 interrupt, timeout"); + status = lp->scb.status; + + DEB(DEB_INTS,printk("%s: i596 interrupt, IRQ %d, status %4.4x.\n", + dev->name, irq, status)); + + ack_cmd = status & 0xf000; + + if (!ack_cmd) { + DEB(DEB_ERRORS, printk("%s: interrupt with no events\n", dev->name)); + spin_unlock (&lp->lock); + return; + } + + if ((status & 0x8000) || (status & 0x2000)) { + struct i596_cmd *ptr; + + if ((status & 0x8000)) + DEB(DEB_INTS,printk("%s: i596 interrupt completed command.\n", dev->name)); + if ((status & 0x2000)) + DEB(DEB_INTS,printk("%s: i596 interrupt command unit inactive %x.\n", dev->name, status & 0x0700)); + + while (lp->cmd_head != I596_NULL) { + CHECK_INV(lp->cmd_head, sizeof(struct i596_cmd)); + if (!(lp->cmd_head->status & STAT_C)) + break; + + ptr = lp->cmd_head; + + DEB(DEB_STATUS,printk("cmd_head->status = %04x, ->command = %04x\n", + lp->cmd_head->status, lp->cmd_head->command)); + lp->cmd_head = ptr->v_next; + lp->cmd_backlog--; + + switch ((ptr->command) & 0x7) { + case CmdTx: + { + struct tx_cmd *tx_cmd = (struct tx_cmd *) ptr; + struct sk_buff *skb = tx_cmd->skb; + + if ((ptr->status) & STAT_OK) { + DEB(DEB_TXADDR,print_eth(skb->data, "tx-done")); + } else { + lp->stats.tx_errors++; + if ((ptr->status) & 0x0020) + lp->stats.collisions++; + if (!((ptr->status) & 0x0040)) + lp->stats.tx_heartbeat_errors++; + if ((ptr->status) & 0x0400) + lp->stats.tx_carrier_errors++; + if ((ptr->status) & 0x0800) + lp->stats.collisions++; + if ((ptr->status) & 0x1000) + lp->stats.tx_aborted_errors++; + } + pci_unmap_single(NULL, tx_cmd->dma_addr, skb->len, PCI_DMA_TODEVICE); + dev_kfree_skb_irq(skb); + + tx_cmd->cmd.command = 0; /* Mark free */ + break; + } + case CmdTDR: + { + unsigned short status = ((struct tdr_cmd *)ptr)->status; + + if (status & 0x8000) { + DEB(DEB_ANY,printk("%s: link ok.\n", dev->name)); + } else { + if (status & 0x4000) + printk("%s: Transceiver problem.\n", dev->name); + if (status & 0x2000) + printk("%s: Termination problem.\n", dev->name); + if (status & 0x1000) + printk("%s: Short circuit.\n", dev->name); + + DEB(DEB_TDR,printk("%s: Time %d.\n", dev->name, status & 0x07ff)); + } + break; + } + case CmdConfigure: + /* Zap command so set_multicast_list() knows it is free */ + ptr->command = 0; + break; + } + ptr->v_next = ptr->b_next = I596_NULL; + CHECK_WBACK(ptr, sizeof(struct i596_cmd)); + lp->last_cmd = jiffies; + } + + /* This mess is arranging that only the last of any outstanding + * commands has the interrupt bit set. Should probably really + * only add to the cmd queue when the CU is stopped. + */ + ptr = lp->cmd_head; + while ((ptr != I596_NULL) && (ptr != lp->cmd_tail)) { + struct i596_cmd *prev = ptr; + + ptr->command &= 0x1fff; + ptr = ptr->v_next; + CHECK_WBACK_INV(prev, sizeof(struct i596_cmd)); + } + + if ((lp->cmd_head != I596_NULL)) + ack_cmd |= CUC_START; + lp->scb.cmd = WSWAPcmd(virt_to_dma(lp,&lp->cmd_head->status)); + CHECK_WBACK_INV(&lp->scb, sizeof(struct i596_scb)); + } + if ((status & 0x1000) || (status & 0x4000)) { + if ((status & 0x4000)) + DEB(DEB_INTS,printk("%s: i596 interrupt received a frame.\n", dev->name)); + i596_rx(dev); + /* Only RX_START if stopped - RGH 07-07-96 */ + if (status & 0x1000) { + if (netif_running(dev)) { + DEB(DEB_ERRORS,printk("%s: i596 interrupt receive unit inactive, status 0x%x\n", dev->name, status)); + ack_cmd |= RX_START; + lp->stats.rx_errors++; + lp->stats.rx_fifo_errors++; + rebuild_rx_bufs(dev); + } + } + } + wait_cmd(dev,lp,100,"i596 interrupt, timeout"); + lp->scb.command = ack_cmd; + CHECK_WBACK(&lp->scb, sizeof(struct i596_scb)); + + /* DANGER: I suspect that some kind of interrupt + acknowledgement aside from acking the 82596 might be needed + here... but it's running acceptably without */ + + CA(dev); + + wait_cmd(dev,lp,100,"i596 interrupt, exit timeout"); + DEB(DEB_INTS,printk("%s: exiting interrupt.\n", dev->name)); + + spin_unlock (&lp->lock); + return; +} + +static int i596_close(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + unsigned long flags; + + netif_stop_queue(dev); + + DEB(DEB_INIT,printk("%s: Shutting down ethercard, status was %4.4x.\n", + dev->name, lp->scb.status)); + + save_flags(flags); + cli(); + + wait_cmd(dev,lp,100,"close1 timed out"); + lp->scb.command = CUC_ABORT | RX_ABORT; + CHECK_WBACK(&lp->scb, sizeof(struct i596_scb)); + + CA(dev); + + wait_cmd(dev,lp,100,"close2 timed out"); + restore_flags(flags); + DEB(DEB_STRUCT,i596_display_data(dev)); + i596_cleanup_cmd(dev,lp); + + disable_irq(dev->irq); + + free_irq(dev->irq, dev); + remove_rx_bufs(dev); + + release_region(dev->base_addr, 12); + + MOD_DEC_USE_COUNT; + + return 0; +} + +static struct net_device_stats * + i596_get_stats(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + + return &lp->stats; +} + +/* + * Set or clear the multicast filter for this adaptor. + */ + +static void set_multicast_list(struct net_device *dev) +{ + struct i596_private *lp = (struct i596_private *) dev->priv; + int config = 0, cnt; + + DEB(DEB_MULTI,printk("%s: set multicast list, %d entries, promisc %s, allmulti %s\n", dev->name, dev->mc_count, dev->flags & IFF_PROMISC ? "ON" : "OFF", dev->flags & IFF_ALLMULTI ? "ON" : "OFF")); + + if ((dev->flags & IFF_PROMISC) && !(lp->cf_cmd.i596_config[8] & 0x01)) { + lp->cf_cmd.i596_config[8] |= 0x01; + config = 1; + } + if (!(dev->flags & IFF_PROMISC) && (lp->cf_cmd.i596_config[8] & 0x01)) { + lp->cf_cmd.i596_config[8] &= ~0x01; + config = 1; + } + if ((dev->flags & IFF_ALLMULTI) && (lp->cf_cmd.i596_config[11] & 0x20)) { + lp->cf_cmd.i596_config[11] &= ~0x20; + config = 1; + } + if (!(dev->flags & IFF_ALLMULTI) && !(lp->cf_cmd.i596_config[11] & 0x20)) { + lp->cf_cmd.i596_config[11] |= 0x20; + config = 1; + } + if (config) { + if (lp->cf_cmd.cmd.command) + printk("%s: config change request already queued\n", + dev->name); + else { + lp->cf_cmd.cmd.command = CmdConfigure; + CHECK_WBACK_INV(&lp->cf_cmd, sizeof(struct cf_cmd)); + i596_add_cmd(dev, &lp->cf_cmd.cmd); + } + } + + cnt = dev->mc_count; + if (cnt > MAX_MC_CNT) + { + cnt = MAX_MC_CNT; + printk("%s: Only %d multicast addresses supported", + dev->name, cnt); + } + + if (dev->mc_count > 0) { + struct dev_mc_list *dmi; + unsigned char *cp; + struct mc_cmd *cmd; + + cmd = &lp->mc_cmd; + cmd->cmd.command = CmdMulticastList; + cmd->mc_cnt = dev->mc_count * 6; + cp = cmd->mc_addrs; + for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) { + memcpy(cp, dmi->dmi_addr, 6); + if (i596_debug > 1) + DEB(DEB_MULTI,printk("%s: Adding address %02x:%02x:%02x:%02x:%02x:%02x\n", + dev->name, cp[0],cp[1],cp[2],cp[3],cp[4],cp[5])); + } + CHECK_WBACK_INV(&lp->mc_cmd, sizeof(struct mc_cmd)); + i596_add_cmd(dev, &cmd->cmd); + } +} + +#ifdef HAVE_DEVLIST +static unsigned int i596_portlist[] __initdata = +{0x300, 0}; +struct netdev_entry i596_drv = +{"lasi_i82596", lasi_i82596_probe, I596_TOTAL_SIZE, i596_portlist}; +#endif + +#ifdef MODULE +static char devicename[9] = +{0,}; +static struct net_device dev_82596 = +{ + devicename, /* device name inserted by drivers/net/net_init.c */ + 0, 0, 0, 0, + 0, 0, /* base, irq */ + 0, 0, 0, NULL, lasi_i82596_probe}; + + +MODULE_PARM(debug, "i"); +static int debug = -1; + +int init_module(void) +{ + if (debug >= 0) + i596_debug = debug; + if (register_netdev(&dev_82596) != 0) + return -EIO; + return 0; +} + +void cleanup_module(void) +{ + unregister_netdev(&dev_82596); + lp = (struct i596_private *) dev_82596.priv; + + if (dma_consistent) + pci_free_consistent( NULL, sizeof( struct i596_private), + dev_82596.mem_start, lp->dma_addr); + else + free_page ((u32)(dev_82596.mem_start)); + + dev_82596.priv = NULL; +} + +#endif /* MODULE */ + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/lne390.c linux/drivers/net/lne390.c --- v2.4.0-test11/linux/drivers/net/lne390.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/lne390.c Mon Dec 11 13:38:29 2000 @@ -50,7 +50,7 @@ #include "8390.h" int lne390_probe(struct net_device *dev); -int lne390_probe1(struct net_device *dev, int ioaddr); +static int lne390_probe1(struct net_device *dev, int ioaddr); static int lne390_open(struct net_device *dev); static int lne390_close(struct net_device *dev); @@ -108,8 +108,10 @@ unsigned short ioaddr = dev->base_addr; int ret; + SET_MODULE_OWNER(dev); + if (ioaddr > 0x1ff) { /* Check a single specified location. */ - if (!request_region(ioaddr, LNE390_IO_EXTENT, "lne390")) + if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name)) return -EBUSY; ret = lne390_probe1(dev, ioaddr); if (ret) @@ -128,7 +130,7 @@ /* EISA spec allows for up to 16 slots, but 8 is typical. */ for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (!request_region(ioaddr, LNE390_IO_EXTENT, "lne390")) + if (!request_region(ioaddr, LNE390_IO_EXTENT, dev->name)) continue; if (lne390_probe1(dev, ioaddr) == 0) return 0; @@ -138,7 +140,7 @@ return -ENODEV; } -int __init lne390_probe1(struct net_device *dev, int ioaddr) +static int __init lne390_probe1(struct net_device *dev, int ioaddr) { int i, revision, ret; unsigned long eisa_id; @@ -195,11 +197,11 @@ } printk(" IRQ %d,", dev->irq); - if (request_irq(dev->irq, ei_interrupt, 0, "lne390", dev)) { + if ((ret = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { printk (" unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return -EAGAIN; + return ret; } if (dev->mem_start == 0) { @@ -356,7 +358,6 @@ static int lne390_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -367,21 +368,12 @@ printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } #ifdef MODULE #define MAX_LNE_CARDS 4 /* Max number of LNE390 cards per module */ -static struct net_device dev_lne[MAX_LNE_CARDS] = { - { - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - +static struct net_device dev_lne[MAX_LNE_CARDS]; static int io[MAX_LNE_CARDS]; static int irq[MAX_LNE_CARDS]; static int mem[MAX_LNE_CARDS]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/mvme147.c linux/drivers/net/mvme147.c --- v2.4.0-test11/linux/drivers/net/mvme147.c Thu Aug 26 14:28:33 1999 +++ linux/drivers/net/mvme147.c Mon Dec 11 13:38:29 2000 @@ -79,9 +79,11 @@ u_long address; if (!MACH_IS_MVME147 || called) - return(ENODEV); + return(-ENODEV); called++; + SET_MODULE_OWNER(dev); + dev->priv = kmalloc(sizeof(struct m147lance_private), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; @@ -173,7 +175,6 @@ m147_pcc->lan_cntrl=0; /* clear the interrupts (if any) */ m147_pcc->lan_cntrl=0x08 | 0x04; /* Enable irq 4 */ - MOD_INC_USE_COUNT; return 0; } @@ -182,7 +183,6 @@ /* disable interrupts at boardlevel */ m147_pcc->lan_cntrl=0x0; /* disable interrupts */ lance_close(dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/natsemi.c linux/drivers/net/natsemi.c --- v2.4.0-test11/linux/drivers/net/natsemi.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/natsemi.c Mon Dec 11 13:38:29 2000 @@ -386,6 +386,7 @@ dev = init_etherdev(NULL, sizeof (struct netdev_private)); if (!dev) return -ENOMEM; + SET_MODULE_OWNER(dev); { void *mmio; @@ -559,12 +560,8 @@ /* Do we need to reset the chip??? */ - MOD_INC_USE_COUNT; - - if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); + if (i) return i; if (debug > 1) printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", @@ -1178,8 +1175,6 @@ #if 0 writel(0x0200, ioaddr + ChipConfig); /* Power down Xcvr. */ #endif - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.4.0-test11/linux/drivers/net/ne.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/ne.c Tue Dec 5 12:29:38 2000 @@ -157,7 +157,9 @@ int __init ne_probe(struct net_device *dev) { - unsigned int base_addr = dev ? dev->base_addr : 0; + unsigned int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); /* First check any supplied i/o locations. User knows best. */ if (base_addr > 0x1ff) /* Check a single specified location. */ @@ -469,7 +471,6 @@ static int ne_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -478,7 +479,6 @@ if (ei_debug > 1) printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ne2.c linux/drivers/net/ne2.c --- v2.4.0-test11/linux/drivers/net/ne2.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/ne2.c Tue Dec 5 12:29:38 2000 @@ -152,6 +152,8 @@ int i; int adapter_found = 0; + SET_MODULE_OWNER(dev); + /* Do not check any supplied i/o locations. POS registers usually don't fail :) */ @@ -371,7 +373,6 @@ static int ne_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -380,7 +381,6 @@ if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c --- v2.4.0-test11/linux/drivers/net/ne2k-pci.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/ne2k-pci.c Tue Dec 5 12:29:38 2000 @@ -244,6 +244,7 @@ printk (KERN_ERR "ne2k-pci: cannot allocate ethernet device\n"); goto err_out_free_res; } + SET_MODULE_OWNER(dev); /* Reset card. Who knows what dain-bramaged state it was left in. */ { @@ -358,11 +359,10 @@ static int ne2k_pci_open(struct net_device *dev) { - MOD_INC_USE_COUNT; - if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + int ret = request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev); + if (ret) + return ret; + /* Set full duplex for the chips that we know about. */ if (ei_status.ne2k_flags & FORCE_FDX) { long ioaddr = dev->base_addr; @@ -380,7 +380,6 @@ { ei_close(dev); free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c --- v2.4.0-test11/linux/drivers/net/ne3210.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/ne3210.c Tue Dec 5 12:29:38 2000 @@ -99,6 +99,8 @@ { unsigned short ioaddr = dev->base_addr; + SET_MODULE_OWNER(dev); + if (ioaddr > 0x1ff) /* Check a single specified location. */ return ne3210_probe1(dev, ioaddr); else if (ioaddr > 0) /* Don't probe at all. */ @@ -345,7 +347,6 @@ static int ne3210_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -356,7 +357,6 @@ printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c --- v2.4.0-test11/linux/drivers/net/pcnet32.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/pcnet32.c Mon Dec 11 13:38:29 2000 @@ -483,7 +483,7 @@ printk(KERN_INFO "pcnet32_probe_pci: found device %#08x.%#08x\n", ent->vendor, ent->device); ioaddr = pci_resource_start (pdev, 0); - printk(KERN_INFO " ioaddr=%#08lx resource_flags=%#08lx\n", ioaddr, pci_resource_flags (pdev, 0)); + printk(KERN_INFO " ioaddr=%#08lx resource_flags=%#08lx\n", ioaddr, pci_resource_flags (pdev, 0)); if (!ioaddr) { printk (KERN_ERR "no PCI IO resources, aborting\n"); return -ENODEV; @@ -627,29 +627,29 @@ /* There is a 16 byte station address PROM at the base address. The first six bytes are the station address. */ for (i = 0; i < 6; i++) - printk( KERN_INFO " %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); + printk(" %2.2x", dev->dev_addr[i] = inb(ioaddr + i)); if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */ i = a->read_csr(ioaddr, 80) & 0x0C00; /* Check tx_start_pt */ - printk(KERN_INFO"\n tx_start_pt(0x%04x):",i); + printk("\n" KERN_INFO " tx_start_pt(0x%04x):",i); switch(i>>10) { - case 0: printk(KERN_INFO " 20 bytes,"); break; - case 1: printk(KERN_INFO " 64 bytes,"); break; - case 2: printk(KERN_INFO " 128 bytes,"); break; - case 3: printk(KERN_INFO "~220 bytes,"); break; + case 0: printk(" 20 bytes,"); break; + case 1: printk(" 64 bytes,"); break; + case 2: printk(" 128 bytes,"); break; + case 3: printk("~220 bytes,"); break; } i = a->read_bcr(ioaddr, 18); /* Check Burst/Bus control */ - printk(KERN_INFO" BCR18(%x):",i&0xffff); - if (i & (1<<5)) printk(KERN_INFO "BurstWrEn "); - if (i & (1<<6)) printk(KERN_INFO "BurstRdEn "); - if (i & (1<<7)) printk(KERN_INFO "DWordIO "); - if (i & (1<<11)) printk(KERN_INFO"NoUFlow "); + printk(" BCR18(%x):",i&0xffff); + if (i & (1<<5)) printk("BurstWrEn "); + if (i & (1<<6)) printk("BurstRdEn "); + if (i & (1<<7)) printk("DWordIO "); + if (i & (1<<11)) printk("NoUFlow "); i = a->read_bcr(ioaddr, 25); - printk(KERN_INFO "\n SRAMSIZE=0x%04x,",i<<8); + printk("\n" KERN_INFO " SRAMSIZE=0x%04x,",i<<8); i = a->read_bcr(ioaddr, 26); - printk(KERN_INFO " SRAM_BND=0x%04x,",i<<8); + printk(" SRAM_BND=0x%04x,",i<<8); i = a->read_bcr(ioaddr, 27); - if (i & (1<<14)) printk(KERN_INFO "LowLatRx,"); + if (i & (1<<14)) printk("LowLatRx"); } dev->base_addr = ioaddr; @@ -662,7 +662,7 @@ memset(lp, 0, sizeof(*lp)); lp->dma_addr = lp_dma_addr; lp->pci_dev = pdev; - printk(KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%#08x\n", lp, lp_dma_addr); + printk("\n" KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%#08x", lp, lp_dma_addr); spin_lock_init(&lp->lock); @@ -713,7 +713,7 @@ } if (dev->irq >= 2) - printk(KERN_INFO " assigned IRQ %d.\n", dev->irq); + printk(" assigned IRQ %d.\n", dev->irq); else { unsigned long irq_mask = probe_irq_on(); @@ -728,9 +728,9 @@ dev->irq = probe_irq_off (irq_mask); if (dev->irq) - printk(KERN_INFO ", probed IRQ %d.\n", dev->irq); + printk(", probed IRQ %d.\n", dev->irq); else { - printk(KERN_ERR ", failed to detect IRQ line.\n"); + printk(", failed to detect IRQ line.\n"); return -ENODEV; } } @@ -978,14 +978,14 @@ lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", lp->cur_rx); for (i = 0 ; i < RX_RING_SIZE; i++) - printk(KERN_DEBUG "%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", lp->rx_ring[i].base, -lp->rx_ring[i].buf_length, lp->rx_ring[i].msg_length, (unsigned)lp->rx_ring[i].status); for (i = 0 ; i < TX_RING_SIZE; i++) - printk(KERN_DEBUG "%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", + printk("%s %08x %04x %08x %04x", i & 1 ? "" : "\n ", lp->tx_ring[i].base, -lp->tx_ring[i].length, lp->tx_ring[i].misc, (unsigned)lp->tx_ring[i].status); - printk(KERN_DEBUG "\n"); + printk("\n"); } pcnet32_restart(dev, 0x0042); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/plip.c linux/drivers/net/plip.c --- v2.4.0-test11/linux/drivers/net/plip.c Mon Jun 19 17:59:40 2000 +++ linux/drivers/net/plip.c Mon Dec 11 12:39:45 2000 @@ -286,6 +286,7 @@ struct net_local *nl; struct pardevice *pardev; + SET_MODULE_OWNER(dev); dev->irq = pb->irq; dev->base_addr = pb->base; @@ -348,18 +349,18 @@ nl->nibble = PLIP_NIBBLE_WAIT; /* Initialize task queue structures */ - nl->immediate.next = NULL; + INIT_LIST_HEAD(&nl->immediate.list); nl->immediate.sync = 0; nl->immediate.routine = (void (*)(void *))plip_bh; nl->immediate.data = dev; - nl->deferred.next = NULL; + INIT_LIST_HEAD(&nl->deferred.list); nl->deferred.sync = 0; nl->deferred.routine = (void (*)(void *))plip_kick_bh; nl->deferred.data = dev; if (dev->irq == -1) { - nl->timer.next = NULL; + INIT_LIST_HEAD(&nl->timer.list); nl->timer.sync = 0; nl->timer.routine = (void (*)(void *))plip_timer_bh; nl->timer.data = dev; @@ -1164,7 +1165,6 @@ netif_start_queue (dev); - MOD_INC_USE_COUNT; return 0; } @@ -1212,7 +1212,6 @@ /* Reset. */ outb(0x00, PAR_CONTROL(dev)); #endif - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c --- v2.4.0-test11/linux/drivers/net/ppp_generic.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/ppp_generic.c Tue Nov 28 21:53:45 2000 @@ -2207,7 +2207,7 @@ dev->init = ppp_net_init; sprintf(dev->name, "ppp%d", unit); dev->priv = ppp; - dev->new_style = 1; + dev->features |= NETIF_F_DYNALLOC; rtnl_lock(); ret = register_netdevice(dev); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c --- v2.4.0-test11/linux/drivers/net/pppoe.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/pppoe.c Mon Dec 11 12:37:03 2000 @@ -785,8 +785,7 @@ skb_reserve(skb, dev->hard_header_len); skb->nh.raw = skb->data; - skb->rx_dev = skb->dev = dev; - dev_hold(skb->rx_dev); + skb->dev = dev; skb->priority = sk->priority; skb->protocol = __constant_htons(ETH_P_PPP_SES); @@ -869,11 +868,7 @@ skb->nh.raw = skb->data; - /* Change device of skb, update reference counts */ - if(skb->rx_dev) - dev_put(skb->rx_dev); - skb->rx_dev = skb->dev = dev; - dev_hold(skb->rx_dev); + skb->dev = dev; dev->hard_header(skb, dev, ETH_P_PPP_SES, sk->protinfo.pppox->pppoe_pa.remote, diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c --- v2.4.0-test11/linux/drivers/net/rclanmtl.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/rclanmtl.c Mon Dec 11 13:04:09 2000 @@ -1561,7 +1561,7 @@ RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction) { unsigned long off; - unsigned long *pMsg; + PU32 pMsg; PPAB pPab; int i; long timeout = 0; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/sb1000.c linux/drivers/net/sb1000.c --- v2.4.0-test11/linux/drivers/net/sb1000.c Tue Jul 18 16:09:27 2000 +++ linux/drivers/net/sb1000.c Mon Dec 11 13:38:29 2000 @@ -210,6 +210,9 @@ dev->rmem_end, serial_number, dev->irq); dev = init_etherdev(dev, 0); + if (!dev) + return -ENOMEM; + SET_MODULE_OWNER(dev); /* Make up a SB1000-specific-data structure. */ dev->priv = kmalloc(sizeof(struct sb1000_private), GFP_KERNEL); @@ -1004,7 +1007,6 @@ netif_start_queue(dev); - MOD_INC_USE_COUNT; return 0; /* Always succeed */ } @@ -1195,7 +1197,6 @@ dev_kfree_skb(lp->rx_skb[i]); } } - MOD_DEC_USE_COUNT; return 0; } @@ -1205,14 +1206,9 @@ MODULE_PARM(io, "1-2i"); MODULE_PARM(irq, "i"); -static struct net_device dev_sb1000 = { - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, sb1000_probe }; - -static int io[2] = {0, 0}; -static int irq = 0; +static struct net_device dev_sb1000; +static int io[2]; +static int irq; int init_module(void) @@ -1226,6 +1222,7 @@ printk(KERN_ERR "sb1000: can't register any device cm\n"); return -ENFILE; } + dev_sb1000.init = sb1000_probe; dev_sb1000.base_addr = io[0]; /* rmem_end holds the second I/O address - fv */ dev_sb1000.rmem_end = io[1]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/setup.c linux/drivers/net/setup.c --- v2.4.0-test11/linux/drivers/net/setup.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/setup.c Mon Dec 11 13:38:29 2000 @@ -31,9 +31,7 @@ extern int comx_init(void); extern int lmc_setup(void); -extern int abyss_probe(void); extern int madgemc_probe(void); -extern int tms_pci_probe(void); /* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */ #define __PAD6 "\0\0\0\0\0\0\0\0\0" @@ -115,16 +113,9 @@ /* * Token Ring Drivers */ -#ifdef CONFIG_ABYSS - {abyss_probe, 0}, -#endif #ifdef CONFIG_MADGEMC {madgemc_probe, 0}, #endif -#ifdef CONFIG_TMSPCI - {tms_pci_probe, 0}, -#endif - {NULL, 0}, }; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/shaper.c linux/drivers/net/shaper.c --- v2.4.0-test11/linux/drivers/net/shaper.c Thu Jun 29 10:09:01 2000 +++ linux/drivers/net/shaper.c Sun Dec 3 17:45:22 2000 @@ -406,7 +406,6 @@ return -ENODEV; if(shaper->bitspersec==0) return -EINVAL; - MOD_INC_USE_COUNT; return 0; } @@ -419,7 +418,6 @@ struct shaper *shaper=dev->priv; shaper_flush(shaper); del_timer_sync(&shaper->timer); - MOD_DEC_USE_COUNT; return 0; } @@ -618,34 +616,31 @@ } } -static struct shaper *shaper_alloc(struct net_device *dev) +static void shaper_init_priv(struct net_device *dev) { - struct shaper *sh=kmalloc(sizeof(struct shaper), GFP_KERNEL); - if(sh==NULL) - return NULL; - memset(sh,0,sizeof(*sh)); + struct shaper *sh = dev->priv; + skb_queue_head_init(&sh->sendq); init_timer(&sh->timer); sh->timer.function=shaper_timer; sh->timer.data=(unsigned long)sh; init_waitqueue_head(&sh->wait_queue); - return sh; } /* * Add a shaper device to the system */ -int __init shaper_probe(struct net_device *dev) +static int __init shaper_probe(struct net_device *dev) { /* * Set up the shaper. */ - - dev->priv = shaper_alloc(dev); - if(dev->priv==NULL) - return -ENOMEM; - + + SET_MODULE_OWNER(dev); + + shaper_init_priv(dev); + dev->open = shaper_open; dev->stop = shaper_close; dev->hard_start_xmit = shaper_start_xmit; @@ -685,89 +680,68 @@ return 0; } +static int shapers = 1; #ifdef MODULE -static struct net_device dev_shape = -{ - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, shaper_probe -}; - -int init_module(void) -{ - int err=dev_alloc_name(&dev_shape,"shaper%d"); - if(err<0) - return err; - printk(SHAPER_BANNER); - if (register_netdev(&dev_shape) != 0) - return -EIO; - printk("Traffic shaper initialised.\n"); - return 0; -} +MODULE_PARM(shapers, "i"); -void cleanup_module(void) -{ - struct shaper *sh=dev_shape.priv; - - /* - * No need to check MOD_IN_USE, as sys_delete_module() checks. - * To be unloadable we must be closed and detached so we don't - * need to flush things. - */ - - unregister_netdev(&dev_shape); +#else /* MODULE */ - /* - * Free up the private structure, or leak memory :-) - */ - kfree(sh); - dev_shape.priv = NULL; +static int __init set_num_shapers(char *str) +{ + shapers = simple_strtol(str, NULL, 0); + return 1; } -#else +__setup("shapers=", set_num_shapers); -static struct net_device dev_sh0 = -{ - "shaper0", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, shaper_probe -}; +#endif /* MODULE */ +static struct net_device *devs; -static struct net_device dev_sh1 = +static int __init shaper_init(void) { - "shaper1", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, shaper_probe -}; + int i, err; + size_t alloc_size; + struct shaper *sp; + unsigned int shapers_registered = 0; + + if (shapers < 1) + return -ENODEV; + + alloc_size = (sizeof(*devs) * shapers) + + (sizeof(struct shaper) * shapers); + devs = kmalloc(alloc_size, GFP_KERNEL); + if (!devs) + return -ENOMEM; + memset(devs, 0, alloc_size); + sp = (struct shaper *) &devs[shapers]; + for (i = 0; i < shapers; i++) { + err = dev_alloc_name(&devs[i], "shaper%d"); + if (err < 0) + break; + devs[i].init = shaper_probe; + devs[i].priv = &sp[i]; + if (register_netdev(&devs[i])) + break; + shapers_registered++; + } -static struct net_device dev_sh2 = -{ - "shaper2", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, shaper_probe -}; + if (!shapers_registered) { + kfree(devs); + devs = NULL; + } -static struct net_device dev_sh3 = -{ - "shaper3", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, shaper_probe -}; + return (shapers_registered ? 0 : -ENODEV); +} -void shaper_init(void) +static void __exit shaper_exit (void) { - register_netdev(&dev_sh0); - register_netdev(&dev_sh1); - register_netdev(&dev_sh2); - register_netdev(&dev_sh3); + kfree(devs); + devs = NULL; } -#endif /* MODULE */ +module_init(shaper_init); +module_exit(shaper_exit); + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.4.0-test11/linux/drivers/net/sis900.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/sis900.c Mon Dec 11 13:38:29 2000 @@ -241,6 +241,7 @@ net_dev = init_etherdev(NULL, sizeof(struct sis900_private)); if (!net_dev) return -ENOMEM; + SET_MODULE_OWNER(net_dev); if (!request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name)) { printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%lX\n", ioaddr); @@ -530,8 +531,7 @@ struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; long ioaddr = net_dev->base_addr; u8 revision; - - MOD_INC_USE_COUNT; + int ret; /* Soft reset the chip. */ sis900_reset(net_dev); @@ -541,10 +541,9 @@ if (revision == SIS630E_REV || revision == SIS630EA1_REV) sis630e_set_eq(net_dev); - if (request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev); + if (ret) + return ret; sis900_init_rxfilter(net_dev); @@ -1278,8 +1277,6 @@ } /* Green! Put the chip in low-power mode. */ - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c --- v2.4.0-test11/linux/drivers/net/sk_mca.c Tue Jul 18 16:09:27 2000 +++ linux/drivers/net/sk_mca.c Mon Dec 11 13:38:29 2000 @@ -879,9 +879,6 @@ dev->interrupt = 0; dev->tbusy = 0; dev->start = 0; -#endif - -#ifdef MODULE MOD_INC_USE_COUNT; #endif @@ -900,7 +897,7 @@ free_irq(dev->irq, dev); dev->irq = 0; -#ifdef MODULE +#if (LINUX_VERSION_CODE < 0x02032a) MOD_DEC_USE_COUNT; #endif @@ -1086,6 +1083,8 @@ if (MCA_bus == 0) return -ENODEV; + + SET_MODULE_OWNER(dev); /* start address of 1 --> forced detection */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/slip.c linux/drivers/net/slip.c --- v2.4.0-test11/linux/drivers/net/slip.c Sun Aug 6 22:20:09 2000 +++ linux/drivers/net/slip.c Sun Dec 3 17:45:22 2000 @@ -549,7 +549,6 @@ sl->xleft = 0; spin_unlock_bh(&sl->lock); - MOD_DEC_USE_COUNT; return 0; } @@ -564,7 +563,6 @@ sl->flags &= (1 << SLF_INUSE); netif_start_queue(dev); - MOD_INC_USE_COUNT; return 0; } @@ -646,6 +644,8 @@ dev->addr_len = 0; dev->type = ARPHRD_SLIP + sl->mode; dev->tx_queue_len = 10; + + SET_MODULE_OWNER(dev); dev_init_buffers(dev); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/slip.h linux/drivers/net/slip.h --- v2.4.0-test11/linux/drivers/net/slip.h Wed Feb 9 20:08:09 2000 +++ linux/drivers/net/slip.h Mon Dec 11 13:01:45 2000 @@ -91,7 +91,7 @@ int xdata, xbits; /* 6 bit slip controls */ #endif - unsigned int flags; /* Flag values/ mode etc */ + unsigned long flags; /* Flag values/ mode etc */ #define SLF_INUSE 0 /* Channel in use */ #define SLF_ESCAPE 1 /* ESC received */ #define SLF_ERROR 2 /* Parity, etc. error */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c --- v2.4.0-test11/linux/drivers/net/smc-mca.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/smc-mca.c Mon Dec 11 13:38:29 2000 @@ -91,7 +91,7 @@ char *name; }; -const struct smc_mca_adapters_t smc_mca_adapters[] = { +static const struct smc_mca_adapters_t smc_mca_adapters[] = { { 0x61c8, "SMC Ethercard PLUS Elite/A BNC/AUI (WD8013EP/A)" }, { 0x61c9, "SMC Ethercard PLUS Elite/A UTP/AUI (WD8013WP/A)" }, { 0x6fc0, "WD Ethercard PLUS/A (WD8003E/A or WD8003ET/A)" }, @@ -114,13 +114,15 @@ int adapter = 0; int tbase = 0; int tirq = 0; - int base_addr = dev ? dev->base_addr : 0; - int irq = dev ? dev->irq : 0; + int base_addr = dev->base_addr; + int irq = dev->irq; if (!MCA_bus) { return -ENODEV; } + SET_MODULE_OWNER(dev); + if (base_addr || irq) { printk(KERN_INFO "Probing for SMC MCA adapter"); if (base_addr) { @@ -340,7 +342,6 @@ */ ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -424,8 +425,6 @@ * "just in case"... */ - MOD_DEC_USE_COUNT; - return 0; } @@ -435,18 +434,9 @@ #define MAX_ULTRAMCA_CARDS 4 /* Max number of Ultra cards per module */ -static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS] = -{ - { - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_ULTRAMCA_CARDS] = { 0, }; -static int irq[MAX_ULTRAMCA_CARDS] = { 0, }; +static struct net_device dev_ultra[MAX_ULTRAMCA_CARDS]; +static int io[MAX_ULTRAMCA_CARDS]; +static int irq[MAX_ULTRAMCA_CARDS]; MODULE_PARM(io, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_ULTRAMCA_CARDS) "i"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v2.4.0-test11/linux/drivers/net/smc-ultra.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/smc-ultra.c Mon Dec 11 13:38:29 2000 @@ -105,7 +105,9 @@ int __init ultra_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); if (base_addr > 0x1ff) /* Check a single specified location. */ return ultra_probe1(dev, base_addr); @@ -272,7 +274,6 @@ outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr); outb(0xff, dev->base_addr + EN0_ERWCNT); ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -411,8 +412,6 @@ /* We should someday disable shared memory and change to 8-bit mode "just in case"... */ - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c --- v2.4.0-test11/linux/drivers/net/smc-ultra32.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/smc-ultra32.c Mon Dec 11 13:38:29 2000 @@ -61,7 +61,7 @@ #include "8390.h" int ultra32_probe(struct net_device *dev); -int ultra32_probe1(struct net_device *dev, int ioaddr); +static int ultra32_probe1(struct net_device *dev, int ioaddr); static int ultra32_open(struct net_device *dev); static void ultra32_reset_8390(struct net_device *dev); static void ultra32_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, @@ -105,48 +105,64 @@ int __init ultra32_probe(struct net_device *dev) { - const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; - int ioaddr, edge, media; + int ioaddr; if (!EISA_bus) return -ENODEV; + SET_MODULE_OWNER(dev); + /* EISA spec allows for up to 16 slots, but 8 is typical. */ for (ioaddr = 0x1000 + ULTRA32_BASE; ioaddr < 0x9000; ioaddr += 0x1000) - if (check_region(ioaddr, ULTRA32_IO_EXTENT) == 0 && - inb(ioaddr + ULTRA32_IDPORT) != 0xff && - inl(ioaddr + ULTRA32_IDPORT) == ULTRA32_ID) { - media = inb(ioaddr + ULTRA32_CFG7) & 0x03; - edge = inb(ioaddr + ULTRA32_CFG5) & 0x08; - printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n", - ioaddr >> 12, ifmap[media], - (edge ? "Edge Triggered" : "Level Sensitive")); if (ultra32_probe1(dev, ioaddr) == 0) - return 0; - } + return 0; + return -ENODEV; } -int __init ultra32_probe1(struct net_device *dev, int ioaddr) +static int __init ultra32_probe1(struct net_device *dev, int ioaddr) { - int i; + int i, edge, media, retval; int checksum = 0; const char *model_name; - static unsigned version_printed = 0; + static unsigned version_printed; /* Values from various config regs. */ - unsigned char idreg = inb(ioaddr + 7); - unsigned char reg4 = inb(ioaddr + 4) & 0x7f; + unsigned char idreg; + unsigned char reg4; + const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"}; + + if (!request_region(ioaddr, ULTRA32_IO_EXTENT, dev->name)) + return -EBUSY; + + if (inb(ioaddr + ULTRA32_IDPORT) == 0xff || + inl(ioaddr + ULTRA32_IDPORT) != ULTRA32_ID) { + retval = -ENODEV; + goto out; + } + + media = inb(ioaddr + ULTRA32_CFG7) & 0x03; + edge = inb(ioaddr + ULTRA32_CFG5) & 0x08; + printk("SMC Ultra32 in EISA Slot %d, Media: %s, %s IRQs.\n", + ioaddr >> 12, ifmap[media], + (edge ? "Edge Triggered" : "Level Sensitive")); + + idreg = inb(ioaddr + 7); + reg4 = inb(ioaddr + 4) & 0x7f; /* Check the ID nibble. */ - if ((idreg & 0xf0) != 0x20) /* SMC Ultra */ - return -ENODEV; + if ((idreg & 0xf0) != 0x20) { /* SMC Ultra */ + retval = -ENODEV; + goto out; + } /* Select the station address register set. */ outb(reg4, ioaddr + 4); for (i = 0; i < 8; i++) checksum += inb(ioaddr + 8 + i); - if ((checksum & 0xff) != 0xff) - return -ENODEV; + if ((checksum & 0xff) != 0xff) { + retval = -ENODEV; + goto out; + } if (ei_debug && version_printed++ == 0) printk(version); @@ -175,7 +191,8 @@ if ((inb(ioaddr + ULTRA32_CFG5) & 0x40) == 0) { printk("\nsmc-ultra32: Card RAM is disabled! " "Run EISA config utility.\n"); - return -ENODEV; + retval = -ENODEV; + goto out; } if ((inb(ioaddr + ULTRA32_CFG2) & 0x04) == 0) printk("\nsmc-ultra32: Ignoring Bus-Master enable bit. " @@ -186,7 +203,8 @@ int irq = irqmap[inb(ioaddr + ULTRA32_CFG5) & 0x07]; if (irq == 0) { printk(", failed to detect IRQ line.\n"); - return -EAGAIN; + retval = -EAGAIN; + goto out; } dev->irq = irq; } @@ -194,12 +212,10 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk (", no memory for dev->priv.\n"); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - /* OK, we are certain this is going to work. Setup the device. */ - request_region(ioaddr, ULTRA32_IO_EXTENT, model_name); - /* The 8390 isn't at the base address, so fake the offset */ dev->base_addr = ioaddr + ULTRA32_NIC_OFFSET; @@ -229,15 +245,20 @@ NS8390_init(dev, 0); return 0; +out: + release_region(ioaddr, ULTRA32_IO_EXTENT); + return retval; } static int ultra32_open(struct net_device *dev) { int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET; /* ASIC addr */ int irq_flags = (inb(ioaddr + ULTRA32_CFG5) & 0x08) ? 0 : SA_SHIRQ; + int retval; - if (request_irq(dev->irq, ei_interrupt, irq_flags, ei_status.name, dev)) - return -EAGAIN; + retval = request_irq(dev->irq, ei_interrupt, irq_flags, dev->name, dev); + if (retval) + return retval; outb(ULTRA32_MEMENB, ioaddr); /* Enable Shared Memory. */ outb(0x80, ioaddr + ULTRA32_CFG6); /* Enable Interrupts. */ @@ -248,7 +269,6 @@ outb_p(E8390_NODMA+E8390_PAGE0, dev->base_addr); outb(0xff, dev->base_addr + EN0_ERWCNT); ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -266,8 +286,6 @@ free_irq(dev->irq, dev); NS8390_init(dev, 0); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.4.0-test11/linux/drivers/net/smc9194.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/smc9194.c Mon Dec 11 13:38:29 2000 @@ -256,15 +256,7 @@ . Test if a given location contains a chip, trying to cause as . little damage as possible if it's not a SMC chip. */ -static int smc_probe( int ioaddr ); - -/* - . this routine initializes the cards hardware, prints out the configuration - . to the system log as well as the vanity message, and handles the setup - . of a device parameter. - . It will give an error if it can't initialize the card. -*/ -static int smc_initcard( struct net_device *, int ioaddr ); +static int smc_probe(struct net_device *dev, int ioaddr); /* . A rather simple routine to print out a packet for debugging purposes. @@ -714,35 +706,20 @@ int __init smc_init(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); /* try a specific location */ - if (base_addr > 0x1ff) { - int error; - error = smc_probe(base_addr); - if ( 0 == error ) { - return smc_initcard( dev, base_addr ); - } - return error; - } else { - if ( 0 != base_addr ) { - return -ENXIO; - } - } + if (base_addr > 0x1ff) + return smc_probe(dev, base_addr); + else if (base_addr != 0) + return -ENXIO; /* check every ethernet address */ - for (i = 0; smc_portlist[i]; i++) { - int ioaddr = smc_portlist[i]; - - /* check if the area is available */ - if (check_region( ioaddr , SMC_IO_EXTENT)) - continue; - - /* check this specific address */ - if ( smc_probe( ioaddr ) == 0) { - return smc_initcard( dev, ioaddr ); - } - } + for (i = 0; smc_portlist[i]; i++) + if (smc_probe(dev, smc_portlist[i]) == 0) + return 0; /* couldn't find anything */ return -ENODEV; @@ -837,23 +814,53 @@ .--------------------------------------------------------------------- */ -static int __init smc_probe( int ioaddr ) +/*--------------------------------------------------------------- + . Here I do typical initialization tasks. + . + . o Initialize the structure if needed + . o print out my vanity message if not done so already + . o print out what type of hardware is detected + . o print out the ethernet address + . o find the IRQ + . o set up my private data + . o configure the dev structure with my subroutines + . o actually GRAB the irq. + . o GRAB the region + .----------------------------------------------------------------- +*/ +static int __init smc_probe(struct net_device *dev, int ioaddr) { - unsigned int bank; - word revision_register; - word base_address_register; + int i, memory, retval; + static unsigned version_printed; + unsigned int bank; + + const char *version_string; + const char *if_string; + + /* registers */ + word revision_register; + word base_address_register; + word configuration_register; + word memory_info_register; + word memory_cfg_register; + + /* Grab the region so that no one else tries to probe our ioports. */ + if (!request_region(ioaddr, SMC_IO_EXTENT, dev->name)) + return -EBUSY; /* First, see if the high byte is 0x33 */ bank = inw( ioaddr + BANK_SELECT ); if ( (bank & 0xFF00) != 0x3300 ) { - return -ENODEV; + retval = -ENODEV; + goto err_out; } /* The above MIGHT indicate a device, but I need to write to further test this. */ outw( 0x0, ioaddr + BANK_SELECT ); bank = inw( ioaddr + BANK_SELECT ); if ( (bank & 0xFF00 ) != 0x3300 ) { - return -ENODEV; + retval = -ENODEV; + goto err_out; } /* well, we've already written once, so hopefully another time won't hurt. This time, I need to switch the bank register to bank 1, @@ -866,7 +873,8 @@ ioaddr, base_address_register >> 3 & 0x3E0 ); /* well, the base address register didn't match. Must not have been a SMC chip after all. */ - return -ENODEV; + retval = -ENODEV; + goto err_out; } /* check if the revision register is something that I recognize. @@ -879,46 +887,13 @@ printk(CARDNAME ": IO %x: Unrecognized revision register:" " %x, Contact author. \n", ioaddr, revision_register ); - return -ENODEV; + retval = -ENODEV; + goto err_out; } /* at this point I'll assume that the chip is an SMC9xxx. It might be prudent to check a listing of MAC addresses against the hardware address, or do some other tests. */ - return 0; -} - -/*--------------------------------------------------------------- - . Here I do typical initialization tasks. - . - . o Initialize the structure if needed - . o print out my vanity message if not done so already - . o print out what type of hardware is detected - . o print out the ethernet address - . o find the IRQ - . o set up my private data - . o configure the dev structure with my subroutines - . o actually GRAB the irq. - . o GRAB the region - .----------------------------------------------------------------- -*/ -static int __init smc_initcard(struct net_device *dev, int ioaddr) -{ - int i; - - static unsigned version_printed = 0; - - /* registers */ - word revision_register; - word configuration_register; - word memory_info_register; - word memory_cfg_register; - - const char * version_string; - const char * if_string; - int memory; - - int irqval; if (version_printed++ == 0) printk("%s", version); @@ -956,7 +931,8 @@ version_string = chip_ids[ ( revision_register >> 4 ) & 0xF ]; if ( !version_string ) { /* I shouldn't get here because this call was done before.... */ - return -ENODEV; + retval = -ENODEV; + goto err_out; } /* is it using AUI or 10BaseT ? */ @@ -1003,7 +979,8 @@ } if (dev->irq == 0 ) { printk(CARDNAME": Couldn't autodetect your IRQ. Use irq=xx.\n"); - return -ENODEV; + retval = -ENODEV; + goto err_out; } if (dev->irq == 2) { /* Fixup for users that don't know that IRQ 2 is really IRQ 9, @@ -1014,7 +991,7 @@ /* now, print out the card info, in a short format.. */ - printk(CARDNAME ": %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", + printk("%s: %s(r:%d) at %#3x IRQ:%d INTF:%s MEM:%db ", dev->name, version_string, revision_register & 0xF, ioaddr, dev->irq, if_string, memory ); /* @@ -1029,8 +1006,10 @@ /* Initialize the private structure. */ if (dev->priv == NULL) { dev->priv = kmalloc(sizeof(struct smc_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (dev->priv == NULL) { + retval = -ENOMEM; + goto err_out; + } } /* set the private data to zero by default */ memset(dev->priv, 0, sizeof(struct smc_local)); @@ -1039,16 +1018,15 @@ ether_setup(dev); /* Grab the IRQ */ - irqval = request_irq(dev->irq, &smc_interrupt, 0, CARDNAME, dev); - if (irqval) { - printk(CARDNAME": unable to get IRQ %d (irqval=%d).\n", - dev->irq, irqval); - return -EAGAIN; + retval = request_irq(dev->irq, &smc_interrupt, 0, dev->name, dev); + if (retval) { + printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, + dev->irq, retval); + kfree(dev->priv); + dev->priv = NULL; + goto err_out; } - /* Grab the region so that no one else tries to probe our ioports. */ - request_region(ioaddr, SMC_IO_EXTENT, CARDNAME); - dev->open = smc_open; dev->stop = smc_close; dev->hard_start_xmit = smc_wait_to_send_packet; @@ -1058,6 +1036,10 @@ dev->set_multicast_list = smc_set_multicast_list; return 0; + +err_out: + release_region(ioaddr, SMC_IO_EXTENT); + return retval; } #if SMC_DEBUG > 2 @@ -1112,8 +1094,6 @@ /* clear out all the junk that was put here before... */ memset(dev->priv, 0, sizeof(struct smc_local)); - MOD_INC_USE_COUNT; - /* reset the hardware */ smc_reset( ioaddr ); @@ -1504,7 +1484,6 @@ smc_shutdown( dev->base_addr ); /* Update the statistics here. */ - MOD_DEC_USE_COUNT; return 0; } @@ -1577,8 +1556,7 @@ #ifdef MODULE -static struct net_device devSMC9194 = { init: smc_init }; - +static struct net_device devSMC9194; static int io; static int irq; static int ifport; @@ -1599,6 +1577,7 @@ devSMC9194.base_addr = io; devSMC9194.irq = irq; devSMC9194.if_port = ifport; + devSMC9194.init = smc_init; if ((result = register_netdev(&devSMC9194)) != 0) return result; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/sundance.c linux/drivers/net/sundance.c --- v2.4.0-test11/linux/drivers/net/sundance.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/net/sundance.c Mon Dec 11 13:38:29 2000 @@ -390,6 +390,7 @@ dev = init_etherdev(NULL, sizeof(*np)); if (!dev) return -ENOMEM; + SET_MODULE_OWNER(dev); #ifdef USE_IO_OPS ioaddr = pci_resource_start(pdev, 0); @@ -609,12 +610,9 @@ /* Do we need to reset the chip??? */ - MOD_INC_USE_COUNT; - - if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); + if (i) + return i; if (debug > 1) printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", @@ -1223,8 +1221,6 @@ dev_kfree_skb(np->tx_skbuff[i]); np->tx_skbuff[i] = 0; } - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.4.0-test11/linux/drivers/net/sunhme.c Sun Nov 19 18:44:11 2000 +++ linux/drivers/net/sunhme.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: sunhme.c,v 1.104 2000/11/17 01:40:00 davem Exp $ +/* $Id: sunhme.c,v 1.105 2000/12/05 02:00:36 anton 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. @@ -1492,18 +1492,18 @@ /* Shut up the MIF. */ HMD(("happy_meal_init: Disable all MIF irqs (old[%08x]), ", - hme_read32(hp, &tregs->int_mask))); + hme_read32(hp, tregs + TCVR_IMASK))); 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) { HMD(("use frame old[%08x], ", - hme_read32(hp, &tregs->cfg))); + hme_read32(hp, tregs + TCVR_CFG))); 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_read32(hp, tregs + TCVR_CFG))); hme_write32(hp, tregs + TCVR_CFG, hme_read32(hp, tregs + TCVR_CFG) | TCV_CFG_BENABLE); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tlan.c linux/drivers/net/tlan.c --- v2.4.0-test11/linux/drivers/net/tlan.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/tlan.c Mon Dec 11 13:38:29 2000 @@ -474,6 +474,7 @@ printk(KERN_ERR "TLAN: Could not allocate memory for device.\n"); return -ENOMEM; } + SET_MODULE_OWNER(dev); priv = dev->priv; @@ -814,14 +815,11 @@ TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv; int err; - MOD_INC_USE_COUNT; - priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION ); err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ, TLanSignature, dev ); if ( err ) { printk(KERN_ERR "TLAN: Cannot open %s because IRQ %d is already in use.\n", dev->name, dev->irq ); - MOD_DEC_USE_COUNT; return err; } @@ -1097,8 +1095,6 @@ free_irq( dev->irq, dev ); TLan_FreeLists( dev ); TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name ); - - MOD_DEC_USE_COUNT; return 0; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tokenring/abyss.c linux/drivers/net/tokenring/abyss.c --- v2.4.0-test11/linux/drivers/net/tokenring/abyss.c Fri Apr 28 23:00:05 2000 +++ linux/drivers/net/tokenring/abyss.c Tue Dec 5 12:29:38 2000 @@ -15,6 +15,7 @@ * Modification History: * 30-Dec-99 AF Split off from the tms380tr driver. * 22-Jan-00 AF Updated to use indirect read/writes + * 23-Nov-00 JG New PCI API, cleanups * * * TODO: @@ -23,7 +24,6 @@ * config registers) * */ -static const char *version = "abyss.c: v1.01 22/01/2000 by Adam Fritzler\n"; #include #include @@ -41,9 +41,18 @@ #include "tms380tr.h" #include "abyss.h" /* Madge-specific constants */ +static char version[] __initdata = +"abyss.c: v1.02 23/11/2000 by Adam Fritzler\n"; + #define ABYSS_IO_EXTENT 64 -int abyss_probe(void); +static struct pci_device_id abyss_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_MADGE, PCI_DEVICE_ID_MADGE_MK2, + PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NETWORK_TOKEN_RING << 8, 0x00ffffff, }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, abyss_pci_tbl); + static int abyss_open(struct net_device *dev); static int abyss_close(struct net_device *dev); static void abyss_enable(struct net_device *dev); @@ -51,17 +60,16 @@ static void abyss_read_eeprom(struct net_device *dev); static unsigned short abyss_setnselout_pins(struct net_device *dev); -void at24_writedatabyte(unsigned long regaddr, unsigned char byte); -int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr); -int at24_sendcmd(unsigned long regaddr, unsigned char cmd); -unsigned char at24_readdatabit(unsigned long regaddr); -unsigned char at24_readdatabyte(unsigned long regaddr); -int at24_waitforack(unsigned long regaddr); -int at24_waitfornack(unsigned long regaddr); -void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data); -void at24_start(unsigned long regaddr); -void at24_stop(unsigned long regaddr); -unsigned char at24_readb(unsigned long regaddr, unsigned char addr); +static void at24_writedatabyte(unsigned long regaddr, unsigned char byte); +static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr); +static int at24_sendcmd(unsigned long regaddr, unsigned char cmd); +static unsigned char at24_readdatabit(unsigned long regaddr); +static unsigned char at24_readdatabyte(unsigned long regaddr); +static int at24_waitforack(unsigned long regaddr); +static int at24_waitfornack(unsigned long regaddr); +static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data); +static void at24_start(unsigned long regaddr); +static unsigned char at24_readb(unsigned long regaddr, unsigned char addr); static unsigned short abyss_sifreadb(struct net_device *dev, unsigned short reg) { @@ -83,129 +91,100 @@ outw(val, dev->base_addr + reg); } -struct tms_abyss_card { - struct net_device *dev; - struct pci_dev *pci_dev; - struct tms_abyss_card *next; -}; -static struct tms_abyss_card *abyss_card_list = NULL; - -int __init abyss_probe(void) +static int __init abyss_attach(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int versionprinted = 0; - struct pci_dev *pdev = NULL ; + static int versionprinted; struct net_device *dev; struct net_local *tp; - int i; - - if (!pci_present()) - return (-1); /* No PCI present. */ + int i, ret, pci_irq_line; + unsigned long pci_ioaddr; - while ( (pdev=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pdev))) { - unsigned int pci_irq_line; - unsigned long pci_ioaddr; - struct tms_abyss_card *card; - - /* We only support Madge Smart 16/4 PCI Mk2 (Abyss) cards */ - if ( (pdev->vendor != PCI_VENDOR_ID_MADGE) || - (pdev->device != PCI_DEVICE_ID_MADGE_MK2) ) - continue; - - if (versionprinted++ == 0) - printk("%s", version); + if (versionprinted++ == 0) + printk("%s", version); - if (pci_enable_device(pdev)) - continue; + if (pci_enable_device(pdev)) + return -EIO; - /* Remove I/O space marker in bit 0. */ - pci_irq_line = pdev->irq; - pci_ioaddr = pci_resource_start (pdev, 0); - - if(!request_region(pci_ioaddr, ABYSS_IO_EXTENT, "abyss")) - continue; + /* Remove I/O space marker in bit 0. */ + pci_irq_line = pdev->irq; + pci_ioaddr = pci_resource_start (pdev, 0); - /* At this point we have found a valid card. */ + /* At this point we have found a valid card. */ - dev = init_trdev(NULL, 0); - if (!dev) { - release_region(pci_ioaddr, ABYSS_IO_EXTENT); - continue; - } - - if(request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ, - "abyss", dev)) { - release_region(pci_ioaddr, ABYSS_IO_EXTENT) ; - /* XXX free trdev */ - continue; /*return (-ENODEV);*/ /* continue; ?? */ - } - - /* - if (load_tms380_module("abyss.c")) { - return 0; - } - */ - - dev->base_addr = pci_ioaddr; - dev->irq = pci_irq_line; - dev->dma = 0; - - printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name); - printk("%s: IO: %#4lx IRQ: %d\n", - dev->name, pci_ioaddr, dev->irq); - /* - * The TMS SIF registers lay 0x10 above the card base address. - */ - dev->base_addr += 0x10; - - if (tmsdev_init(dev)) { - printk("%s: unable to get memory for dev->priv.\n", - dev->name); - return 0; - } + dev = init_trdev(NULL, 0); + if (!dev) + return -ENOMEM; + SET_MODULE_OWNER(dev); - abyss_read_eeprom(dev); + if (!request_region(pci_ioaddr, ABYSS_IO_EXTENT, dev->name)) { + ret = -EBUSY; + goto err_out_trdev; + } - printk("%s: Ring Station Address: ", dev->name); - printk("%2.2x", dev->dev_addr[0]); - for (i = 1; i < 6; i++) - printk(":%2.2x", dev->dev_addr[i]); - printk("\n"); - - tp = (struct net_local *)dev->priv; - tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */ - tp->setnselout = abyss_setnselout_pins; - tp->sifreadb = abyss_sifreadb; - tp->sifreadw = abyss_sifreadw; - tp->sifwriteb = abyss_sifwriteb; - tp->sifwritew = abyss_sifwritew; + ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ, + dev->name, dev); + if (ret) + goto err_out_region; + + dev->base_addr = pci_ioaddr; + dev->irq = pci_irq_line; + + printk("%s: Madge Smart 16/4 PCI Mk2 (Abyss)\n", dev->name); + printk("%s: IO: %#4lx IRQ: %d\n", + dev->name, pci_ioaddr, dev->irq); + /* + * The TMS SIF registers lay 0x10 above the card base address. + */ + dev->base_addr += 0x10; + + ret = tmsdev_init(dev); + if (ret) { + printk("%s: unable to get memory for dev->priv.\n", + dev->name); + goto err_out_irq; + } - memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1); + abyss_read_eeprom(dev); - dev->open = abyss_open; - dev->stop = abyss_close; - - if (register_trdev(dev) == 0) { - /* Enlist in the card list */ - card = kmalloc(sizeof(struct tms_abyss_card), - GFP_KERNEL); - card->next = abyss_card_list; - abyss_card_list = card; - card->dev = dev; - card->pci_dev = pdev; - } else { - printk("abyss: register_trdev() returned non-zero.\n"); - kfree(dev->priv); - kfree(dev); - return -1; - } - } - - if (abyss_card_list) - return 0; - return (-1); + printk("%s: Ring Station Address: ", dev->name); + printk("%2.2x", dev->dev_addr[0]); + for (i = 1; i < 6; i++) + printk(":%2.2x", dev->dev_addr[i]); + printk("\n"); + + tp = dev->priv; + tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */ + tp->setnselout = abyss_setnselout_pins; + tp->sifreadb = abyss_sifreadb; + tp->sifreadw = abyss_sifreadw; + tp->sifwriteb = abyss_sifwriteb; + tp->sifwritew = abyss_sifwritew; + + memcpy(tp->ProductID, "Madge PCI 16/4 Mk2", PROD_ID_SIZE + 1); + + dev->open = abyss_open; + dev->stop = abyss_close; + + ret = register_trdev(dev); + if (ret) + goto err_out_tmsdev; + + pci_set_drvdata(pdev, dev); + return 0; + +err_out_tmsdev: + kfree(dev->priv); +err_out_irq: + free_irq(pdev->irq, dev); +err_out_region: + release_region(pci_ioaddr, ABYSS_IO_EXTENT); +err_out_trdev: + unregister_netdev(dev); + kfree(dev); + return ret; } -unsigned short abyss_setnselout_pins(struct net_device *dev) +static unsigned short abyss_setnselout_pins(struct net_device *dev) { unsigned short val = 0; struct net_local *tp = (struct net_local *)dev->priv; @@ -228,7 +207,7 @@ * These access an Atmel AT24 SEEPROM using their glue chip registers. * */ -void at24_writedatabyte(unsigned long regaddr, unsigned char byte) +static void at24_writedatabyte(unsigned long regaddr, unsigned char byte) { int i; @@ -239,7 +218,7 @@ } } -int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr) +static int at24_sendfullcmd(unsigned long regaddr, unsigned char cmd, unsigned char addr) { if (at24_sendcmd(regaddr, cmd)) { at24_writedatabyte(regaddr, addr); @@ -248,7 +227,7 @@ return 0; } -int at24_sendcmd(unsigned long regaddr, unsigned char cmd) +static int at24_sendcmd(unsigned long regaddr, unsigned char cmd) { int i; @@ -261,7 +240,7 @@ return 0; } -unsigned char at24_readdatabit(unsigned long regaddr) +static unsigned char at24_readdatabit(unsigned long regaddr) { unsigned char val; @@ -273,7 +252,7 @@ return val; } -unsigned char at24_readdatabyte(unsigned long regaddr) +static unsigned char at24_readdatabyte(unsigned long regaddr) { unsigned char data = 0; int i; @@ -286,7 +265,7 @@ return data; } -int at24_waitforack(unsigned long regaddr) +static int at24_waitforack(unsigned long regaddr) { int i; @@ -297,7 +276,7 @@ return 0; } -int at24_waitfornack(unsigned long regaddr) +static int at24_waitfornack(unsigned long regaddr) { int i; for (i = 0; i < 10; i++) { @@ -307,10 +286,9 @@ return 0; } -void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data) +static void at24_setlines(unsigned long regaddr, unsigned char clock, unsigned char data) { - unsigned char val; - val = AT24_ENABLE; + unsigned char val = AT24_ENABLE; if (clock) val |= AT24_CLOCK; if (data) @@ -320,25 +298,15 @@ tms380tr_wait(20); /* Very necessary. */ } -void at24_start(unsigned long regaddr) +static void at24_start(unsigned long regaddr) { at24_setlines(regaddr, 0, 1); at24_setlines(regaddr, 1, 1); at24_setlines(regaddr, 1, 0); at24_setlines(regaddr, 0, 1); - return; } -void at24_stop(unsigned long regaddr) -{ - at24_setlines(regaddr, 0, 0); - at24_setlines(regaddr, 1, 0); - at24_setlines(regaddr, 1, 1); - at24_setlines(regaddr, 0, 1); - return; -} - -unsigned char at24_readb(unsigned long regaddr, unsigned char addr) +static unsigned char at24_readb(unsigned long regaddr, unsigned char addr) { unsigned char data = 0xff; @@ -367,7 +335,6 @@ reset_reg |= PCIBM2_RESET_REG_CHIP_NRES; outb(reset_reg, ioaddr + PCIBM2_RESET_REG); tms380tr_wait(100); - return; } /* @@ -411,14 +378,12 @@ return 0; } -void abyss_chipset_close(struct net_device *dev) +static inline void abyss_chipset_close(struct net_device *dev) { unsigned long ioaddr; ioaddr = dev->base_addr; outb(0, ioaddr + PCIBM2_RESET_REG); - - return; } /* @@ -451,15 +416,12 @@ for (i = 0; i < 6; i++) dev->dev_addr[i] = at24_readb(ioaddr + PCIBM2_SEEPROM_REG, PCIBM2_SEEPROM_BIA+i); - - return; } static int abyss_open(struct net_device *dev) { abyss_chipset_init(dev); tms380tr_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -467,41 +429,49 @@ { tms380tr_close(dev); abyss_chipset_close(dev); - MOD_DEC_USE_COUNT; return 0; } -#ifdef MODULE +static void __exit abyss_detach (struct pci_dev *pdev) +{ + struct net_device *dev = pci_get_drvdata(pdev); + + if (!dev) + BUG(); + unregister_netdev(dev); + release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); + free_irq(dev->irq, dev); + kfree(dev->priv); + kfree(dev); + pci_set_drvdata(pdev, NULL); +} + +static struct pci_driver abyss_driver = { + name: "abyss", + id_table: abyss_pci_tbl, + probe: abyss_attach, + remove: abyss_detach, +}; -int init_module(void) +static int __init abyss_init (void) { - /* Probe for cards. */ - if (abyss_probe()) { - printk(KERN_NOTICE "abyss.c: No cards found.\n"); + int rc = pci_register_driver (&abyss_driver); + if (rc < 0) + return rc; + if (rc == 0) { + pci_unregister_driver (&abyss_driver); + return -ENODEV; } - /* lock_tms380_module(); */ - return (0); + return 0; } -void cleanup_module(void) +static void __exit abyss_rmmod (void) { - struct net_device *dev; - struct tms_abyss_card *this_card; - - while (abyss_card_list) { - dev = abyss_card_list->dev; - unregister_netdev(dev); - release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT); - free_irq(dev->irq, dev); - kfree(dev->priv); - kfree(dev); - this_card = abyss_card_list; - abyss_card_list = this_card->next; - kfree(this_card); - } - /* unlock_tms380_module(); */ + pci_unregister_driver (&abyss_driver); } -#endif /* MODULE */ + +module_init(abyss_init); +module_exit(abyss_rmmod); /* diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c --- v2.4.0-test11/linux/drivers/net/tokenring/olympic.c Tue Jul 18 16:52:35 2000 +++ linux/drivers/net/tokenring/olympic.c Tue Dec 5 12:29:39 2000 @@ -101,6 +101,13 @@ static char *version = "Olympic.c v0.5.0 3/10/00 - Peter De Schrijver & Mike Phillips" ; +static struct pci_device_id olympic_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_TR_WAKE, PCI_ANY_ID, PCI_ANY_ID, }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(pci, olympic_pci_tbl); + + static char *open_maj_error[] = {"No error", "Lobe Media Test", "Physical Insertion", "Address Verification", "Neighbor Notification (Ring Poll)", "Request Parameters","FDX Registration Request", diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tokenring/tms380tr_microcode.h linux/drivers/net/tokenring/tms380tr_microcode.h --- v2.4.0-test11/linux/drivers/net/tokenring/tms380tr_microcode.h Thu Oct 14 14:22:09 1999 +++ linux/drivers/net/tokenring/tms380tr_microcode.h Mon Dec 11 12:59:45 2000 @@ -27,7 +27,7 @@ #if defined(CONFIG_TMS380TR) || defined(CONFIG_TMS380TR_MODULE) -unsigned char tms380tr_code[] = { +static unsigned char tms380tr_code[] = { 0x00, 0x00, 0x00, 0xA0, 0x00, 0x20, 0x68, 0x54, 0x73, 0x69, 0x63, 0x20, 0x64, 0x6F, 0x20, 0x65, 0x73, 0x69, 0x72, 0x20, 0x6C, 0x65, 0x61, 0x65, diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tokenring/tmspci.c linux/drivers/net/tokenring/tmspci.c --- v2.4.0-test11/linux/drivers/net/tokenring/tmspci.c Fri Apr 28 23:00:05 2000 +++ linux/drivers/net/tokenring/tmspci.c Tue Dec 5 12:29:39 2000 @@ -19,12 +19,12 @@ * Modification History: * 30-Dec-99 AF Split off from the tms380tr driver. * 22-Jan-00 AF Updated to use indirect read/writes + * 23-Nov-00 JG New PCI API, cleanups * * TODO: * 1. See if we can use MMIO instead of port accesses * */ -static const char *version = "tmspci.c: v1.01 22/01/2000 by Adam Fritzler\n"; #include #include @@ -41,33 +41,32 @@ #include #include "tms380tr.h" +static char version[] __initdata = +"tmspci.c: v1.02 23/11/2000 by Adam Fritzler\n"; + #define TMS_PCI_IO_EXTENT 32 -struct cardinfo_table { - int vendor_id; /* PCI info */ - int device_id; - int registeroffset; /* SIF offset from dev->base_addr */ +struct card_info { unsigned char nselout[2]; /* NSELOUT vals for 4mb([0]) and 16mb([1]) */ char *name; }; -struct cardinfo_table probelist[] = { - { 0, 0, - 0x0000, {0x00, 0x00}, "Unknown TMS380 Token Ring Adapter"}, - { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, - 0x0000, {0x03, 0x01}, "Compaq 4/16 TR PCI"}, - { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, - 0x0000, {0x03, 0x01}, "SK NET TR 4/16 PCI"}, - { PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING, - 0x0000, {0x03, 0x01}, "Thomas-Conrad TC4048 PCI 4/16"}, - { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339, - 0x0000, {0x03, 0x01}, "3Com Token Link Velocity"}, - { 0, 0, 0, {0x00, 0x00}, NULL} +static struct card_info card_info_table[] = { + { {0x03, 0x01}, "Compaq 4/16 TR PCI"}, + { {0x03, 0x01}, "SK NET TR 4/16 PCI"}, + { {0x03, 0x01}, "Thomas-Conrad TC4048 PCI 4/16"}, + { {0x03, 0x01}, "3Com Token Link Velocity"}, +}; + +static struct pci_device_id tmspci_pci_tbl[] __initdata = { + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, + { PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_TR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, + { PCI_VENDOR_ID_TCONRAD, PCI_DEVICE_ID_TCONRAD_TOKENRING, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, + { PCI_VENDOR_ID_3COM, PCI_DEVICE_ID_3COM_3C339, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, + { } /* Terminating entry */ }; +MODULE_DEVICE_TABLE(pci, tmspci_pci_tbl); -int tms_pci_probe(void); -static int tms_pci_open(struct net_device *dev); -static int tms_pci_close(struct net_device *dev); static void tms_pci_read_eeprom(struct net_device *dev); static unsigned short tms_pci_setnselout_pins(struct net_device *dev); @@ -91,145 +90,97 @@ outw(val, dev->base_addr + reg); } -struct tms_pci_card { - struct net_device *dev; - struct pci_dev *pci_dev; - struct cardinfo_table *cardinfo; - struct tms_pci_card *next; -}; -static struct tms_pci_card *tms_pci_card_list = NULL; - - -struct cardinfo_table * __init tms_pci_getcardinfo(unsigned short vendor, - unsigned short device) -{ - int cur; - for (cur = 1; probelist[cur].name != NULL; cur++) { - if ((probelist[cur].vendor_id == vendor) && - (probelist[cur].device_id == device)) - return &probelist[cur]; - } - - return NULL; -} - -int __init tms_pci_probe(void) +static int __init tms_pci_attach(struct pci_dev *pdev, const struct pci_device_id *ent) { - static int versionprinted = 0; - struct pci_dev *pdev = NULL ; + static int versionprinted; struct net_device *dev; struct net_local *tp; - int i; + int i, ret; + unsigned int pci_irq_line; + unsigned long pci_ioaddr; + struct card_info *cardinfo = &card_info_table[ent->driver_data]; + + if (versionprinted++ == 0) + printk("%s", version); + + if (pci_enable_device(pdev)) + return -EIO; + + /* Remove I/O space marker in bit 0. */ + pci_irq_line = pdev->irq; + pci_ioaddr = pci_resource_start (pdev, 0); + + /* At this point we have found a valid card. */ + dev = init_trdev(NULL, 0); + if (!dev) + return -ENOMEM; + SET_MODULE_OWNER(dev); + + if (!request_region(pci_ioaddr, TMS_PCI_IO_EXTENT, dev->name)) { + ret = -EBUSY; + goto err_out_trdev; + } - if (!pci_present()) - return (-1); /* No PCI present. */ - - while ( (pdev=pci_find_class(PCI_CLASS_NETWORK_TOKEN_RING<<8, pdev))) { - unsigned int pci_irq_line; - unsigned long pci_ioaddr; - struct tms_pci_card *card; - struct cardinfo_table *cardinfo; - - if ((cardinfo = - tms_pci_getcardinfo(pdev->vendor, pdev->device)) == NULL) - continue; - - if (versionprinted++ == 0) - printk("%s", version); - - if (pci_enable_device(pdev)) - continue; - - /* Remove I/O space marker in bit 0. */ - pci_irq_line = pdev->irq; - pci_ioaddr = pci_resource_start (pdev, 0); - - if(check_region(pci_ioaddr, TMS_PCI_IO_EXTENT)) - continue; - - /* At this point we have found a valid card. */ - - dev = init_trdev(NULL, 0); - if (!dev) { - continue; /*return (-ENOMEM);*/ /* continue; ?? */ - } - - request_region(pci_ioaddr, TMS_PCI_IO_EXTENT, cardinfo->name); /* XXX check return */ - if(request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ, - cardinfo->name, dev)) { - release_region(pci_ioaddr, TMS_PCI_IO_EXTENT); - /* XXX free trdev */ - continue; /*return (-ENODEV);*/ /* continue; ?? */ - } - - /* - if (load_tms380_module("tmspci.c")) { - return 0; - } - */ - - pci_ioaddr &= ~3 ; - dev->base_addr = pci_ioaddr; - dev->irq = pci_irq_line; - dev->dma = 0; - - printk("%s: %s\n", dev->name, cardinfo->name); - printk("%s: IO: %#4lx IRQ: %d\n", - dev->name, dev->base_addr, dev->irq); - /* - * Some cards have their TMS SIF registers offset from - * their given base address. Account for that here. - */ - dev->base_addr += cardinfo->registeroffset; - - tms_pci_read_eeprom(dev); + ret = request_irq(pdev->irq, tms380tr_interrupt, SA_SHIRQ, + dev->name, dev); + if (ret) + goto err_out_region; + + dev->base_addr = pci_ioaddr; + dev->irq = pci_irq_line; + dev->dma = 0; + + printk("%s: %s\n", dev->name, cardinfo->name); + printk("%s: IO: %#4lx IRQ: %d\n", + dev->name, dev->base_addr, dev->irq); + + tms_pci_read_eeprom(dev); + + printk("%s: Ring Station Address: ", dev->name); + printk("%2.2x", dev->dev_addr[0]); + for (i = 1; i < 6; i++) + printk(":%2.2x", dev->dev_addr[i]); + printk("\n"); + + ret = tmsdev_init(dev); + if (ret) { + printk("%s: unable to get memory for dev->priv.\n", dev->name); + goto err_out_irq; + } - printk("%s: Ring Station Address: ", dev->name); - printk("%2.2x", dev->dev_addr[0]); - for (i = 1; i < 6; i++) - printk(":%2.2x", dev->dev_addr[i]); - printk("\n"); - - if (tmsdev_init(dev)) { - printk("%s: unable to get memory for dev->priv.\n", dev->name); - return 0; - } - - tp = (struct net_local *)dev->priv; - tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */ - tp->setnselout = tms_pci_setnselout_pins; + tp = dev->priv; + tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */ + tp->setnselout = tms_pci_setnselout_pins; - tp->sifreadb = tms_pci_sifreadb; - tp->sifreadw = tms_pci_sifreadw; - tp->sifwriteb = tms_pci_sifwriteb; - tp->sifwritew = tms_pci_sifwritew; + tp->sifreadb = tms_pci_sifreadb; + tp->sifreadw = tms_pci_sifreadw; + tp->sifwriteb = tms_pci_sifwriteb; + tp->sifwritew = tms_pci_sifwritew; - memcpy(tp->ProductID, cardinfo->name, PROD_ID_SIZE + 1); + memcpy(tp->ProductID, cardinfo->name, PROD_ID_SIZE + 1); - tp->tmspriv = cardinfo; + tp->tmspriv = cardinfo; - dev->open = tms_pci_open; - dev->stop = tms_pci_close; + dev->open = tms380tr_open; + dev->stop = tms380tr_close; - if (register_trdev(dev) == 0) { - /* Enlist in the card list */ - card = kmalloc(sizeof(struct tms_pci_card), GFP_KERNEL); - card->next = tms_pci_card_list; - tms_pci_card_list = card; - card->dev = dev; - card->pci_dev = pdev; - card->cardinfo = cardinfo; - } else { - printk("%s: register_trdev() returned non-zero.\n", dev->name); - kfree(dev->priv); - kfree(dev); - return -1; - } - } + ret = register_trdev(dev); + if (!ret) + goto err_out_tmsdev; - if (tms_pci_card_list) - return 0; - return (-1); + pci_set_drvdata(pdev, dev); + return 0; + +err_out_tmsdev: + kfree(dev->priv); +err_out_irq: + free_irq(pdev->irq, dev); +err_out_region: + release_region(pci_ioaddr, TMS_PCI_IO_EXTENT); +err_out_trdev: + unregister_netdev(dev); + kfree(dev); + return ret; } /* @@ -255,11 +206,11 @@ dev->dev_addr[i] = tms_pci_sifreadw(dev, SIFINC) >> 8; } -unsigned short tms_pci_setnselout_pins(struct net_device *dev) +static unsigned short tms_pci_setnselout_pins(struct net_device *dev) { unsigned short val = 0; - struct net_local *tp = (struct net_local *)dev->priv; - struct cardinfo_table *cardinfo = (struct cardinfo_table *)tp->tmspriv; + struct net_local *tp = dev->priv; + struct card_info *cardinfo = tp->tmspriv; if(tp->DataRate == SPEED_4) val |= cardinfo->nselout[0]; /* Set 4Mbps */ @@ -268,65 +219,46 @@ return val; } -static int tms_pci_open(struct net_device *dev) -{ - tms380tr_open(dev); - MOD_INC_USE_COUNT; - return 0; -} - -static int tms_pci_close(struct net_device *dev) +static void __exit tms_pci_detach (struct pci_dev *pdev) { - tms380tr_close(dev); - MOD_DEC_USE_COUNT; - return 0; -} + struct net_device *dev = pci_get_drvdata(pdev); -#ifdef MODULE + if (!dev) + BUG(); + unregister_netdev(dev); + release_region(dev->base_addr, TMS_PCI_IO_EXTENT); + free_irq(dev->irq, dev); + kfree(dev->priv); + kfree(dev); + pci_set_drvdata(pdev, NULL); +} + +static struct pci_driver tms_pci_driver = { + name: "tmspci", + id_table: tmspci_pci_tbl, + probe: tms_pci_attach, + remove: tms_pci_detach, +}; -int init_module(void) +static int __init tms_pci_init (void) { - /* Probe for cards. */ - if (tms_pci_probe()) { - printk(KERN_NOTICE "tmspci.c: No cards found.\n"); + int rc = pci_register_driver (&tms_pci_driver); + if (rc < 0) + return rc; + if (rc == 0) { + pci_unregister_driver (&tms_pci_driver); + return -ENODEV; } - /* lock_tms380_module(); */ - return (0); + return 0; } -void cleanup_module(void) +static void __exit tms_pci_rmmod (void) { - struct net_device *dev; - struct tms_pci_card *this_card; - - while (tms_pci_card_list) { - dev = tms_pci_card_list->dev; - - /* - * If we used a register offset, revert here. - */ - if (dev->priv) - { - struct net_local *tp; - struct cardinfo_table *cardinfo; - - tp = (struct net_local *)dev->priv; - cardinfo = (struct cardinfo_table *)tp->tmspriv; - - dev->base_addr -= cardinfo->registeroffset; - } - unregister_netdev(dev); - release_region(dev->base_addr, TMS_PCI_IO_EXTENT); - free_irq(dev->irq, dev); - kfree(dev->priv); - kfree(dev); - this_card = tms_pci_card_list; - tms_pci_card_list = this_card->next; - kfree(this_card); - } - /* unlock_tms380_module(); */ + pci_unregister_driver (&tms_pci_driver); } -#endif /* MODULE */ + +module_init(tms_pci_init); +module_exit(tms_pci_rmmod); /* diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tulip/eeprom.c linux/drivers/net/tulip/eeprom.c --- v2.4.0-test11/linux/drivers/net/tulip/eeprom.c Mon Jun 19 13:42:39 2000 +++ linux/drivers/net/tulip/eeprom.c Sun Dec 3 17:45:22 2000 @@ -237,6 +237,7 @@ printk(KERN_INFO "%s: Index #%d - Media %s (#%d) described " "by a %s (%d) block.\n", dev->name, i, medianame[leaf->media], leaf->media, + leaf->type >= ARRAY_SIZE(block_name) ? "UNKNOWN" : block_name[leaf->type], leaf->type); } if (new_advertise) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- v2.4.0-test11/linux/drivers/net/tulip/tulip_core.c Sun Nov 19 18:44:12 2000 +++ linux/drivers/net/tulip/tulip_core.c Mon Dec 11 13:45:42 2000 @@ -52,7 +52,7 @@ /* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */ #if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \ - || defined(__sparc_) + || defined(__sparc_) || defined(__ia64__) static int rx_copybreak = 1518; #else static int rx_copybreak = 100; @@ -71,11 +71,11 @@ ToDo: Non-Intel setting could be better. */ -#if defined(__alpha__) +#if defined(__alpha__) || defined(__ia64__) static int csr0 = 0x01A00000 | 0xE000; -#elif defined(__i386__) || defined(__powerpc__) || defined(__hppa__) +#elif defined(__i386__) || defined(__powerpc__) static int csr0 = 0x01A00000 | 0x8000; -#elif defined(__sparc__) +#elif defined(__sparc__) || defined(__hppa__) /* The UltraSparc PCI controllers will disconnect at every 64-byte * crossing anyways so it makes no sense to tell Tulip to burst * any more than that. diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/tun.c linux/drivers/net/tun.c --- v2.4.0-test11/linux/drivers/net/tun.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/tun.c Sun Dec 3 17:45:22 2000 @@ -130,6 +130,7 @@ DBG(KERN_INFO "%s: tun_net_init\n", tun->name); + SET_MODULE_OWNER(dev); dev->open = tun_net_open; dev->hard_start_xmit = tun_net_xmit; dev->stop = tun_net_close; @@ -454,8 +455,6 @@ tun->dev.init = tun_net_init; tun->dev.priv = tun; - MOD_INC_USE_COUNT; - return 0; } @@ -479,7 +478,6 @@ kfree(tun); file->private_data = NULL; - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c --- v2.4.0-test11/linux/drivers/net/via-rhine.c Fri Aug 11 15:57:58 2000 +++ linux/drivers/net/via-rhine.c Mon Dec 11 13:38:29 2000 @@ -508,6 +508,7 @@ card_idx); goto err_out_free_dma; } + SET_MODULE_OWNER(dev); /* request all PIO and MMIO regions just to make sure * noone else attempts to use any portion of our I/O space */ @@ -694,15 +695,12 @@ long ioaddr = dev->base_addr; int i; - MOD_INC_USE_COUNT; - /* Reset the chip. */ writew(CmdReset, ioaddr + ChipCmd); - if (request_irq(dev->irq, &via_rhine_interrupt, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; - return -EBUSY; - } + i = request_irq(dev->irq, &via_rhine_interrupt, SA_SHIRQ, dev->name, dev); + if (i) + return i; if (debug > 1) printk(KERN_DEBUG "%s: via_rhine_open() irq %d.\n", @@ -712,7 +710,6 @@ &np->tx_bufs_dma); if (np->tx_bufs == NULL) { free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; return -ENOMEM; } @@ -1402,8 +1399,6 @@ } pci_free_consistent(np->pdev, PKT_BUF_SZ * TX_RING_SIZE, np->tx_bufs, np->tx_bufs_dma); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/wan/comx-hw-mixcom.c linux/drivers/net/wan/comx-hw-mixcom.c --- v2.4.0-test11/linux/drivers/net/wan/comx-hw-mixcom.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/net/wan/comx-hw-mixcom.c Mon Dec 11 13:38:29 2000 @@ -76,7 +76,7 @@ struct mixcom_privdata { u16 clock; char channel; - char txbusy; + long txbusy; struct sk_buff *sending; unsigned tx_ptr; struct sk_buff *recving; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/wan/comx.h linux/drivers/net/wan/comx.h --- v2.4.0-test11/linux/drivers/net/wan/comx.h Wed Apr 12 09:38:57 2000 +++ linux/drivers/net/wan/comx.h Mon Dec 11 13:38:29 2000 @@ -55,12 +55,12 @@ unsigned char line_status; struct timer_list lineup_timer; // against line jitter - int lineup_pending; + long int lineup_pending; unsigned char lineup_delay; #if 0 struct timer_list reset_timer; // for board resetting - int reset_pending; + long reset_pending; int reset_timeout; #endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/wan/sdlamain.c linux/drivers/net/wan/sdlamain.c --- v2.4.0-test11/linux/drivers/net/wan/sdlamain.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/wan/sdlamain.c Mon Dec 11 13:01:55 2000 @@ -106,14 +106,7 @@ static sdla_t* card_array; /* adapter data space */ /* Task queue element for creating a 'thread' */ -static struct tq_struct sdla_tq = -{ - NULL, /* .next */ - 0, /* .sync */ - &sdla_poll, /* .routine */ - NULL /* .data */ -}; - +static struct tq_struct sdla_tq = { routine: sdla_poll }; /******* Kernel Loadable Module Entry Points ********************************/ @@ -480,8 +473,11 @@ if(card->hw.type != SDLA_S514 && !card->wandev.piggyback) request_region(card->hw.port, card->hw.io_range, wandev->name); - if (++active == 1) - queue_task(&sdla_tq, &tq_scheduler); + if (++active == 1) { + MOD_INC_USE_COUNT; + if (schedule_task(&sdla_tq) == 0) + MOD_DEC_USE_COUNT; + } wandev->critical = 0; return 0; @@ -859,8 +855,12 @@ card->poll(card); } } - if (active) - queue_task(&sdla_tq, &tq_scheduler); + if (active) { + MOD_INC_USE_COUNT; + if (schedule_task(&sdla_tq) == 0) /* Surely not? */ + MOD_DEC_USE_COUNT; + } + MOD_DEC_USE_COUNT; } /*============================================================================ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/wan/x25_asy.h linux/drivers/net/wan/x25_asy.h --- v2.4.0-test11/linux/drivers/net/wan/x25_asy.h Mon Oct 11 10:13:25 1999 +++ linux/drivers/net/wan/x25_asy.h Mon Dec 11 13:38:29 2000 @@ -42,7 +42,7 @@ int mtu; /* Our mtu (to spot changes!) */ int buffsize; /* Max buffers sizes */ - unsigned int flags; /* Flag values/ mode etc */ + unsigned long flags; /* Flag values/ mode etc */ #define SLF_INUSE 0 /* Channel in use */ #define SLF_ESCAPE 1 /* ESC received */ #define SLF_ERROR 2 /* Parity, etc. error */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/wd.c linux/drivers/net/wd.c --- v2.4.0-test11/linux/drivers/net/wd.c Sun Nov 19 18:44:12 2000 +++ linux/drivers/net/wd.c Mon Dec 11 13:38:29 2000 @@ -86,7 +86,9 @@ { int i; struct resource *r; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); if (base_addr > 0x1ff) { /* Check a user specified location. */ r = request_region(base_addr, WD_IO_EXTENT, "wd-probe"); @@ -96,7 +98,7 @@ if (i != 0) release_resource(r); else - r->name = ei_status.name; + r->name = dev->name; return i; } else if (base_addr != 0) /* Don't probe at all. */ @@ -108,7 +110,7 @@ if (r == NULL) continue; if (wd_probe1(dev, ioaddr) == 0) { - r->name = ei_status.name; + r->name = dev->name; return 0; } release_resource(r); @@ -263,11 +265,12 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - if (request_irq(dev->irq, ei_interrupt, 0, model_name, dev)) { + i = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (i) { printk (" unable to get IRQ %d.\n", dev->irq); kfree(dev->priv); dev->priv = NULL; - return -EAGAIN; + return i; } /* OK, were are certain this is going to work. Setup the device. */ @@ -324,7 +327,6 @@ outb(ei_status.reg0, ioaddr); /* WD_CMDREG */ ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -430,8 +432,6 @@ /* And disable the shared memory. */ outb(ei_status.reg0 & ~WD_MEMENB, wd_cmdreg); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c --- v2.4.0-test11/linux/drivers/net/winbond-840.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/net/winbond-840.c Mon Dec 11 13:38:29 2000 @@ -367,6 +367,7 @@ dev = init_etherdev(NULL, sizeof(*np)); if (!dev) return -ENOMEM; + SET_MODULE_OWNER(dev); #ifdef USE_IO_OPS ioaddr = pci_resource_start(pdev, 0); @@ -623,12 +624,9 @@ writel(0x00000001, ioaddr + PCIBusCfg); /* Reset */ - MOD_INC_USE_COUNT; - - if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + i = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev); + if (i) + return i; if (debug > 1) printk(KERN_DEBUG "%s: w89c840_open() irq %d.\n", @@ -1304,8 +1302,6 @@ dev_kfree_skb(np->tx_skbuff[i]); np->tx_skbuff[i] = 0; } - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c --- v2.4.0-test11/linux/drivers/net/yellowfin.c Sat May 13 08:19:21 2000 +++ linux/drivers/net/yellowfin.c Mon Dec 11 13:38:29 2000 @@ -305,9 +305,6 @@ for status. */ struct yellowfin_desc rx_ring[RX_RING_SIZE]; struct yellowfin_desc tx_ring[TX_RING_SIZE*2]; - const char *product_name; - struct net_device *next_module; - void *priv_addr; /* Unaligned address for kfree */ /* The addresses of receive-in-place skbuffs. */ struct sk_buff* rx_skbuff[RX_RING_SIZE]; /* The saved address of a sent-in-place packet/buffer, for skfree(). */ @@ -426,8 +423,6 @@ printk(KERN_DEBUG "%s: yellowfin_open() irq %d.\n", dev->name, dev->irq); - MOD_INC_USE_COUNT; - yellowfin_init_ring(dev); YF_OUTL(virt_to_bus(yp->rx_ring), ioaddr + RxPtr); @@ -1110,8 +1105,6 @@ dev->name, bogus_rx); } #endif - MOD_DEC_USE_COUNT; - return 0; } @@ -1230,24 +1223,19 @@ chip_idx = ent->driver_data; flags = chip_info[chip_idx].flags; - dev = init_etherdev(NULL, 0); + dev = init_etherdev(NULL, sizeof(*yp)); if (!dev) { printk (KERN_ERR PFX "cannot allocate ethernet device\n"); return -ENOMEM; } + SET_MODULE_OWNER(dev); - dev->priv = kmalloc(sizeof(*yp) + PRIV_ALIGN, GFP_KERNEL); - if (!dev->priv) - goto err_out_free_netdev; - yp = (void *)(((long)dev->priv + PRIV_ALIGN) & ~PRIV_ALIGN); - memset(yp, 0, sizeof(*yp)); - yp->priv_addr = dev->priv; /* store real addr for kfree */ - dev->priv = yp; /* use aligned addr */ + yp = dev->priv; if (!request_region (pci_resource_start (pdev, 0), YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) { printk (KERN_ERR PFX "cannot obtain I/O port region\n"); - goto err_out_free_priv; + goto err_out_free_netdev; } if (!request_mem_region (pci_resource_start (pdev, 1), YELLOWFIN_SIZE, YELLOWFIN_MODULE_NAME)) { @@ -1255,8 +1243,8 @@ goto err_out_free_pio_region; } - /* XXX check enable_device for failure */ - pci_enable_device (pdev); + if (pci_enable_device (pdev)) + goto err_out_free_mmio_region; pci_set_master (pdev); #ifdef USE_IO_OPS @@ -1264,7 +1252,8 @@ #else real_ioaddr = ioaddr = pci_resource_start (pdev, 1); ioaddr = (long) ioremap(ioaddr, YELLOWFIN_SIZE); - /* XXX check for failure */ + if (!ioaddr) + goto err_out_free_mmio_region; #endif irq = pdev->irq; @@ -1348,10 +1337,10 @@ return 0; +err_out_free_mmio_region: + release_mem_region (pci_resource_start (pdev, 1), YELLOWFIN_SIZE); err_out_free_pio_region: release_region (pci_resource_start (pdev, 0), YELLOWFIN_SIZE); -err_out_free_priv: - kfree (dev->priv); err_out_free_netdev: unregister_netdev (dev); kfree (dev); @@ -1363,23 +1352,18 @@ struct net_device *dev = pdev->driver_data; struct yellowfin_private *np; - if (!dev) { - printk (KERN_ERR "remove non-existent device\n"); - return; - } - np = (struct yellowfin_private *) dev->priv; + if (!dev) + BUG(); + np = dev->priv; unregister_netdev (dev); -#ifdef USE_IO_OPS release_region (dev->base_addr, YELLOWFIN_SIZE); -#else - iounmap ((void *) dev->base_addr); release_mem_region (dev->base_addr, YELLOWFIN_SIZE); -#endif - if (np->priv_addr) - kfree (np->priv_addr); +#ifndef USE_IO_OPS + iounmap ((void *) dev->base_addr); +#endif kfree (dev); } @@ -1398,11 +1382,7 @@ if (debug) /* Emit version even if no cards detected. */ printk(KERN_INFO "%s", version); - if (pci_register_driver (&yellowfin_driver) > 0) - return 0; - - pci_unregister_driver (&yellowfin_driver); - return -ENODEV; + return pci_module_init (&yellowfin_driver); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/nubus/nubus.c linux/drivers/nubus/nubus.c --- v2.4.0-test11/linux/drivers/nubus/nubus.c Thu Oct 28 14:34:46 1999 +++ linux/drivers/nubus/nubus.c Sun Dec 3 17:48:19 2000 @@ -27,8 +27,6 @@ extern void via_nubus_init(void); extern void oss_nubus_init(void); -extern int console_loglevel; - /* Constants */ /* This is, of course, the size in bytelanes, rather than the size in @@ -967,8 +965,9 @@ int count, int *eof, void *data) { int nprinted, len, begin = 0; - int slot; - + int slot,size; + struct nubus_board* board; + len = sprintf(buf, "Nubus devices found:\n"); /* Walk the list of NuBus boards */ for (board = nubus_boards; board != NULL; board = board->next) @@ -987,7 +986,7 @@ if (slot==16 || len+begin < off) *eof = 1; off -= begin; - *strat = buf + off; + *start = buf + off; len -= off; if (len>count) len = count; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog --- v2.4.0-test11/linux/drivers/parport/ChangeLog Sun Oct 8 10:50:20 2000 +++ linux/drivers/parport/ChangeLog Mon Dec 11 13:43:59 2000 @@ -1,3 +1,9 @@ +2000-11-21 Tim Waugh + + * parport_pc.c (parport_pc_ecp_write_block_pio): Fix + reverse-to-forward logic. Spotted by Roland Kuck + . + 2000-09-16 Cesar Eduardo Barros * parport_pc.c (sio_via_686a_probe): Handle case diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/Makefile linux/drivers/parport/Makefile --- v2.4.0-test11/linux/drivers/parport/Makefile Tue Oct 31 12:42:26 2000 +++ linux/drivers/parport/Makefile Mon Dec 11 13:43:59 2000 @@ -26,6 +26,7 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o +obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o # Extract lists of the multi-part drivers. # The 'int-*' lists are the intermediate files used to build the multi's. diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/parport_amiga.c linux/drivers/parport/parport_amiga.c --- v2.4.0-test11/linux/drivers/parport/parport_amiga.c Mon Jun 19 13:42:38 2000 +++ linux/drivers/parport/parport_amiga.c Mon Nov 27 17:11:26 2000 @@ -1,4 +1,4 @@ -/* Low-level parallel port routines for the Amiga buildin port +/* Low-level parallel port routines for the Amiga built-in port * * Author: Joerg Dorchain * @@ -6,9 +6,9 @@ * lp_intern. code. * * The built-in Amiga parallel port provides one port at a fixed address - * with 8 bisdirecttional data lines (D0 - D7) and 3 bidirectional status - * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically in - * hardware when the data register is accessed), and 1 input control line + * with 8 bidirectional data lines (D0 - D7) and 3 bidirectional status + * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically + * in hardware when the data register is accessed), and 1 input control line * /ACK, able to cause an interrupt, but both not directly settable by * software. */ @@ -20,22 +20,24 @@ #include #include #include +#include #include #undef DEBUG #ifdef DEBUG #define DPRINTK printk #else -static inline void DPRINTK(void *nothing, ...) {} +#define DPRINTK(x...) do { } while (0) #endif static struct parport *this_port = NULL; static void amiga_write_data(struct parport *p, unsigned char data) { -DPRINTK("write_data %c\n",data); + DPRINTK("write_data %c\n",data); /* Triggers also /STROBE. This behavior cannot be changed */ ciaa.prb = data; + mb(); } static unsigned char amiga_read_data(struct parport *p) @@ -71,13 +73,13 @@ static void amiga_write_control(struct parport *p, unsigned char control) { -DPRINTK("write_control %02x\n",control); + DPRINTK("write_control %02x\n",control); /* No implementation possible */ } static unsigned char amiga_read_control( struct parport *p) { -DPRINTK("read_control \n"); + DPRINTK("read_control \n"); return control_amiga_to_pc(0); } @@ -85,7 +87,7 @@ { unsigned char old; -DPRINTK("frob_control mask %02x, value %02x\n",mask,val); + DPRINTK("frob_control mask %02x, value %02x\n",mask,val); old = amiga_read_control(p); amiga_write_control(p, (old & ~mask) ^ val); return old; @@ -130,7 +132,7 @@ unsigned char status; status = status_amiga_to_pc(ciab.pra & 7); -DPRINTK("read_status %02x\n", status); + DPRINTK("read_status %02x\n", status); return status; } @@ -154,12 +156,14 @@ { DPRINTK("forward\n"); ciaa.ddrb = 0xff; /* all pins output */ + mb(); } static void amiga_data_reverse(struct parport *p) { DPRINTK("reverse\n"); ciaa.ddrb = 0; /* all pins input */ + mb(); } static void amiga_init_state(struct pardevice *dev, struct parport_state *s) @@ -172,18 +176,22 @@ static void amiga_save_state(struct parport *p, struct parport_state *s) { + mb(); s->u.amiga.data = ciaa.prb; s->u.amiga.datadir = ciaa.ddrb; s->u.amiga.status = ciab.pra & 7; s->u.amiga.statusdir = ciab.ddra & 7; + mb(); } static void amiga_restore_state(struct parport *p, struct parport_state *s) { + mb(); ciaa.prb = s->u.amiga.data; ciaa.ddrb = s->u.amiga.datadir; ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status; ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir; + mb(); } static void amiga_inc_use_count(void) @@ -238,56 +246,58 @@ int __init parport_amiga_init(void) { struct parport *p; + int err; - if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_PARALLEL)) { - if (!request_mem_region(CIAA_PHYSADDR+0x100, 1, "parallel")) - return 0; - ciaa.ddrb = 0xff; - ciab.ddra &= 0xf8; - if (!(p = parport_register_port((unsigned long)&ciaa.prb, - IRQ_AMIGA_CIAA_FLG, PARPORT_DMA_NONE, - &pp_amiga_ops))) { - release_mem_region(CIAA_PHYSADDR+0x100, 1); - return 0; - } - if (!request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p)) { - parport_unregister_port (p); - release_mem_region(CIAA_PHYSADDR+0x100, 1); - return 0; - } - - this_port = p; - printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); - /* XXX: set operating mode */ - parport_proc_register(p); + if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL)) + return -ENODEV; - parport_announce_port(p); + err = -EBUSY; + if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel")) + goto out_mem; + + ciaa.ddrb = 0xff; + ciab.ddra &= 0xf8; + mb(); + + p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, + PARPORT_DMA_NONE, &pp_amiga_ops); + if (!p) + goto out_port; + + err = request_irq(IRQ_AMIGA_CIAA_FLG, amiga_interrupt, 0, p->name, p); + if (err) + goto out_irq; + + this_port = p; + printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); + /* XXX: set operating mode */ + parport_proc_register(p); - return 1; + parport_announce_port(p); - } return 0; -} - -#ifdef MODULE - -MODULE_AUTHOR("Joerg Dorchain "); -MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); -MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); -int init_module(void) -{ - return ! parport_amiga_init(); +out_irq: + parport_unregister_port(p); +out_port: + release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); +out_mem: + return err; } -void cleanup_module(void) +void __exit parport_amiga_exit(void) { if (this_port->irq != PARPORT_IRQ_NONE) free_irq(IRQ_AMIGA_CIAA_FLG, this_port); parport_proc_unregister(this_port); parport_unregister_port(this_port); - release_mem_region(CIAA_PHYSADDR+0x100, 1); + release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); } -#endif +MODULE_AUTHOR("Joerg Dorchain "); +MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); +MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); + +module_init(parport_amiga_init) +module_exit(parport_amiga_exit) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/parport_atari.c linux/drivers/parport/parport_atari.c --- v2.4.0-test11/linux/drivers/parport/parport_atari.c Mon Aug 9 12:32:28 1999 +++ linux/drivers/parport/parport_atari.c Mon Nov 27 17:11:26 2000 @@ -113,6 +113,46 @@ } static void +parport_atari_enable_irq(struct parport *p) +{ + enable_irq(IRQ_MFP_BUSY); +} + +static void +parport_atari_disable_irq(struct parport *p) +{ + disable_irq(IRQ_MFP_BUSY); +} + +static void +parport_atari_data_forward(struct parport *p) +{ + unsigned long flags; + + save_flags(flags); + cli(); + /* Soundchip port B as output. */ + sound_ym.rd_data_reg_sel = 7; + sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x40; + restore_flags(flags); +} + +static void +parport_atari_data_reverse(struct parport *p) +{ +#if 0 /* too dangerous, can kill sound chip */ + unsigned long flags; + + save_flags(flags); + cli(); + /* Soundchip port B as input. */ + sound_ym.rd_data_reg_sel = 7; + sound_ym.wd_data = sound_ym.rd_data_reg_sel & ~0x40; + restore_flags(flags); +#endif +} + +static void parport_atari_inc_use_count(void) { MOD_INC_USE_COUNT; @@ -134,11 +174,11 @@ parport_atari_read_status, - NULL, /* enable_irq - FIXME */ - NULL, /* disable_irq - FIXME */ + parport_atari_enable_irq, + parport_atari_disable_irq, - NULL, /* data_forward - FIXME */ - NULL, /* data_reverse - FIXME */ + parport_atari_data_forward, + parport_atari_data_reverse, parport_atari_init_state, parport_atari_save_state, @@ -147,18 +187,18 @@ parport_atari_inc_use_count, parport_atari_dec_use_count, - NULL, /* epp_write_data */ - NULL, /* epp_read_data */ - NULL, /* epp_write_addr */ - NULL, /* epp_read_addr */ - - NULL, /* ecp_write_data */ - NULL, /* ecp_read_data */ - NULL, /* ecp_write_addr */ - - NULL, /* compat_write_data */ - NULL, /* nibble_read_data */ - NULL, /* byte_read_data */ + parport_ieee1284_epp_write_data, + parport_ieee1284_epp_read_data, + parport_ieee1284_epp_write_addr, + parport_ieee1284_epp_read_addr, + + parport_ieee1284_ecp_write_data, + parport_ieee1284_ecp_read_data, + parport_ieee1284_ecp_write_addr, + + parport_ieee1284_write_compat, + parport_ieee1284_read_nibble, + parport_ieee1284_read_byte, }; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/parport_gsc.c linux/drivers/parport/parport_gsc.c --- v2.4.0-test11/linux/drivers/parport/parport_gsc.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/parport/parport_gsc.c Mon Dec 11 13:43:59 2000 @@ -0,0 +1,573 @@ +/* + * Low-level parallel-support for PC-style hardware integrated in the + * LASI-Controller (on GSC-Bus) for HP-PARISC Workstations + * + * 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. + * + * by Helge Deller + * + * + * based on parport_pc.c by + * Grant Guenther + * Phil Blundell + * Tim Waugh + * Jose Renau + * David Campbell + * Andrea Arcangeli + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + + +#undef DEBUG /* undef for production */ + +#ifdef DEBUG +#define DPRINTK printk +#else +#define DPRINTK(stuff...) +#endif + + +/* + * Clear TIMEOUT BIT in EPP MODE + * + * This is also used in SPP detection. + */ +static int clear_epp_timeout(struct parport *pb) +{ + unsigned char r; + + if (!(parport_gsc_read_status(pb) & 0x01)) + return 1; + + /* To clear timeout some chips require double read */ + parport_gsc_read_status(pb); + r = parport_gsc_read_status(pb); + parport_writeb (r | 0x01, STATUS (pb)); /* Some reset by writing 1 */ + parport_writeb (r & 0xfe, STATUS (pb)); /* Others by writing 0 */ + r = parport_gsc_read_status(pb); + + return !(r & 0x01); +} + +/* + * Access functions. + * + * Most of these aren't static because they may be used by the + * parport_xxx_yyy macros. extern __inline__ versions of several + * of these are in parport_gsc.h. + */ + +static void parport_gsc_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + DPRINTK(__FILE__ ": got IRQ\n"); + parport_generic_irq(irq, (struct parport *) dev_id, regs); +} + +void parport_gsc_write_data(struct parport *p, unsigned char d) +{ + DPRINTK(__FILE__ ": write (0x%02x) %c \n", d, d); + parport_writeb (d, DATA (p)); +} + +unsigned char parport_gsc_read_data(struct parport *p) +{ +#ifdef DEBUG + unsigned char c = parport_readb (DATA (p)); + DPRINTK(__FILE__ ": read (0x%02x) %c\n", c,c); + return c; +#else + return parport_readb (DATA (p)); +#endif +} + +void parport_gsc_write_control(struct parport *p, unsigned char d) +{ + const unsigned char wm = (PARPORT_CONTROL_STROBE | + PARPORT_CONTROL_AUTOFD | + PARPORT_CONTROL_INIT | + PARPORT_CONTROL_SELECT); + + /* Take this out when drivers have adapted to the newer interface. */ + if (d & 0x20) { + printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n", + p->name, p->cad->name); + parport_gsc_data_reverse (p); + } + + __parport_gsc_frob_control (p, wm, d & wm); +} + +unsigned char parport_gsc_read_control(struct parport *p) +{ + const unsigned char wm = (PARPORT_CONTROL_STROBE | + PARPORT_CONTROL_AUTOFD | + PARPORT_CONTROL_INIT | + PARPORT_CONTROL_SELECT); + const struct parport_gsc_private *priv = p->physport->private_data; + return priv->ctr & wm; /* Use soft copy */ +} + +unsigned char parport_gsc_frob_control (struct parport *p, unsigned char mask, + unsigned char val) +{ + const unsigned char wm = (PARPORT_CONTROL_STROBE | + PARPORT_CONTROL_AUTOFD | + PARPORT_CONTROL_INIT | + PARPORT_CONTROL_SELECT); + + /* Take this out when drivers have adapted to the newer interface. */ + if (mask & 0x20) { + printk (KERN_DEBUG "%s (%s): use data_%s for this!\n", + p->name, p->cad->name, + (val & 0x20) ? "reverse" : "forward"); + if (val & 0x20) + parport_gsc_data_reverse (p); + else + parport_gsc_data_forward (p); + } + + /* Restrict mask and val to control lines. */ + mask &= wm; + val &= wm; + + return __parport_gsc_frob_control (p, mask, val); +} + +unsigned char parport_gsc_read_status(struct parport *p) +{ + return parport_readb (STATUS (p)); +} + +void parport_gsc_disable_irq(struct parport *p) +{ + __parport_gsc_frob_control (p, 0x10, 0); +} + +void parport_gsc_enable_irq(struct parport *p) +{ + __parport_gsc_frob_control (p, 0x10, 0x10); +} + +void parport_gsc_data_forward (struct parport *p) +{ + __parport_gsc_frob_control (p, 0x20, 0); +} + +void parport_gsc_data_reverse (struct parport *p) +{ + __parport_gsc_frob_control (p, 0x20, 0x20); +} + +void parport_gsc_init_state(struct pardevice *dev, struct parport_state *s) +{ + s->u.pc.ctr = 0xc | (dev->irq_func ? 0x10 : 0x0); +} + +void parport_gsc_save_state(struct parport *p, struct parport_state *s) +{ + s->u.pc.ctr = parport_readb (CONTROL (p)); +} + +void parport_gsc_restore_state(struct parport *p, struct parport_state *s) +{ + parport_writeb (s->u.pc.ctr, CONTROL (p)); +} + +void parport_gsc_inc_use_count(void) +{ +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif +} + +void parport_gsc_dec_use_count(void) +{ +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif +} + + +struct parport_operations parport_gsc_ops = +{ + write_data: parport_gsc_write_data, + read_data: parport_gsc_read_data, + + write_control: parport_gsc_write_control, + read_control: parport_gsc_read_control, + frob_control: parport_gsc_frob_control, + + read_status: parport_gsc_read_status, + + enable_irq: parport_gsc_enable_irq, + disable_irq: parport_gsc_disable_irq, + + data_forward: parport_gsc_data_forward, + data_reverse: parport_gsc_data_reverse, + + init_state: parport_gsc_init_state, + save_state: parport_gsc_save_state, + restore_state: parport_gsc_restore_state, + + inc_use_count: parport_gsc_inc_use_count, + dec_use_count: parport_gsc_dec_use_count, + + epp_write_data: parport_ieee1284_epp_write_data, + epp_read_data: parport_ieee1284_epp_read_data, + epp_write_addr: parport_ieee1284_epp_write_addr, + epp_read_addr: parport_ieee1284_epp_read_addr, + + ecp_write_data: parport_ieee1284_ecp_write_data, + ecp_read_data: parport_ieee1284_ecp_read_data, + ecp_write_addr: parport_ieee1284_ecp_write_addr, + + compat_write_data: parport_ieee1284_write_compat, + nibble_read_data: parport_ieee1284_read_nibble, + byte_read_data: parport_ieee1284_read_byte, +}; + +/* --- Mode detection ------------------------------------- */ + +/* + * Checks for port existence, all ports support SPP MODE + */ +static int __devinit parport_SPP_supported(struct parport *pb) +{ + unsigned char r, w; + + /* + * first clear an eventually pending EPP timeout + * I (sailer@ife.ee.ethz.ch) have an SMSC chipset + * that does not even respond to SPP cycles if an EPP + * timeout is pending + */ + clear_epp_timeout(pb); + + /* Do a simple read-write test to make sure the port exists. */ + w = 0xc; + parport_writeb (w, CONTROL (pb)); + + /* Is there a control register that we can read from? Some + * ports don't allow reads, so read_control just returns a + * software copy. Some ports _do_ allow reads, so bypass the + * software copy here. In addition, some bits aren't + * writable. */ + r = parport_readb (CONTROL (pb)); + if ((r & 0xf) == w) { + w = 0xe; + parport_writeb (w, CONTROL (pb)); + r = parport_readb (CONTROL (pb)); + parport_writeb (0xc, CONTROL (pb)); + if ((r & 0xf) == w) + return PARPORT_MODE_PCSPP; + } + + /* Try the data register. The data lines aren't tri-stated at + * this stage, so we expect back what we wrote. */ + w = 0xaa; + parport_gsc_write_data (pb, w); + r = parport_gsc_read_data (pb); + if (r == w) { + w = 0x55; + parport_gsc_write_data (pb, w); + r = parport_gsc_read_data (pb); + if (r == w) + return PARPORT_MODE_PCSPP; + } + + return 0; +} + +/* Detect PS/2 support. + * + * Bit 5 (0x20) sets the PS/2 data direction; setting this high + * allows us to read data from the data lines. In theory we would get back + * 0xff but any peripheral attached to the port may drag some or all of the + * lines down to zero. So if we get back anything that isn't the contents + * of the data register we deem PS/2 support to be present. + * + * Some SPP ports have "half PS/2" ability - you can't turn off the line + * drivers, but an external peripheral with sufficiently beefy drivers of + * its own can overpower them and assert its own levels onto the bus, from + * where they can then be read back as normal. Ports with this property + * and the right type of device attached are likely to fail the SPP test, + * (as they will appear to have stuck bits) and so the fact that they might + * be misdetected here is rather academic. + */ + +static int __devinit parport_PS2_supported(struct parport *pb) +{ + int ok = 0; + + clear_epp_timeout(pb); + + /* try to tri-state the buffer */ + parport_gsc_data_reverse (pb); + + parport_gsc_write_data(pb, 0x55); + if (parport_gsc_read_data(pb) != 0x55) ok++; + + parport_gsc_write_data(pb, 0xaa); + if (parport_gsc_read_data(pb) != 0xaa) ok++; + + /* cancel input mode */ + parport_gsc_data_forward (pb); + + if (ok) { + pb->modes |= PARPORT_MODE_TRISTATE; + } else { + struct parport_gsc_private *priv = pb->private_data; + priv->ctr_writable &= ~0x20; + } + + return ok; +} + + +/* --- Initialisation code -------------------------------- */ + +struct parport *__devinit parport_gsc_probe_port (unsigned long base, + unsigned long base_hi, + int irq, int dma, + struct pci_dev *dev) +{ + struct parport_gsc_private *priv; + struct parport_operations *ops; + struct parport tmp; + struct parport *p = &tmp; + + if (check_region(base, 3)) + return NULL; + + priv = kmalloc (sizeof (struct parport_gsc_private), GFP_KERNEL); + if (!priv) { + printk (KERN_DEBUG "parport (0x%lx): no memory!\n", base); + return NULL; + } + ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); + if (!ops) { + printk (KERN_DEBUG "parport (0x%lx): no memory for ops!\n", + base); + kfree (priv); + return NULL; + } + memcpy (ops, &parport_gsc_ops, sizeof (struct parport_operations)); + priv->ctr = 0xc; + priv->ctr_writable = 0xff; + priv->dma_buf = 0; + priv->dma_handle = 0; + priv->dev = dev; + p->base = base; + p->base_hi = base_hi; + p->irq = irq; + p->dma = dma; + p->modes = PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT; + p->ops = ops; + p->private_data = priv; + p->physport = p; + if (!parport_SPP_supported (p)) { + /* No port. */ + kfree (priv); + return NULL; + } + parport_PS2_supported (p); + + if (!(p = parport_register_port(base, PARPORT_IRQ_NONE, + PARPORT_DMA_NONE, ops))) { + kfree (priv); + kfree (ops); + return NULL; + } + + p->base_hi = base_hi; + p->modes = tmp.modes; + p->size = (p->modes & PARPORT_MODE_EPP)?8:3; + p->private_data = priv; + + printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); + p->irq = irq; + if (p->irq == PARPORT_IRQ_AUTO) { + p->irq = PARPORT_IRQ_NONE; + } + if (p->irq != PARPORT_IRQ_NONE) { + printk(", irq %d", p->irq); + + if (p->dma == PARPORT_DMA_AUTO) { + p->dma = PARPORT_DMA_NONE; + } + } + if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq + is mandatory (see above) */ + p->dma = PARPORT_DMA_NONE; + + printk(" ["); +#define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}} + { + int f = 0; + printmode(PCSPP); + printmode(TRISTATE); + printmode(COMPAT) + printmode(EPP); +// printmode(ECP); +// printmode(DMA); + } +#undef printmode + printk("]\n"); + parport_proc_register(p); + + request_region (p->base, 3, p->name); + if (p->size > 3) + request_region (p->base + 3, p->size - 3, p->name); + if (p->modes & PARPORT_MODE_ECP) + request_region (p->base_hi, 3, p->name); + + if (p->irq != PARPORT_IRQ_NONE) { + if (request_irq (p->irq, parport_gsc_interrupt, + 0, p->name, p)) { + printk (KERN_WARNING "%s: irq %d in use, " + "resorting to polled operation\n", + p->name, p->irq); + p->irq = PARPORT_IRQ_NONE; + p->dma = PARPORT_DMA_NONE; + } + } + + /* Done probing. Now put the port into a sensible start-up state. */ + + parport_gsc_write_data(p, 0); + parport_gsc_data_forward (p); + + /* Now that we've told the sharing engine about the port, and + found out its characteristics, let the high-level drivers + know about it. */ + parport_announce_port (p); + + return p; +} + + +#define PARPORT_GSC_OFFSET 0x800 + +static int __initdata parport_count; + +static int __init +parport_init_chip(struct hp_device *d, struct pa_iodc_driver *dri) +{ + unsigned long port; + int irq; + + irq = busdevice_alloc_irq(d); + + if (!irq) { + printk("IRQ not found for parallel device at 0x%p\n", d->hpa); + return -ENODEV; + } + + port = ((unsigned long) d->hpa) + PARPORT_GSC_OFFSET; + + /* + some older machines with ASP-chip don't support the enhanced parport modes + */ + if (!pdc_add_valid( (void *)(port+4))) { + /* Initialize bidirectional-mode (0x10) & data-tranfer-mode #1 (0x20) */ + printk("%s: initialize bidirectional-mode.\n", __FUNCTION__); + parport_writeb ( (0x10 + 0x20), port + 4); + } else { + printk("%s: enhanced parport-modes not supported.\n", __FUNCTION__); + } + + if (parport_gsc_probe_port(port, 0, + irq, /* PARPORT_IRQ_NONE */ + PARPORT_DMA_NONE, NULL)) + parport_count++; + + return 0; +} + +static struct pa_iodc_driver parport_drivers_for[] __initdata = { + {HPHW_FIO, 0x0, 0x0, 0x74, 0x0, 0, /* 715/64 */ + DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE, + "parallel device", "HP 7xx - Series", (void *) parport_init_chip}, + { 0 } +}; + +int __init +parport_gsc_init ( void ) +{ + parport_count = 0; + + register_driver(parport_drivers_for); + + return parport_count; +} + +/* Exported symbols. */ +EXPORT_NO_SYMBOLS; + + +#ifdef MODULE + +MODULE_AUTHOR("Helge Deller "); +MODULE_DESCRIPTION("HP-PARISC PC-style parallel port driver"); +MODULE_SUPPORTED_DEVICE("integrated PC-style parallel port"); + +int init_module(void) +{ + return !parport_gsc_init (); +} + +void cleanup_module(void) +{ + struct parport *p = parport_enumerate(), *tmp; + while (p) { + tmp = p->next; + if (p->modes & PARPORT_MODE_PCSPP) { + struct parport_gsc_private *priv = p->private_data; + struct parport_operations *ops = p->ops; + if (p->dma != PARPORT_DMA_NONE) + free_dma(p->dma); + if (p->irq != PARPORT_IRQ_NONE) + free_irq(p->irq, p); + release_region(p->base, 3); + if (p->size > 3) + release_region(p->base + 3, p->size - 3); + if (p->modes & PARPORT_MODE_ECP) + release_region(p->base_hi, 3); + parport_proc_unregister(p); + if (priv->dma_buf) + pci_free_consistent(priv->dev, PAGE_SIZE, + priv->dma_buf, + priv->dma_handle); + kfree (p->private_data); + parport_unregister_port(p); + kfree (ops); /* hope no-one cached it */ + } + p = tmp; + } +} +#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/parport_mfc3.c linux/drivers/parport/parport_mfc3.c --- v2.4.0-test11/linux/drivers/parport/parport_mfc3.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/parport/parport_mfc3.c Mon Nov 27 17:11:26 2000 @@ -332,75 +332,83 @@ int __init parport_mfc3_init(void) { struct parport *p; - int pias = 0; + int pias; struct pia *pp; struct zorro_dev *z = NULL; if (!MACH_IS_AMIGA) - return 0; + return -ENODEV; while ((z = zorro_find_device(ZORRO_PROD_BSC_MULTIFACE_III, z))) { unsigned long piabase = z->resource.start+PIABASE; if (!request_mem_region(piabase, sizeof(struct pia), "PIA")) continue; + pp = (struct pia *)ZTWO_VADDR(piabase); - if (pias < MAX_MFC) { - pp->crb = 0; - pp->pddrb = 255; /* all data pins output */ - pp->crb = PIA_DDR|32|8; - dummy = pp->pddrb; /* reading clears interrupt */ - pp->cra = 0; - pp->pddra = 0xe0; /* /RESET, /DIR ,/AUTO-FEED output */ - pp->cra = PIA_DDR; - pp->ppra = 0; /* reset printer */ - udelay(10); - pp->ppra = 128; - if ((p = parport_register_port((unsigned long)pp, - IRQ_AMIGA_PORTS, PARPORT_DMA_NONE, - &pp_mfc3_ops))) { - this_port[pias++] = p; - printk(KERN_INFO "%s: Multiface III port using irq\n", p->name); - /* XXX: set operating mode */ - parport_proc_register(p); - - if (p->irq != PARPORT_IRQ_NONE) - if (use_cnt++ == 0) - if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, SA_SHIRQ, p->name, &pp_mfc3_ops)) - use_cnt--; - - p->private_data = (void *)piabase; - parport_announce_port (p); - } + pp->crb = 0; + pp->pddrb = 255; /* all data pins output */ + pp->crb = PIA_DDR|32|8; + dummy = pp->pddrb; /* reading clears interrupt */ + pp->cra = 0; + pp->pddra = 0xe0; /* /RESET, /DIR ,/AUTO-FEED output */ + pp->cra = PIA_DDR; + pp->ppra = 0; /* reset printer */ + udelay(10); + pp->ppra = 128; + p = parport_register_port((unsigned long)pp, IRQ_AMIGA_PORTS, + PARPORT_DMA_NONE, &pp_mfc3_ops); + if (!p) + goto out_port; + + if (p->irq != PARPORT_IRQ_NONE) { + if (use_cnt++ == 0) + if (request_irq(IRQ_AMIGA_PORTS, mfc3_interrupt, SA_SHIRQ, p->name, &pp_mfc3_ops)) + goto out_irq; } - } - return pias; -} - -#ifdef MODULE -MODULE_AUTHOR("Joerg Dorchain "); -MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port"); -MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port"); + this_port[pias++] = p; + printk(KERN_INFO "%s: Multiface III port using irq\n", p->name); + /* XXX: set operating mode */ + parport_proc_register(p); + + p->private_data = (void *)piabase; + parport_announce_port (p); + + if (pias >= MAX_MFC) + break; + continue; + + out_irq: + parport_unregister_port(p); + out_port: + release_mem_region(piabase, sizeof(struct pia)); + } -int init_module(void) -{ - return ! parport_mfc3_init(); + return pias ? 0 : -ENODEV; } -void cleanup_module(void) +void __exit parport_mfc3_exit(void) { int i; - for (i = 0; i < MAX_MFC; i++) - if (this_port[i] != NULL) { - if (p->irq != PARPORT_IRQ_NONE) - if (--use_cnt == 0) - free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); - parport_proc_unregister(this_port[i]); - parport_unregister_port(this_port[i]); - release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia)); + for (i = 0; i < MAX_MFC; i++) { + if (!this_port[i]) + continue; + if (!this_port[i]->irq != PARPORT_IRQ_NONE) { + if (--use_cnt == 0) + free_irq(IRQ_AMIGA_PORTS, &pp_mfc3_ops); } + parport_proc_unregister(this_port[i]); + parport_unregister_port(this_port[i]); + release_mem_region(ZTWO_PADDR(this_port[i]->private_data), sizeof(struct pia)); + } } -#endif + +MODULE_AUTHOR("Joerg Dorchain "); +MODULE_DESCRIPTION("Parport Driver for Multiface 3 expansion cards Paralllel Port"); +MODULE_SUPPORTED_DEVICE("Multiface 3 Parallel Port"); + +module_init(parport_mfc3_init) +module_exit(parport_mfc3_exit) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c --- v2.4.0-test11/linux/drivers/parport/parport_pc.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/parport/parport_pc.c Mon Dec 11 13:43:59 2000 @@ -778,9 +778,13 @@ /* Switch to forward mode if necessary. */ if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { /* Event 47: Set nInit high. */ - parport_frob_control (port, PARPORT_CONTROL_INIT, 0); + parport_frob_control (port, + PARPORT_CONTROL_INIT + | PARPORT_CONTROL_AUTOFD, + PARPORT_CONTROL_INIT + | PARPORT_CONTROL_AUTOFD); - /* Event 40: PError goes high. */ + /* Event 49: PError goes high. */ r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, PARPORT_STATUS_PAPEROUT); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.4.0-test11/linux/drivers/pci/pci.c Sun Nov 19 18:44:12 2000 +++ linux/drivers/pci/pci.c Mon Dec 11 13:46:26 2000 @@ -300,18 +300,25 @@ pci_announce_device(struct pci_driver *drv, struct pci_dev *dev) { const struct pci_device_id *id; + int ret = 0; if (drv->id_table) { id = pci_match_device(drv->id_table, dev); - if (!id) - return 0; + if (!id) { + ret = 0; + goto out; + } } else id = NULL; + + dev_probe_lock(); if (drv->probe(dev, id) >= 0) { dev->driver = drv; - return 1; + ret = 1; } - return 0; + dev_probe_unlock(); +out: + return ret; } int @@ -354,16 +361,16 @@ run_sbin_hotplug(struct pci_dev *pdev, int insert) { int i; - char *argv[3], *envp[7]; - char id[20], sub_id[24], bus_id[64], class_id[20]; + char *argv[3], *envp[8]; + char id[20], sub_id[24], bus_id[24], class_id[20]; if (!hotplug_path[0]) return; - sprintf(class_id, "PCI_CLASS=%X", pdev->class >> 8); - sprintf(id, "PCI_ID=%X/%X", pdev->vendor, pdev->device); - sprintf(sub_id, "PCI_SUBSYS_ID=%X/%X", pdev->subsystem_vendor, pdev->subsystem_device); - sprintf(bus_id, "PCI_BUS_ID=%s", pdev->slot_name); + sprintf(class_id, "PCI_CLASS=%04X", pdev->class); + sprintf(id, "PCI_ID=%04X:%04X", pdev->vendor, pdev->device); + sprintf(sub_id, "PCI_SUBSYS_ID=%04X:%04X", pdev->subsystem_vendor, pdev->subsystem_device); + sprintf(bus_id, "PCI_SLOT_NAME=%s", pdev->slot_name); i = 0; argv[i++] = hotplug_path; @@ -376,6 +383,7 @@ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; /* other stuff we want to pass to /sbin/hotplug */ + envp[i++] = class_id; envp[i++] = id; envp[i++] = sub_id; envp[i++] = bus_id; @@ -539,15 +547,9 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) { unsigned int pos, reg, next; - u32 l, sz, tmp; - u16 cmd; + u32 l, sz; struct resource *res; - /* Disable IO and memory while we fiddle */ - pci_read_config_word(dev, PCI_COMMAND, &cmd); - tmp = cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_write_config_word(dev, PCI_COMMAND, tmp); - for(pos=0; posresource[pos]; @@ -578,10 +580,11 @@ res->start |= ((unsigned long) l) << 32; res->end = res->start + sz; pci_write_config_dword(dev, reg+4, ~0); - pci_read_config_dword(dev, reg+4, &tmp); + pci_read_config_dword(dev, reg+4, &sz); pci_write_config_dword(dev, reg+4, l); - if (l) - res->end = res->start + (((unsigned long) ~l) << 32); + if (~sz) + res->end = res->start + 0xffffffff + + (((unsigned long) ~sz) << 32); #else if (l) { printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", dev->slot_name); @@ -610,7 +613,6 @@ } res->name = dev->name; } - pci_write_config_word(dev, PCI_COMMAND, cmd); } void __init pci_read_bridge_bases(struct pci_bus *child) @@ -710,6 +712,7 @@ static struct pci_bus * __init pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr) { struct pci_bus *child; + int i; /* * Allocate a new bus, and inherit stuff from the parent.. @@ -731,6 +734,10 @@ child->primary = parent->secondary; child->subordinate = 0xff; + /* Set up default resource pointers.. */ + for (i = 0; i < 4; i++) + child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; + return child; } @@ -755,7 +762,7 @@ pci_read_config_dword(dev, PCI_PRIMARY_BUS, &buses); DBG("Scanning behind PCI bridge %s, config %06x, pass %d\n", dev->slot_name, buses & 0xffffff, pass); - if ((buses & 0xffffff) && !pcibios_assign_all_busses()) { + if ((buses & 0xffff00) && !pcibios_assign_all_busses()) { /* * Bus already configured by firmware, process it in the first * pass and just note the configuration. @@ -771,9 +778,8 @@ unsigned int cmax = pci_do_scan_bus(child); if (cmax > max) max = cmax; } else { - int i; - for (i = 0; i < 4; i++) - child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; + unsigned int cmax = child->subordinate; + if (cmax > max) max = cmax; } } else { /* @@ -786,6 +792,7 @@ pci_read_config_word(dev, PCI_COMMAND, &cr); pci_write_config_word(dev, PCI_COMMAND, 0x0000); pci_write_config_word(dev, PCI_STATUS, 0xffff); + child = pci_add_new_bus(bus, dev, ++max); buses = (buses & 0xff000000) | ((unsigned int)(child->primary) << 0) @@ -799,15 +806,12 @@ /* Now we can scan all subordinate buses... */ max = pci_do_scan_bus(child); } else { - int i; /* * For CardBus bridges, we leave 4 bus numbers * as cards with a PCI-to-PCI bridge can be * inserted later. */ max += 3; - for (i = 0; i < 4; i++) - child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i]; } /* * Set the subordinate bus number to its real value. @@ -1086,6 +1090,9 @@ return 0; } + +/* take care to suspend/resume bridges only once */ + static int pci_pm_suspend_bus(struct pci_bus *bus) { struct list_head *list; @@ -1097,9 +1104,6 @@ /* Walk the device children list */ list_for_each(list, &bus->devices) pci_pm_suspend_device(pci_dev_b(list)); - - /* Suspend the bus controller.. */ - pci_pm_suspend_device(bus->self); return 0; } @@ -1107,8 +1111,6 @@ { struct list_head *list; - pci_pm_resume_device(bus->self); - /* Walk the device children list */ list_for_each(list, &bus->devices) pci_pm_resume_device(pci_dev_b(list)); @@ -1122,18 +1124,26 @@ static int pci_pm_suspend(void) { struct list_head *list; + struct pci_bus *bus; - list_for_each(list, &pci_root_buses) - pci_pm_suspend_bus(pci_bus_b(list)); + list_for_each(list, &pci_root_buses) { + bus = pci_bus_b(list); + pci_pm_suspend_bus(bus); + pci_pm_suspend_device(bus->self); + } return 0; } static int pci_pm_resume(void) { struct list_head *list; + struct pci_bus *bus; - list_for_each(list, &pci_root_buses) - pci_pm_resume_bus(pci_bus_b(list)); + list_for_each(list, &pci_root_buses) { + bus = pci_bus_b(list); + pci_pm_resume_device(bus->self); + pci_pm_resume_bus(bus); + } return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/pci/setup-bus.c linux/drivers/pci/setup-bus.c --- v2.4.0-test11/linux/drivers/pci/setup-bus.c Tue Jan 11 14:22:31 2000 +++ linux/drivers/pci/setup-bus.c Mon Dec 11 13:46:26 2000 @@ -9,148 +9,241 @@ * Support routines for initializing a PCI subsystem. */ +/* + * Nov 2000, Ivan Kokshaysky + * PCI-PCI bridges cleanup, sorted resource allocation + */ + #include #include #include #include #include #include +#include -#define DEBUG_CONFIG 0 +#define DEBUG_CONFIG 1 #if DEBUG_CONFIG # define DBGC(args) printk args #else # define DBGC(args) #endif - #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define ROUND_DOWN(x, a) ((x) & ~((a) - 1)) +static int __init +pbus_assign_resources_sorted(struct pci_bus *bus, + struct pbus_set_ranges_data *ranges) +{ + struct list_head *ln; + struct resource *res; + struct resource_list head_io, head_mem, *list, *tmp; + unsigned long io_reserved = 0, mem_reserved = 0; + int idx, found_vga = 0; + + head_io.next = head_mem.next = NULL; + for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { + struct pci_dev *dev = pci_dev_b(ln); + u16 class = dev->class >> 8; + u16 cmd; + + /* First, disable the device to avoid side + effects of possibly overlapping I/O and + memory ranges. + Leave VGA enabled - for obvious reason. :-) + Same with all sorts of bridges - they may + have VGA behind them. */ + if (class == PCI_CLASS_DISPLAY_VGA + || class == PCI_CLASS_NOT_DEFINED_VGA) + found_vga = 1; + else if (class >> 8 != PCI_BASE_CLASS_BRIDGE) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY + | PCI_COMMAND_MASTER); + pci_write_config_word(dev, PCI_COMMAND, cmd); + } + + /* Reserve some resources for CardBus. + Are these values reasonable? */ + if (class == PCI_CLASS_BRIDGE_CARDBUS) { + io_reserved += 8*1024; + mem_reserved += 32*1024*1024; + continue; + } + + pdev_sort_resources(dev, &head_io, IORESOURCE_IO); + pdev_sort_resources(dev, &head_mem, IORESOURCE_MEM); + } + + for (list = head_io.next; list;) { + res = list->res; + idx = res - &list->dev->resource[0]; + if (pci_assign_resource(list->dev, idx) == 0 + && ranges->io_end < res->end) + ranges->io_end = res->end; + tmp = list; + list = list->next; + kfree(tmp); + } + for (list = head_mem.next; list;) { + res = list->res; + idx = res - &list->dev->resource[0]; + if (pci_assign_resource(list->dev, idx) == 0 + && ranges->mem_end < res->end) + ranges->mem_end = res->end; + tmp = list; + list = list->next; + kfree(tmp); + } + + ranges->io_end += io_reserved; + ranges->mem_end += mem_reserved; + + /* PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998) + requires that if there is no I/O ports or memory behind the + bridge, corresponding range must be turned off by writing base + value greater than limit to the bridge's base/limit registers. */ +#if 1 + /* But assuming that some hardware designed before 1998 might + not support this (very unlikely - at least all DEC bridges + are ok and I believe that was standard de-facto. -ink), we + must allow for at least one unit. */ + if (ranges->io_end == ranges->io_start) + ranges->io_end += 1; + if (ranges->mem_end == ranges->mem_start) + ranges->mem_end += 1; +#endif + ranges->io_end = ROUND_UP(ranges->io_end, 4*1024); + ranges->mem_end = ROUND_UP(ranges->mem_end, 1024*1024); + + return found_vga; +} + +/* Initialize bridges with base/limit values we have collected */ static void __init -pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer) +pci_setup_bridge(struct pci_bus *bus) +{ + struct pbus_set_ranges_data ranges; + struct pci_dev *bridge = bus->self; + u32 l; + + if (!bridge || (bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI) + return; + ranges.io_start = bus->resource[0]->start; + ranges.io_end = bus->resource[0]->end; + ranges.mem_start = bus->resource[1]->start; + ranges.mem_end = bus->resource[1]->end; + pcibios_fixup_pbus_ranges(bus, &ranges); + + DBGC(("PCI: Bus %d, bridge: %s\n", bus->number, bridge->name)); + DBGC((" IO window: %04lx-%04lx\n", ranges.io_start, ranges.io_end)); + DBGC((" MEM window: %08lx-%08lx\n", ranges.mem_start, ranges.mem_end)); + + /* Set up the top and bottom of the PCI I/O segment for this bus. */ + pci_read_config_dword(bridge, PCI_IO_BASE, &l); + l &= 0xffff0000; + l |= (ranges.io_start >> 8) & 0x00f0; + l |= ranges.io_end & 0xf000; + pci_write_config_dword(bridge, PCI_IO_BASE, l); + + /* Clear upper 16 bits of I/O base/limit. */ + pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0); + + /* Clear out the upper 32 bits of PREF base/limit. */ + pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); + pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); + + /* Set up the top and bottom of the PCI Memory segment + for this bus. */ + l = (ranges.mem_start >> 16) & 0xfff0; + l |= ranges.mem_end & 0xfff00000; + pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); + + /* Set up PREF base/limit. */ + l = (bus->resource[2]->start >> 16) & 0xfff0; + l |= bus->resource[2]->end & 0xfff00000; + pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); + + /* Check if we have VGA behind the bridge. + Enable ISA in either case. */ + l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04; + pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l); +} + +static void __init +pbus_assign_resources(struct pci_bus *bus, struct pbus_set_ranges_data *ranges) { - struct pbus_set_ranges_data inner; - struct pci_dev *dev; struct list_head *ln; + int found_vga = pbus_assign_resources_sorted(bus, ranges); - inner.found_vga = 0; - inner.mem_start = inner.io_start = ~0UL; - inner.mem_end = inner.io_end = 0; + if (!ranges->found_vga && found_vga) { + struct pci_bus *b; - /* Collect information about how our direct children are layed out. */ - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - int i; - dev = pci_dev_b(ln); - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = &dev->resource[i]; - if (res->flags & IORESOURCE_IO) { - if (res->start < inner.io_start) - inner.io_start = res->start; - if (res->end > inner.io_end) - inner.io_end = res->end; - } else if (res->flags & IORESOURCE_MEM) { - if (res->start < inner.mem_start) - inner.mem_start = res->start; - if (res->end > inner.mem_end) - inner.mem_end = res->end; - } + ranges->found_vga = 1; + /* Propogate presence of the VGA to upstream bridges */ + for (b = bus; b->parent; b = b->parent) { +#if 0 + /* ? Do we actually need to enable PF memory? */ + b->resource[2]->start = 0; +#endif + b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA; } - if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA) - inner.found_vga = 1; } + for (ln=bus->children.next; ln != &bus->children; ln=ln->next) { + struct pci_bus *b = pci_bus_b(ln); + + b->resource[0]->start = ranges->io_start = ranges->io_end; + b->resource[1]->start = ranges->mem_start = ranges->mem_end; + + pbus_assign_resources(b, ranges); + + b->resource[0]->end = ranges->io_end - 1; + b->resource[1]->end = ranges->mem_end - 1; - /* And for all of the sub-busses. */ - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pbus_set_ranges(pci_bus_b(ln), &inner); - - /* Align the values. */ - inner.io_start = ROUND_DOWN(inner.io_start, 4*1024); - inner.io_end = ROUND_UP(inner.io_end, 4*1024); - - inner.mem_start = ROUND_DOWN(inner.mem_start, 1*1024*1024); - inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024); - - pcibios_fixup_pbus_ranges(bus, &inner); - - /* Configure the bridge, if possible. */ - if (bus->self) { - struct pci_dev *bridge = bus->self; - u32 l; - - /* Set up the top and bottom of the PCI I/O segment - for this bus. */ - pci_read_config_dword(bridge, PCI_IO_BASE, &l); - l &= 0xffff0000; - l |= (inner.io_start >> 8) & 0x00f0; - l |= (inner.io_end - 1) & 0xf000; - pci_write_config_dword(bridge, PCI_IO_BASE, l); - - /* - * Clear out the upper 16 bits of IO base/limit. - * Clear out the upper 32 bits of PREF base/limit. - */ - pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0); - pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0); - pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0); - - /* Set up the top and bottom of the PCI Memory segment - for this bus. */ - l = (inner.mem_start & 0xfff00000) >> 16; - l |= (inner.mem_end - 1) & 0xfff00000; - pci_write_config_dword(bridge, PCI_MEMORY_BASE, l); - - /* - * Turn off downstream PF memory address range, unless - * there is a VGA behind this bridge, in which case, we - * enable the PREFETCH range to include BIOS ROM at C0000. - * - * NOTE: this is a bit of a hack, done with PREFETCH for - * simplicity, rather than having to add it into the above - * non-PREFETCH range, which could then be bigger than we want. - * We might assume that we could relocate the BIOS ROM, but - * that would depend on having it found by those who need it - * (the DEC BIOS emulator would find it, but I do not know - * about the Xservers). So, we do it this way for now... ;-) - */ - l = (inner.found_vga) ? 0 : 0x0000ffff; - pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l); - - /* - * Tell bridge that there is an ISA bus in the system, - * and (possibly) a VGA as well. - */ - l = (inner.found_vga) ? 0x0c : 0x04; - pci_write_config_byte(bridge, PCI_BRIDGE_CONTROL, l); - - /* - * Clear status bits, - * turn on I/O enable (for downstream I/O), - * turn on memory enable (for downstream memory), - * turn on master enable (for upstream memory and I/O). - */ - pci_write_config_dword(bridge, PCI_COMMAND, 0xffff0007); - } - - if (outer) { - outer->found_vga |= inner.found_vga; - if (inner.io_start < outer->io_start) - outer->io_start = inner.io_start; - if (inner.io_end > outer->io_end) - outer->io_end = inner.io_end; - if (inner.mem_start < outer->mem_start) - outer->mem_start = inner.mem_start; - if (inner.mem_end > outer->mem_end) - outer->mem_end = inner.mem_end; + pci_setup_bridge(b); } } void __init -pci_set_bus_ranges(void) +pci_assign_unassigned_resources(void) { + struct pbus_set_ranges_data ranges; struct list_head *ln; + struct pci_dev *dev; + + for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) { + struct pci_bus *b = pci_bus_b(ln); - for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) - pbus_set_ranges(pci_bus_b(ln), NULL); + ranges.io_start = b->resource[0]->start + PCIBIOS_MIN_IO; + ranges.mem_start = b->resource[1]->start + PCIBIOS_MIN_MEM; + ranges.io_end = ranges.io_start; + ranges.mem_end = ranges.mem_start; + ranges.found_vga = 0; + pbus_assign_resources(b, &ranges); + } + pci_for_each_dev(dev) { + pdev_enable_device(dev); + } +} + +/* Check whether the bridge supports I/O forwarding. + If not, its I/O base/limit register must be + read-only and read as 0. */ +unsigned long __init +pci_bridge_check_io(struct pci_dev *bridge) +{ + u16 io; + + pci_read_config_word(bridge, PCI_IO_BASE, &io); + if (!io) { + pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0); + pci_read_config_word(bridge, PCI_IO_BASE, &io); + pci_write_config_word(bridge, PCI_IO_BASE, 0x0); + } + if (io) + return IORESOURCE_IO; + printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n", + bridge->name); + return 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c --- v2.4.0-test11/linux/drivers/pci/setup-res.c Thu Aug 10 15:19:40 2000 +++ linux/drivers/pci/setup-res.c Mon Dec 11 13:46:26 2000 @@ -11,15 +11,21 @@ /* fixed for multiple pci buses, 1999 Andrea Arcangeli */ +/* + * Nov 2000, Ivan Kokshaysky + * Resource sorting + */ + #include #include #include #include #include #include +#include -#define DEBUG_CONFIG 0 +#define DEBUG_CONFIG 1 #if DEBUG_CONFIG # define DBGC(args) printk args #else @@ -114,19 +120,67 @@ } } - DBGC((" got res[%lx:%lx] for resource %d\n", res->start, res->end, i)); + DBGC((" got res[%lx:%lx] for resource %d of %s\n", res->start, + res->end, i, dev->name)); return 0; } -void -pdev_assign_unassigned_resources(struct pci_dev *dev) +/* Sort resources of a given type by alignment */ +void __init +pdev_sort_resources(struct pci_dev *dev, + struct resource_list *head, u32 type_mask) +{ + int i; + + for (i = 0; i < PCI_NUM_RESOURCES; i++) { + struct resource *r; + struct resource_list *list, *tmp; + unsigned long r_size; + + /* PCI-PCI bridges may have I/O ports or + memory on the primary bus */ + if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI && + i >= PCI_BRIDGE_RESOURCES) + continue; + + r = &dev->resource[i]; + r_size = r->end - r->start; + + if (!(r->flags & type_mask) || r->parent) + continue; + if (!r_size) { + printk(KERN_WARNING "PCI: Ignore bogus resource %d " + "[%lx:%lx] of %s\n", + i, r->start, r->end, dev->name); + continue; + } + for (list = head; ; list = list->next) { + unsigned long size = 0; + struct resource_list *ln = list->next; + + if (ln) + size = ln->res->end - ln->res->start; + if (r_size > size) { + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + tmp->next = ln; + tmp->res = r; + tmp->dev = dev; + list->next = tmp; + break; + } + } + } +} + +void __init +pdev_enable_device(struct pci_dev *dev) { u32 reg; u16 cmd; int i; - DBGC(("PCI assign unassigned: (%s)\n", dev->name)); + DBGC(("PCI enable device: (%s)\n", dev->name)); pci_read_config_word(dev, PCI_COMMAND, &cmd); @@ -137,13 +191,6 @@ cmd |= PCI_COMMAND_IO; else if (res->flags & IORESOURCE_MEM) cmd |= PCI_COMMAND_MEMORY; - - /* If it is already assigned or the resource does - not exist, there is nothing to do. */ - if (res->parent != NULL || res->flags == 0) - continue; - - pci_assign_resource(dev, i); } /* Special case, disable the ROM. Several devices act funny @@ -171,24 +218,12 @@ it, the bit will go into the bucket. */ cmd |= PCI_COMMAND_MASTER; + /* Set the cache line and default latency (32). */ + pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, + (32 << 8) | (L1_CACHE_BYTES / sizeof(u32))); + /* Enable the appropriate bits in the PCI command register. */ pci_write_config_word(dev, PCI_COMMAND, cmd); DBGC((" cmd reg 0x%x\n", cmd)); - - /* If this is a PCI bridge, set the cache line correctly. */ - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, - (L1_CACHE_BYTES / sizeof(u32))); - } -} - -void __init -pci_assign_unassigned_resources(void) -{ - struct pci_dev *dev; - - pci_for_each_dev(dev) { - pdev_assign_unassigned_resources(dev); - } } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c --- v2.4.0-test11/linux/drivers/pnp/isapnp.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/pnp/isapnp.c Mon Dec 11 12:38:58 2000 @@ -270,17 +270,16 @@ { int rdp = isapnp_rdp; while (rdp <= 0x3ff) { - if (!check_region(rdp, 1)) { - isapnp_rdp = rdp; - return 0; - } - rdp += RDP_STEP; /* * We cannot use NE2000 probe spaces for ISAPnP or we * will lock up machines. */ - if(rdp >= 0x280 && rdp <= 0x380) - continue; + if ((rdp < 0x280 || rdp > 0x380) && !check_region(rdp, 1)) + { + isapnp_rdp = rdp; + return 0; + } + rdp += RDP_STEP; } return -1; } @@ -748,6 +747,25 @@ } /* + * Parse card name for ISA PnP device. + */ + +static void __init +isapnp_parse_name(char *name, unsigned int name_max, unsigned short *size) +{ + if (name[0] == '\0') { + unsigned short size1 = *size >= name_max ? (name_max - 1) : *size; + isapnp_peek(name, size1); + name[size1] = '\0'; + *size -= size1; + + /* clean whitespace from end of string */ + while (size1 > 0 && name[--size1] == ' ') + name[size1] = '\0'; + } +} + +/* * Parse resource map for logical device. */ @@ -844,12 +862,7 @@ size = 0; break; case _LTAG_ANSISTR: - if (dev->name[0] == '\0') { - unsigned short size1 = size > 47 ? 47 : size; - isapnp_peek(dev->name, size1); - dev->name[size1] = '\0'; - size -= size1; - } + isapnp_parse_name(dev->name, sizeof(dev->name), &size); break; case _LTAG_UNICODESTR: /* silently ignore */ @@ -915,12 +928,7 @@ case _STAG_VENDOR: break; case _LTAG_ANSISTR: - if (card->name[0] == '\0') { - unsigned short size1 = size > 47 ? 47 : size; - isapnp_peek(card->name, size1); - card->name[size1] = '\0'; - size -= size1; - } + isapnp_parse_name(card->name, sizeof(card->name), &size); break; case _LTAG_UNICODESTR: /* silently ignore */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/s390/net/ctc.c linux/drivers/s390/net/ctc.c --- v2.4.0-test11/linux/drivers/s390/net/ctc.c Fri May 12 11:41:44 2000 +++ linux/drivers/s390/net/ctc.c Mon Dec 11 12:39:45 2000 @@ -1313,7 +1313,7 @@ return -ENOMEM; } init_waitqueue_head(&privptr->channel[i].wait); - privptr->channel[i].tq.next = NULL; + INIT_LIST_HEAD(&privptr->channel[i].tq.list); privptr->channel[i].tq.sync = 0; privptr->channel[i].tq.routine = (void *)(void *)ctc_irq_bh; privptr->channel[i].tq.data = &privptr->channel[i]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sbus/audio/dmy.c linux/drivers/sbus/audio/dmy.c --- v2.4.0-test11/linux/drivers/sbus/audio/dmy.c Mon Dec 20 22:06:42 1999 +++ linux/drivers/sbus/audio/dmy.c Mon Dec 11 12:39:45 2000 @@ -547,7 +547,7 @@ dummy_chip->perchip_info.play.active = 1; /* fake an "interrupt" to deal with this block */ - dummy_chip->tqueue.next = NULL; + INIT_LIST_HEAD(&dummy_chip->tqueue.list); dummy_chip->tqueue.sync = 0; dummy_chip->tqueue.routine = dummy_output_done_task; dummy_chip->tqueue.data = drv; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c --- v2.4.0-test11/linux/drivers/sbus/char/aurora.c Sun Nov 19 18:44:12 2000 +++ linux/drivers/sbus/char/aurora.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: aurora.c,v 1.9 2000/11/08 05:33:03 davem Exp $ +/* $Id: aurora.c,v 1.10 2000/12/07 04:35:38 anton Exp $ * linux/drivers/sbus/char/aurora.c -- Aurora multiport driver * * Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro) @@ -666,9 +666,11 @@ 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))) - queue_task(&port->tqueue_hangup, - &tq_scheduler); + (port->flags & ASYNC_CALLOUT_NOHUP))) { + MOD_INC_USE_COUNT; + if (schedule_task(&port->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; + } } /* We don't have such things yet. My aurora board has DTR and RTS swapped, but that doesn't count in this driver. Let's hope @@ -2211,13 +2213,13 @@ printk("do_aurora_hangup: start\n"); #endif tty = port->tty; - if (tty == NULL) - return; - - tty_hangup(tty); + if (tty != NULL) { + tty_hangup(tty); /* FIXME: module removal race - AKPM */ #ifdef AURORA_DEBUG - printk("do_aurora_hangup: end\n"); + printk("do_aurora_hangup: end\n"); #endif + } + MOD_DEC_USE_COUNT; } static void aurora_hangup(struct tty_struct * tty) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- v2.4.0-test11/linux/drivers/sbus/char/sab82532.c Sun Nov 19 18:44:12 2000 +++ linux/drivers/sbus/char/sab82532.c Mon Dec 11 12:37:03 2000 @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.53 2000/11/15 07:28:09 davem Exp $ +/* $Id: sab82532.c,v 1.54 2000/12/07 04:35:39 anton Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -527,8 +527,9 @@ #ifdef SERIAL_DEBUG_OPEN printk("scheduling hangup..."); #endif - - queue_task(&info->tqueue_hangup, &tq_scheduler); + MOD_INC_USE_COUNT; + if (schedule_task(&info->tqueue_hangup) == 0) + MOD_DEC_USE_COUNT; } } @@ -676,10 +677,9 @@ struct tty_struct *tty; tty = info->tty; - if (!tty) - return; - - tty_hangup(tty); + if (tty) + tty_hangup(tty); + MOD_DEC_USE_COUNT; } static void @@ -2134,7 +2134,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.53 $"; + char *revision = "$Revision: 1.54 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile --- v2.4.0-test11/linux/drivers/scsi/Makefile Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/Makefile Mon Dec 11 13:59:19 2000 @@ -30,7 +30,7 @@ CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM -obj-$(CONFIG_SCSI) += scsi_mod.o scsi_syms.o +obj-$(CONFIG_SCSI) += scsi_mod.o obj-$(CONFIG_A4000T_SCSI) += amiga7xx.o 53c7xx.o obj-$(CONFIG_A4091_SCSI) += amiga7xx.o 53c7xx.o @@ -39,6 +39,7 @@ obj-$(CONFIG_A3000_SCSI) += a3000.o wd33c93.o obj-$(CONFIG_A2091_SCSI) += a2091.o wd33c93.o obj-$(CONFIG_GVP11_SCSI) += gvp11.o wd33c93.o +obj-$(CONFIG_MVME147_SCSI) += mvme147.o wd33c93.o obj-$(CONFIG_CYBERSTORM_SCSI) += NCR53C9x.o cyberstorm.o obj-$(CONFIG_CYBERSTORMII_SCSI) += NCR53C9x.o cyberstormII.o obj-$(CONFIG_BLZ2060_SCSI) += NCR53C9x.o blz2060.o @@ -122,6 +123,7 @@ scsicam.o scsi_proc.o scsi_error.o \ scsi_obsolete.o scsi_queue.o scsi_lib.o \ scsi_merge.o scsi_dma.o scsi_scan.o \ + scsi_syms.o sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o initio-objs := ini9100u.o i91uscsi.o diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/a2091.c linux/drivers/scsi/a2091.c --- v2.4.0-test11/linux/drivers/scsi/a2091.c Sun Nov 19 18:44:13 2000 +++ linux/drivers/scsi/a2091.c Mon Nov 27 17:57:34 2000 @@ -231,8 +231,6 @@ #define HOSTS_C -#include "a2091.h" - static Scsi_Host_Template driver_template = A2091_SCSI; #include "scsi_module.c" diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/a2091.h linux/drivers/scsi/a2091.h --- v2.4.0-test11/linux/drivers/scsi/a2091.h Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/a2091.h Mon Nov 27 17:57:34 2000 @@ -1,4 +1,5 @@ #ifndef A2091_H +#define A2091_H /* $Id: a2091.h,v 1.4 1997/01/19 23:07:09 davem Exp $ * diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/a3000.c linux/drivers/scsi/a3000.c --- v2.4.0-test11/linux/drivers/scsi/a3000.c Sun Nov 19 18:44:13 2000 +++ linux/drivers/scsi/a3000.c Mon Nov 27 17:57:34 2000 @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -100,7 +101,9 @@ cache_push (addr, cmd->SCp.this_residual); /* start DMA */ + mb(); /* make sure setup is completed */ DMA(a3000_host)->ST_DMA = 1; + mb(); /* make sure DMA has started before next IO */ /* return success */ return 0; @@ -116,12 +119,15 @@ cntr |= CNTR_DDIR; DMA(instance)->CNTR = cntr; + mb(); /* make sure CNTR is updated before next IO */ /* flush if we were reading */ if (HDATA(instance)->dma_dir) { DMA(instance)->FLUSH = 1; + mb(); /* don't allow prefetch */ while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) - ; + barrier(); + mb(); /* no IO until FLUSH is done */ } /* clear a possible interrupt */ @@ -132,9 +138,11 @@ /* stop DMA */ DMA(instance)->SP_DMA = 1; + mb(); /* make sure DMA is stopped before next IO */ /* restore the CONTROL bits (minus the direction flag) */ DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; + mb(); /* make sure CNTR is updated before next IO */ /* copy from a bounce buffer, if necessary */ if (status && HDATA(instance)->dma_bounce_buffer) { @@ -170,13 +178,17 @@ if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) return 0; + if (!request_mem_region(0xDD0000, 256, "wd33c93")) + return -EBUSY; tpnt->proc_name = "A3000"; tpnt->proc_info = &wd33c93_proc_info; a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); - if(a3000_host == NULL) + if (a3000_host == NULL) { + release_mem_region(0xDD0000, 256); return 0; + } a3000_host->base = ZTWO_VADDR(0xDD0000); a3000_host->irq = IRQ_AMIGA_PORTS; DMA(a3000_host)->DAWR = DAWR_A3000; @@ -192,9 +204,7 @@ #define HOSTS_C -#include "a3000.h" - -static Scsi_Host_Template driver_template = A3000_SCSI; +static Scsi_Host_Template driver_template = _A3000_SCSI; #include "scsi_module.c" @@ -203,6 +213,7 @@ #ifdef MODULE wd33c93_release(); DMA(instance)->CNTR = 0; + release_mem_region(0xDD0000, 256); free_irq(IRQ_AMIGA_PORTS, a3000_intr); #endif return 1; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/a3000.h linux/drivers/scsi/a3000.h --- v2.4.0-test11/linux/drivers/scsi/a3000.h Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/a3000.h Mon Nov 27 17:57:34 2000 @@ -1,4 +1,5 @@ #ifndef A3000_H +#define A3000_H /* $Id: a3000.h,v 1.4 1997/01/19 23:07:10 davem Exp $ * @@ -29,7 +30,7 @@ #define CAN_QUEUE 16 #endif -#define A3000_SCSI { proc_name: "A3000", \ +#define _A3000_SCSI { proc_name: "A3000", \ proc_info: NULL, \ name: "Amiga 3000 built-in SCSI", \ detect: a3000_detect, \ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v2.4.0-test11/linux/drivers/scsi/aha1542.c Sun Nov 19 18:44:13 2000 +++ linux/drivers/scsi/aha1542.c Thu Nov 23 09:33:36 2000 @@ -1416,6 +1416,7 @@ SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; if (SCtmp->host_scribble) { scsi_free(SCtmp->host_scribble, 512); + SCtmp->host_scribble = NULL; } HOSTDATA(SCpnt->host)->SCint[i] = NULL; HOSTDATA(SCpnt->host)->mb[i].status = 0; @@ -1478,6 +1479,7 @@ } if (SCtmp->host_scribble) { scsi_free(SCtmp->host_scribble, 512); + SCtmp->host_scribble = NULL; } HOSTDATA(SCpnt->host)->SCint[i] = NULL; HOSTDATA(SCpnt->host)->mb[i].status = 0; @@ -1546,6 +1548,7 @@ } if (SCtmp->host_scribble) { scsi_free(SCtmp->host_scribble, 512); + SCtmp->host_scribble = NULL; } HOSTDATA(SCpnt->host)->SCint[i] = NULL; HOSTDATA(SCpnt->host)->mb[i].status = 0; @@ -1681,8 +1684,10 @@ Scsi_Cmnd *SCtmp; SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; SCtmp->result = DID_RESET << 16; - if (SCtmp->host_scribble) + if (SCtmp->host_scribble) { scsi_free(SCtmp->host_scribble, 512); + SCtmp->host_scribble = NULL; + } printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target); SCtmp->scsi_done(SCpnt); @@ -1725,8 +1730,10 @@ Scsi_Cmnd *SCtmp; SCtmp = HOSTDATA(SCpnt->host)->SCint[i]; SCtmp->result = DID_RESET << 16; - if (SCtmp->host_scribble) + if (SCtmp->host_scribble) { scsi_free(SCtmp->host_scribble, 512); + SCtmp->host_scribble = NULL; + } printk(KERN_WARNING "Sending DID_RESET for target %d\n", SCpnt->target); SCtmp->scsi_done(SCpnt); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c --- v2.4.0-test11/linux/drivers/scsi/atari_scsi.c Sun Nov 19 18:44:13 2000 +++ linux/drivers/scsi/atari_scsi.c Mon Nov 27 17:57:34 2000 @@ -656,7 +656,7 @@ */ if (MACH_IS_ATARI && ATARIHW_PRESENT(ST_SCSI) && !ATARIHW_PRESENT(EXTD_DMA) && m68k_num_memory > 1) { - atari_dma_buffer = atari_stram_alloc( STRAM_BUFFER_SIZE, NULL, "SCSI" ); + atari_dma_buffer = atari_stram_alloc(STRAM_BUFFER_SIZE, "SCSI"); if (!atari_dma_buffer) { printk( KERN_ERR "atari_scsi_detect: can't allocate ST-RAM " "double buffer\n" ); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c --- v2.4.0-test11/linux/drivers/scsi/eata.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/eata.c Mon Nov 27 17:49:00 2000 @@ -1,12 +1,26 @@ /* * eata.c - Low-level driver for EATA/DMA SCSI host adapters. * + * 22 Nov 2000 Rev. 6.02 for linux 2.4.0-test11 + * + Return code checked when calling pci_enable_device. + * + Removed old scsi error handling support. + * + The obsolete boot option flag eh:n is silently ignored. + * + Removed error messages while a disk drive is powered up at + * boot time. + * + Improved boot messages: all tagged capable device are + * indicated as "tagged" or "soft-tagged" : + * - "soft-tagged" means that the driver is trying to do its + * own tagging (i.e. the tc:y option is in effect); + * - "tagged" means that the device supports tagged commands, + * but the driver lets the HBA be responsible for tagging + * support. + * * 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18 * + Updated to the new __setup interface for boot command line options. * + When loaded as a module, accepts the new parameter boot_options * which value is a string with the same format of the kernel boot * command line options. A valid example is: - * modprobe eata 'boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\"' + * modprobe eata boot_options=\"0x7410,0x230,lc:y,tc:n,mq:4\" * * 9 Sep 1999 Rev. 5.10 for linux 2.2.12 and 2.3.17 * + 64bit cleanup for Linux/Alpha platform support @@ -196,7 +210,9 @@ * This driver is based on the CAM (Common Access Method Committee) * EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol. * - * Copyright (C) 1994-1999 Dario Ballabio (dario@milano.europe.dg.com) + * Copyright (C) 1994-2000 Dario Ballabio (ballabio_dario@emc.com) + * + * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that redistributions of source @@ -288,8 +304,6 @@ * After the optional list of detection probes, other possible command line * options are: * - * eh:y use new scsi code; - * eh:n use old scsi code; * et:y force use of extended translation (255 heads, 63 sectors); * et:n use disk geometry detected by scsicam_bios_param; * rs:y reverse scan order while detecting PCI boards; @@ -306,13 +320,13 @@ * * The default value is: "eata=lc:n,tc:n,mq:16,tm:0,et:n,rs:n". * An example using the list of detection probes could be: - * "eata=0x7410,0x230,lc:y,tc:n,mq:4,eh:n,et:n". + * "eata=0x7410,0x230,lc:y,tc:n,mq:4,et:n". * * When loading as a module, parameters can be specified as well. * The above example would be (use 1 in place of y and 0 in place of n): * * modprobe eata io_port=0x7410,0x230 linked_comm=1 tagged_comm=0 \ - * max_queue_depth=4 tag_mode=0 use_new_eh_code=0 \ + * max_queue_depth=4 tag_mode=0 \ * ext_tran=0 rev_scan=1 * * ---------------------------------------------------------------------------- @@ -369,7 +383,10 @@ #include +#ifndef LinuxVersionCode #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#endif + #define MAX_INT_PARAM 10 #if defined(MODULE) @@ -382,7 +399,6 @@ MODULE_PARM(link_statistics, "i"); MODULE_PARM(max_queue_depth, "i"); MODULE_PARM(tag_mode, "i"); -MODULE_PARM(use_new_eh_code, "i"); MODULE_PARM(ext_tran, "i"); MODULE_PARM(rev_scan, "i"); MODULE_AUTHOR("Dario Ballabio"); @@ -410,12 +426,7 @@ #include #include #include - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) -#include -#else #include -#endif #define SPIN_FLAGS unsigned long spin_flags; #define SPIN_LOCK spin_lock_irq(&io_request_lock); @@ -501,10 +512,6 @@ #define ASOK 0x00 #define ASST 0x01 -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) -#define ARRAY_SIZE(x) (sizeof (x) / sizeof((x)[0])) -#endif - #define YESNO(a) ((a) ? 'y' : 'n') #define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) @@ -693,7 +700,6 @@ static int tag_mode = TAG_MIXED; static int ext_tran = FALSE; static int rev_scan = TRUE; -static int use_new_eh_code = TRUE; static char *boot_options; #if defined(CONFIG_SCSI_EATA_TAGGED_QUEUE) @@ -761,9 +767,9 @@ } if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue) - tag_suffix = ", tagged"; + tag_suffix = ", soft-tagged"; else if (dev->tagged_supported && TLDEV(dev->type)) - tag_suffix = ", untagged"; + tag_suffix = ", tagged"; printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", BN(j), host->host_no, dev->channel, dev->id, dev->lun, @@ -831,7 +837,7 @@ addr = pci_resource_start (dev, 0); - pci_enable_device (dev); /* XXX handle error */ + if (pci_enable_device (dev)) continue; #if defined(DEBUG_PCI_DETECT) printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n", @@ -1122,13 +1128,11 @@ } else tag_type = 'n'; - sh[j]->hostt->use_new_eh_code = use_new_eh_code; - if (j == 0) { - printk("EATA/DMA 2.0x: Copyright (C) 1994-1999 Dario Ballabio.\n"); - printk("%s config options -> tc:%c, lc:%c, mq:%d, eh:%c, rs:%c, et:%c.\n", + printk("EATA/DMA 2.0x: Copyright (C) 1994-2000 Dario Ballabio.\n"); + printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c.\n", driver_name, tag_type, YESNO(linked_comm), max_queue_depth, - YESNO(use_new_eh_code), YESNO(rev_scan), YESNO(ext_tran)); + YESNO(rev_scan), YESNO(ext_tran)); } printk("%s: 2.0%c, %s 0x%03lx, IRQ %u, %s, SG %d, MB %d.\n", @@ -1191,7 +1195,6 @@ else if (!strncmp(cur, "tm:", 3)) tag_mode = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; - else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; else if (!strncmp(cur, "rs:", 3)) rev_scan = val; @@ -1439,79 +1442,6 @@ return rtn; } -static inline int do_old_abort(Scsi_Cmnd *SCarg) { - unsigned int i, j; - - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - - if (SCarg->host_scribble == NULL || - (SCarg->serial_number_at_timeout && - (SCarg->serial_number != SCarg->serial_number_at_timeout))) { - printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - return SCSI_ABORT_NOT_RUNNING; - } - - i = *(unsigned int *)SCarg->host_scribble; - printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", - BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - - if (i >= sh[j]->can_queue) - panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: abort, timeout error.\n", BN(j)); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == FREE) { - printk("%s: abort, mbox %d is free.\n", BN(j), i); - return SCSI_ABORT_NOT_RUNNING; - } - - if (HD(j)->cp_stat[i] == IN_USE) { - printk("%s: abort, mbox %d is in use.\n", BN(j), i); - - if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); - - if (inb(sh[j]->io_port + REG_AUX_STATUS) & IRQ_ASSERTED) - printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); - - return SCSI_ABORT_SNOOZE; - } - - if (HD(j)->cp_stat[i] == IN_RESET) { - printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == LOCKED) { - printk("%s: abort, mbox %d is locked.\n", BN(j), i); - return SCSI_ABORT_NOT_RUNNING; - } - - if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { - SCarg->result = DID_ABORT << 16; - SCarg->host_scribble = NULL; - HD(j)->cp_stat[i] = FREE; - printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - BN(j), i, SCarg->pid); - SCarg->scsi_done(SCarg); - return SCSI_ABORT_SUCCESS; - } - - panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); -} - -int eata2x_old_abort(Scsi_Cmnd *SCarg) { - int rtn; - - rtn = do_old_abort(SCarg); - return rtn; -} - static inline int do_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; @@ -1589,151 +1519,6 @@ return do_abort(SCarg); } -static inline int do_old_reset(Scsi_Cmnd *SCarg) { - unsigned int i, j, time, k, c, limit = 0; - int arg_done = FALSE; - Scsi_Cmnd *SCpnt; - - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - - if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); - - if (SCarg->serial_number_at_timeout && - (SCarg->serial_number != SCarg->serial_number_at_timeout)) { - printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid); - return SCSI_RESET_NOT_RUNNING; - } - - if (HD(j)->in_reset) { - printk("%s: reset, exit, already in reset.\n", BN(j)); - return SCSI_RESET_ERROR; - } - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: reset, exit, timeout error.\n", BN(j)); - return SCSI_RESET_ERROR; - } - - HD(j)->retries = 0; - - for (c = 0; c <= sh[j]->max_channel; c++) - for (k = 0; k < sh[j]->max_id; k++) { - HD(j)->target_redo[k][c] = TRUE; - HD(j)->target_to[k][c] = 0; - } - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == FREE) continue; - - if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } - - if (!(SCpnt = HD(j)->cp[i].SCpnt)) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { - HD(j)->cp_stat[i] = ABORTING; - printk("%s: reset, mbox %d aborting, pid %ld.\n", - BN(j), i, SCpnt->pid); - } - - else { - HD(j)->cp_stat[i] = IN_RESET; - printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->pid); - } - - if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); - - if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); - - if (SCpnt == SCarg) arg_done = TRUE; - } - - if (do_dma(sh[j]->io_port, 0, RESET_PIO)) { - printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - return SCSI_RESET_ERROR; - } - - printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); - -#if defined(DEBUG_RESET) - do_trace = TRUE; -#endif - - HD(j)->in_reset = TRUE; - SPIN_UNLOCK - time = jiffies; - while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); - SPIN_LOCK - printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == IN_RESET) { - SCpnt = HD(j)->cp[i].SCpnt; - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox is still waiting for its interrupt */ - HD(j)->cp_stat[i] = LOCKED; - - printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); - } - - else if (HD(j)->cp_stat[i] == ABORTING) { - SCpnt = HD(j)->cp[i].SCpnt; - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox was never queued to the adapter */ - HD(j)->cp_stat[i] = FREE; - - printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); - } - - else - - /* Any other mailbox has already been set free by interrupt */ - continue; - - SCpnt->scsi_done(SCpnt); - } - - HD(j)->in_reset = FALSE; - do_trace = FALSE; - - if (arg_done) { - printk("%s: reset, exit, success.\n", BN(j)); - return SCSI_RESET_SUCCESS; - } - else { - printk("%s: reset, exit, wakeup.\n", BN(j)); - return SCSI_RESET_PUNT; - } -} - -int eata2x_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { - int rtn; - - rtn = do_old_reset(SCarg); - return rtn; -} - static inline int do_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; @@ -1983,7 +1768,7 @@ if (link_statistics) { if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; - batchcount++; readycount += n_ready, seeknosort += seek / 1024; + batchcount++; readycount += n_ready; seeknosort += seek / 1024; if (input_only) inputcount++; if (overlap) { ovlcount++; seeksorted += iseek / 1024; } else seeksorted += (iseek + maxsec - minsec) / 1024; @@ -2169,7 +1954,9 @@ if (tstatus == GOOD) HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; - if (spp->target_status && SCpnt->device->type == TYPE_DISK) + if (spp->target_status && SCpnt->device->type == TYPE_DISK && + (!(tstatus == CHECK_CONDITION && HD(j)->iocount <= 1000 && + (SCpnt->sense_buffer[2] & 0xf) == NOT_READY))) printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ "target_status 0x%x, sense key 0x%x.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, @@ -2297,13 +2084,5 @@ #include "scsi_module.c" #ifndef MODULE - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) -void eata2x_setup(char *str, int *ints) { - internal_setup(str, ints); -} -#else __setup("eata=", option_setup); -#endif - #endif /* end MODULE */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h --- v2.4.0-test11/linux/drivers/scsi/eata.h Fri Sep 8 12:54:35 2000 +++ linux/drivers/scsi/eata.h Mon Nov 27 17:49:00 2000 @@ -5,28 +5,23 @@ #define _EATA_H #include -#include int eata2x_detect(Scsi_Host_Template *); int eata2x_release(struct Scsi_Host *); int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int eata2x_abort(Scsi_Cmnd *); -int eata2x_old_abort(Scsi_Cmnd *); int eata2x_reset(Scsi_Cmnd *); -int eata2x_old_reset(Scsi_Cmnd *, unsigned int); int eata2x_biosparam(Disk *, kdev_t, int *); -#define EATA_VERSION "5.11.00" - -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#define EATA_VERSION "6.02.00" #define EATA { \ name: "EATA/DMA 2.0x rev. " EATA_VERSION " ", \ detect: eata2x_detect, \ release: eata2x_release, \ queuecommand: eata2x_queuecommand, \ - abort: eata2x_old_abort, \ - reset: eata2x_old_reset, \ + abort: NULL, \ + reset: NULL, \ eh_abort_handler: eata2x_abort, \ eh_device_reset_handler: NULL, \ eh_bus_reset_handler: NULL, \ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c --- v2.4.0-test11/linux/drivers/scsi/gvp11.c Sun Nov 19 18:44:13 2000 +++ linux/drivers/scsi/gvp11.c Mon Nov 27 17:57:34 2000 @@ -346,7 +346,7 @@ continue; release: - release_mem_region(ZTWO_PADDR(instance->base), 256); + release_mem_region(address, 256); } return num_gvp11; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c --- v2.4.0-test11/linux/drivers/scsi/ide-scsi.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/ide-scsi.c Mon Nov 27 17:57:34 2000 @@ -840,7 +840,7 @@ failed = 0; while ((drive = ide_scan_devices (media[i], idescsi_driver.name, &idescsi_driver, failed)) != NULL) if (idescsi_cleanup (drive)) { - printk ("%s: cleanup_module() called while still busy\n", drive->name); + printk ("%s: exit_idescsi_module() called while still busy\n", drive->name); failed++; } } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c --- v2.4.0-test11/linux/drivers/scsi/imm.c Sun Nov 19 18:44:13 2000 +++ linux/drivers/scsi/imm.c Mon Dec 11 13:43:20 2000 @@ -51,7 +51,7 @@ mode: IMM_AUTODETECT, \ host: -1, \ cur_cmd: NULL, \ - imm_tq: {0, 0, imm_interrupt, NULL}, \ + imm_tq: { routine: imm_interrupt }, \ jstart: 0, \ failed: 0, \ dp: 0, \ @@ -122,7 +122,14 @@ struct Scsi_Host *hreg; int ports; int i, nhosts, try_again; - struct parport *pb = parport_enumerate(); + struct parport *pb; + + /* + * unlock to allow the lowlevel parport driver to probe + * the irqs + */ + spin_unlock_irq(&io_request_lock); + pb = parport_enumerate(); printk("imm: Version %s\n", IMM_VERSION); nhosts = 0; @@ -130,6 +137,7 @@ if (!pb) { printk("imm: parport reports no devices.\n"); + spin_lock_irq(&io_request_lock); return 0; } retry_entry: @@ -154,6 +162,7 @@ printk(KERN_ERR "imm%d: failed to claim parport because a " "pardevice is owning the port for too longtime!\n", i); + spin_lock_irq(&io_request_lock); return 0; } } @@ -208,12 +217,16 @@ nhosts++; } if (nhosts == 0) { - if (try_again == 1) + if (try_again == 1) { + spin_lock_irq(&io_request_lock); return 0; + } try_again = 1; goto retry_entry; - } else + } else { + spin_lock_irq (&io_request_lock); return 1; /* return number of hosts detected */ + } } /* This is to give the imm driver a way to modify the timings (and other diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/imm.h linux/drivers/scsi/imm.h --- v2.4.0-test11/linux/drivers/scsi/imm.h Fri Sep 8 12:54:35 2000 +++ linux/drivers/scsi/imm.h Mon Dec 11 13:43:20 2000 @@ -10,7 +10,7 @@ #ifndef _IMM_H #define _IMM_H -#define IMM_VERSION "2.04 (for Linux 2.4.0)" +#define IMM_VERSION "2.05 (for Linux 2.4.0)" /* * 10 Apr 1998 (Good Friday) - Received EN144302 by email from Iomega. @@ -60,6 +60,9 @@ * added CONFIG_SCSI_IZIP_SLOW_CTR option * [2.03] * Fix kernel panic on scsi timeout. 20Aug00 [2.04] + * + * Avoid io_request_lock problems. + * John Cavan 16Nov00 [2.05] */ /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/ips.h linux/drivers/scsi/ips.h --- v2.4.0-test11/linux/drivers/scsi/ips.h Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/ips.h Mon Dec 11 13:38:29 2000 @@ -929,7 +929,7 @@ char *ioctl_data; /* IOCTL data area */ u32 ioctl_datasize; /* IOCTL data size */ u32 cmd_in_progress; /* Current command in progress*/ - u32 flags; /* HA flags */ + long flags; /* HA flags */ u8 waitflag; /* are we waiting for cmd */ u8 active; u16 reset_count; /* number of resets */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.4.0-test11/linux/drivers/scsi/megaraid.c Sun Nov 19 18:44:14 2000 +++ linux/drivers/scsi/megaraid.c Wed Dec 6 12:06:18 2000 @@ -194,9 +194,6 @@ *================================================================ */ -#define queue_task_irq(a,b) queue_task(a,b) -#define queue_task_irq_off(a,b) queue_task(a,b) - #define MAX_SERBUF 160 #define COM_BASE 0x2f8 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/mvme147.c linux/drivers/scsi/mvme147.c --- v2.4.0-test11/linux/drivers/scsi/mvme147.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mvme147.c Mon Nov 27 17:57:34 2000 @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "scsi.h" +#include "hosts.h" +#include "wd33c93.h" +#include "mvme147.h" + +#include + +#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata)) + +static struct Scsi_Host *mvme147_host = NULL; + +static void mvme147_intr (int irq, void *dummy, struct pt_regs *fp) +{ + if (irq == MVME147_IRQ_SCSI_PORT) + wd33c93_intr (mvme147_host); + else + m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ +} + +static int dma_setup (Scsi_Cmnd *cmd, int dir_in) +{ + unsigned char flags = 0x01; + unsigned long addr = virt_to_bus(cmd->SCp.ptr); + + /* setup dma direction */ + if (!dir_in) + flags |= 0x04; + + /* remember direction */ + HDATA(mvme147_host)->dma_dir = dir_in; + + if (dir_in) + /* invalidate any cache */ + cache_clear (addr, cmd->SCp.this_residual); + else + /* push any dirty cache */ + cache_push (addr, cmd->SCp.this_residual); + + /* start DMA */ + m147_pcc->dma_bcr = cmd->SCp.this_residual | (1<<24); + m147_pcc->dma_dadr = addr; + m147_pcc->dma_cntrl = flags; + + /* return success */ + return 0; +} + +static void dma_stop (struct Scsi_Host *instance, Scsi_Cmnd *SCpnt, + int status) +{ + m147_pcc->dma_cntrl = 0; +} + +int mvme147_detect(Scsi_Host_Template *tpnt) +{ + static unsigned char called = 0; + + if (!MACH_IS_MVME147 || called) + return 0; + called++; + + tpnt->proc_name = "MVME147"; + tpnt->proc_info = &wd33c93_proc_info; + + mvme147_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); + mvme147_host->base = 0xfffe4000; + mvme147_host->irq = MVME147_IRQ_SCSI_PORT; + wd33c93_init(mvme147_host, (wd33c93_regs *)0xfffe4000, + dma_setup, dma_stop, WD33C93_FS_8_10); + + request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, "MVME147 SCSI PORT", mvme147_intr); + request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, "MVME147 SCSI DMA", mvme147_intr); +#if 0 /* Disabled; causes problems booting */ + m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ + udelay(100); + m147_pcc->scsi_interrupt = 0x00; /* Negate SCSI bus reset */ + udelay(2000); + m147_pcc->scsi_interrupt = 0x40; /* Clear bus reset interrupt */ +#endif + m147_pcc->scsi_interrupt = 0x09; /* Enable interrupt */ + + m147_pcc->dma_cntrl = 0x00; /* ensure DMA is stopped */ + m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ + + return 1; +} + +#define HOSTS_C + +#include "mvme147.h" + +static Scsi_Host_Template driver_template = MVME147_SCSI; + +#include "scsi_module.c" + +int mvme147_release(struct Scsi_Host *instance) +{ +#ifdef MODULE + /* XXX Make sure DMA is stopped! */ + wd33c93_release(); + free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); + free_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr); +#endif + return 1; +} diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/mvme147.h linux/drivers/scsi/mvme147.h --- v2.4.0-test11/linux/drivers/scsi/mvme147.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/scsi/mvme147.h Mon Nov 27 17:57:34 2000 @@ -0,0 +1,50 @@ +#ifndef MVME147_H + +/* $Id: mvme147.h,v 1.4 1997/01/19 23:07:10 davem Exp $ + * + * Header file for the MVME147 built-in SCSI controller for Linux + * + * Written and (C) 1993, Hamish Macdonald, see mvme147.c for more info + * + */ + +#include + +int mvme147_detect(Scsi_Host_Template *); +int mvme147_release(struct Scsi_Host *); +const char *wd33c93_info(void); +int wd33c93_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); +int wd33c93_abort(Scsi_Cmnd *); +int wd33c93_reset(Scsi_Cmnd *, unsigned int); + +#ifndef NULL +#define NULL 0 +#endif + +#ifndef CMD_PER_LUN +#define CMD_PER_LUN 2 +#endif + +#ifndef CAN_QUEUE +#define CAN_QUEUE 16 +#endif + +#ifdef HOSTS_C + +#define MVME147_SCSI {proc_name: "MVME147", \ + proc_info: NULL, \ + name: "MVME147 built-in SCSI", \ + detect: mvme147_detect, \ + release: mvme147_release, \ + queuecommand: wd33c93_queuecommand, \ + abort: wd33c93_abort, \ + reset: wd33c93_reset, \ + can_queue: CAN_QUEUE, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: CMD_PER_LUN, \ + use_clustering: ENABLE_CLUSTERING } + +#endif /* else def HOSTS_C */ + +#endif /* MVME147_H */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c --- v2.4.0-test11/linux/drivers/scsi/ppa.c Sun Nov 19 18:44:14 2000 +++ linux/drivers/scsi/ppa.c Mon Dec 11 13:43:20 2000 @@ -41,7 +41,7 @@ mode: PPA_AUTODETECT, \ host: -1, \ cur_cmd: NULL, \ - ppa_tq: {0, 0, ppa_interrupt, NULL}, \ + ppa_tq: { routine: ppa_interrupt }, \ jstart: 0, \ failed: 0, \ p_busy: 0 \ @@ -111,7 +111,14 @@ struct Scsi_Host *hreg; int ports; int i, nhosts, try_again; - struct parport *pb = parport_enumerate(); + struct parport *pb; + + /* + * unlock to allow the lowlevel parport driver to probe + * the irqs + */ + spin_unlock_irq(&io_request_lock); + pb = parport_enumerate(); printk("ppa: Version %s\n", PPA_VERSION); nhosts = 0; @@ -119,6 +126,7 @@ if (!pb) { printk("ppa: parport reports no devices.\n"); + spin_lock_irq(&io_request_lock); return 0; } retry_entry: @@ -143,6 +151,7 @@ printk(KERN_ERR "ppa%d: failed to claim parport because a " "pardevice is owning the port for too longtime!\n", i); + spin_lock_irq(&io_request_lock); return 0; } } @@ -212,11 +221,14 @@ printk(" cable is marked with \"AutoDetect\", this is what has\n"); printk(" happened.\n"); return 0; + spin_lock_irq(&io_request_lock); } try_again = 1; goto retry_entry; - } else + } else { + spin_lock_irq(&io_request_lock); return 1; /* return number of hosts detected */ + } } /* This is to give the ppa driver a way to modify the timings (and other diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/ppa.h linux/drivers/scsi/ppa.h --- v2.4.0-test11/linux/drivers/scsi/ppa.h Fri Sep 8 12:54:35 2000 +++ linux/drivers/scsi/ppa.h Mon Dec 11 13:43:20 2000 @@ -10,7 +10,7 @@ #ifndef _PPA_H #define _PPA_H -#define PPA_VERSION "2.05 (for Linux 2.2.x)" +#define PPA_VERSION "2.06 (for Linux 2.2.x)" /* * this driver has been hacked by Matteo Frigo (athena@theory.lcs.mit.edu) @@ -58,6 +58,9 @@ * Tim Waugh * [2.04] * Fix kernel panic on scsi timeout, 2000-08-18 [2.05] + * + * Avoid io_request_lock problems. + * John Cavan [2.06] */ /* ------ END OF USER CONFIGURABLE PARAMETERS ----- */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/qla1280.c linux/drivers/scsi/qla1280.c --- v2.4.0-test11/linux/drivers/scsi/qla1280.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/qla1280.c Wed Dec 6 12:06:18 2000 @@ -312,7 +312,7 @@ STATIC int qla1280_return_status( sts_entry_t *sts, Scsi_Cmnd *cp); STATIC void qla1280_removeq(scsi_lu_t *q, srb_t *sp); STATIC void qla1280_mem_free(scsi_qla_host_t *ha); -void qla1280_do_dpc(void *p); +static void qla1280_do_dpc(void *p); #ifdef QLA1280_UNUSED static void qla1280_set_flags(char * s); #endif @@ -1082,7 +1082,8 @@ { CMD_RESULT(cmd) = (int) (DID_BUS_BUSY << 16); qla1280_done_q_put(sp, &ha->done_q_first, &ha->done_q_last); - queue_task(&ha->run_qla_bh,&tq_scheduler); + + schedule_task(&ha->run_qla_bh); ha->flags.dpc_sched = TRUE; DRIVER_UNLOCK return(0); @@ -1580,7 +1581,7 @@ ha->run_qla_bh.routine = qla1280_do_dpc; COMTRACE('P') - queue_task_irq(&ha->run_qla_bh,&tq_scheduler); + schedule_task(&ha->run_qla_bh); ha->flags.dpc_sched = TRUE; } clear_bit(QLA1280_IN_ISR_BIT, (int *)&ha->flags); @@ -1604,7 +1605,7 @@ * "host->can_queue". This can cause a panic if we were in our interrupt * code . **************************************************************************/ -void qla1280_do_dpc(void *p) +static void qla1280_do_dpc(void *p) { scsi_qla_host_t *ha = (scsi_qla_host_t *) p; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,95) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c --- v2.4.0-test11/linux/drivers/scsi/u14-34f.c Sun Oct 8 10:50:26 2000 +++ linux/drivers/scsi/u14-34f.c Mon Nov 27 17:49:00 2000 @@ -1,12 +1,20 @@ /* * u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters. * + * 01 Nov 2000 Rev. 6.02 for linux 2.4.0-test11 + * + Removed old scsi error handling support. + * + The obsolete boot option flag eh:n is silently ignored. + * + Removed error messages while a disk drive is powered up at + * boot time. + * + Improved boot messages: all tagged capable device are + * indicated as "tagged". + * * 16 Sep 1999 Rev. 5.11 for linux 2.2.12 and 2.3.18 * + Updated to the new __setup interface for boot command line options. * + When loaded as a module, accepts the new parameter boot_options * which value is a string with the same format of the kernel boot * command line options. A valid example is: - * modprobe u14-34f 'boot_options=\"0x230,0x340,lc:y,mq:4\"' + * modprobe u14-34f boot_options=\"0x230,0x340,lc:y,mq:4\" * * 22 Jul 1999 Rev. 5.00 for linux 2.2.10 and 2.3.11 * + Removed pre-2.2 source code compatibility. @@ -169,7 +177,9 @@ * * Multiple U14F and/or U34F host adapters are supported. * - * Copyright (C) 1994-1999 Dario Ballabio (dario@milano.europe.dg.com) + * Copyright (C) 1994-2000 Dario Ballabio (ballabio_dario@emc.com) + * + * Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that redistributions of source @@ -261,8 +271,6 @@ * After the optional list of detection probes, other possible command line * options are: * - * eh:y use new scsi code; - * eh:n use old scsi code; * et:y use disk geometry returned by scsicam_bios_param; * et:n use disk geometry jumpered on the board; * lc:y enables linked commands; @@ -273,13 +281,13 @@ * * The default value is: "u14-34f=lc:n,of:n,mq:8,et:n". * An example using the list of detection probes could be: - * "u14-34f=0x230,0x340,lc:y,of:n,mq:4,eh:n,et:n". + * "u14-34f=0x230,0x340,lc:y,of:n,mq:4,et:n". * * When loading as a module, parameters can be specified as well. * The above example would be (use 1 in place of y and 0 in place of n): * * modprobe u14-34f io_port=0x230,0x340 linked_comm=1 have_old_firmware=0 \ - * max_queue_depth=4 use_new_eh_code=0 ext_tran=0 + * max_queue_depth=4 ext_tran=0 * * ---------------------------------------------------------------------------- * In this implementation, linked commands are designed to work with any DISK @@ -322,7 +330,10 @@ #include +#ifndef LinuxVersionCode #define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) +#endif + #define MAX_INT_PARAM 10 #if defined(MODULE) @@ -334,7 +345,6 @@ MODULE_PARM(have_old_firmware, "i"); MODULE_PARM(link_statistics, "i"); MODULE_PARM(max_queue_depth, "i"); -MODULE_PARM(use_new_eh_code, "i"); MODULE_PARM(ext_tran, "i"); MODULE_AUTHOR("Dario Ballabio"); @@ -360,12 +370,7 @@ #include #include #include - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) -#include -#else #include -#endif #define SPIN_FLAGS unsigned long spin_flags; #define SPIN_LOCK spin_lock_irq(&io_request_lock); @@ -450,10 +455,6 @@ #define ASOK 0x00 #define ASST 0x91 -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) -#define ARRAY_SIZE(x) (sizeof (x) / sizeof((x)[0])) -#endif - #define YESNO(a) ((a) ? 'y' : 'n') #define TLDEV(type) ((type) == TYPE_DISK || (type) == TYPE_ROM) @@ -554,10 +555,9 @@ static void flush_dev(Scsi_Device *, unsigned long, unsigned int, unsigned int); static int do_trace = FALSE; static int setup_done = FALSE; -static int link_statistics = 0; +static int link_statistics; static int ext_tran = FALSE; -static int use_new_eh_code = TRUE; -static char *boot_options = NULL; +static char *boot_options; #if defined(HAVE_OLD_UX4F_FIRMWARE) static int have_old_firmware = TRUE; @@ -619,9 +619,9 @@ } if (dev->tagged_supported && TLDEV(dev->type) && dev->tagged_queue) - tag_suffix = ", tagged"; + tag_suffix = ", soft-tagged"; else if (dev->tagged_supported && TLDEV(dev->type)) - tag_suffix = ", untagged"; + tag_suffix = ", tagged"; printk("%s: scsi%d, channel %d, id %d, lun %d, cmds/lun %d%s%s.\n", BN(j), host->host_no, dev->channel, dev->id, dev->lun, @@ -766,8 +766,6 @@ if (have_old_firmware) tpnt->use_clustering = DISABLE_CLUSTERING; - tpnt->use_new_eh_code = use_new_eh_code; - sh[j] = scsi_register(tpnt, sizeof(struct hostdata)); if (sh[j] == NULL) { @@ -875,10 +873,10 @@ if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN; if (j == 0) { - printk("UltraStor 14F/34F: Copyright (C) 1994-1999 Dario Ballabio.\n"); - printk("%s config options -> of:%c, lc:%c, mq:%d, eh:%c, et:%c.\n", + printk("UltraStor 14F/34F: Copyright (C) 1994-2000 Dario Ballabio.\n"); + printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n", driver_name, YESNO(have_old_firmware), YESNO(linked_comm), - max_queue_depth, YESNO(use_new_eh_code), YESNO(ext_tran)); + max_queue_depth, YESNO(ext_tran)); } printk("%s: %s 0x%03lx, BIOS 0x%05x, IRQ %u, %s, SG %d, MB %d.\n", @@ -921,7 +919,6 @@ else if (!strncmp(cur, "of:", 3)) have_old_firmware = val; else if (!strncmp(cur, "mq:", 3)) max_queue_depth = val; else if (!strncmp(cur, "ls:", 3)) link_statistics = val; - else if (!strncmp(cur, "eh:", 3)) use_new_eh_code = val; else if (!strncmp(cur, "et:", 3)) ext_tran = val; if ((cur = strchr(cur, ','))) ++cur; @@ -1112,79 +1109,6 @@ return rtn; } -static inline int do_old_abort(Scsi_Cmnd *SCarg) { - unsigned int i, j; - - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - - if (SCarg->host_scribble == NULL || - (SCarg->serial_number_at_timeout && - (SCarg->serial_number != SCarg->serial_number_at_timeout))) { - printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - return SCSI_ABORT_NOT_RUNNING; - } - - i = *(unsigned int *)SCarg->host_scribble; - printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", - BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - - if (i >= sh[j]->can_queue) - panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: abort, timeout error.\n", BN(j)); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == FREE) { - printk("%s: abort, mbox %d is free.\n", BN(j), i); - return SCSI_ABORT_NOT_RUNNING; - } - - if (HD(j)->cp_stat[i] == IN_USE) { - printk("%s: abort, mbox %d is in use.\n", BN(j), i); - - if (SCarg != HD(j)->cp[i].SCpnt) - panic("%s: abort, mbox %d, SCarg %p, cp SCpnt %p.\n", - BN(j), i, SCarg, HD(j)->cp[i].SCpnt); - - if (inb(sh[j]->io_port + REG_SYS_INTR) & IRQ_ASSERTED) - printk("%s: abort, mbox %d, interrupt pending.\n", BN(j), i); - - return SCSI_ABORT_SNOOZE; - } - - if (HD(j)->cp_stat[i] == IN_RESET) { - printk("%s: abort, mbox %d is in reset.\n", BN(j), i); - return SCSI_ABORT_ERROR; - } - - if (HD(j)->cp_stat[i] == LOCKED) { - printk("%s: abort, mbox %d is locked.\n", BN(j), i); - return SCSI_ABORT_NOT_RUNNING; - } - - if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { - SCarg->result = DID_ABORT << 16; - SCarg->host_scribble = NULL; - HD(j)->cp_stat[i] = FREE; - printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - BN(j), i, SCarg->pid); - SCarg->scsi_done(SCarg); - return SCSI_ABORT_SUCCESS; - } - - panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i); -} - -int u14_34f_old_abort(Scsi_Cmnd *SCarg) { - int rtn; - - rtn = do_old_abort(SCarg); - return rtn; -} - static inline int do_abort(Scsi_Cmnd *SCarg) { unsigned int i, j; @@ -1262,152 +1186,6 @@ return do_abort(SCarg); } -static inline int do_old_reset(Scsi_Cmnd *SCarg) { - unsigned int i, j, time, k, c, limit = 0; - int arg_done = FALSE; - Scsi_Cmnd *SCpnt; - - j = ((struct hostdata *) SCarg->host->hostdata)->board_number; - printk("%s: reset, enter, target %d.%d:%d, pid %ld.\n", - BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid); - - if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); - - if (SCarg->serial_number_at_timeout && - (SCarg->serial_number != SCarg->serial_number_at_timeout)) { - printk("%s: reset, pid %ld, reset not running.\n", BN(j), SCarg->pid); - return SCSI_RESET_NOT_RUNNING; - } - - if (HD(j)->in_reset) { - printk("%s: reset, exit, already in reset.\n", BN(j)); - return SCSI_RESET_ERROR; - } - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: reset, exit, timeout error.\n", BN(j)); - return SCSI_RESET_ERROR; - } - - HD(j)->retries = 0; - - for (c = 0; c <= sh[j]->max_channel; c++) - for (k = 0; k < sh[j]->max_id; k++) { - HD(j)->target_redo[k][c] = TRUE; - HD(j)->target_to[k][c] = 0; - } - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == FREE) continue; - - if (HD(j)->cp_stat[i] == LOCKED) { - HD(j)->cp_stat[i] = FREE; - printk("%s: reset, locked mbox %d forced free.\n", BN(j), i); - continue; - } - - if (!(SCpnt = HD(j)->cp[i].SCpnt)) - panic("%s: reset, mbox %d, SCpnt == NULL.\n", BN(j), i); - - if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { - HD(j)->cp_stat[i] = ABORTING; - printk("%s: reset, mbox %d aborting, pid %ld.\n", - BN(j), i, SCpnt->pid); - } - - else { - HD(j)->cp_stat[i] = IN_RESET; - printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->pid); - } - - if (SCpnt->host_scribble == NULL) - panic("%s: reset, mbox %d, garbled SCpnt.\n", BN(j), i); - - if (*(unsigned int *)SCpnt->host_scribble != i) - panic("%s: reset, mbox %d, index mismatch.\n", BN(j), i); - - if (SCpnt->scsi_done == NULL) - panic("%s: reset, mbox %d, SCpnt->scsi_done == NULL.\n", BN(j), i); - - if (SCpnt == SCarg) arg_done = TRUE; - } - - if (wait_on_busy(sh[j]->io_port, MAXLOOP)) { - printk("%s: reset, cannot reset, timeout error.\n", BN(j)); - return SCSI_RESET_ERROR; - } - - outb(CMD_RESET, sh[j]->io_port + REG_LCL_INTR); - printk("%s: reset, board reset done, enabling interrupts.\n", BN(j)); - -#if defined(DEBUG_RESET) - do_trace = TRUE; -#endif - - HD(j)->in_reset = TRUE; - SPIN_UNLOCK - time = jiffies; - while ((jiffies - time) < (10 * HZ) && limit++ < 200000) udelay(100L); - SPIN_LOCK - printk("%s: reset, interrupts disabled, loops %d.\n", BN(j), limit); - - for (i = 0; i < sh[j]->can_queue; i++) { - - if (HD(j)->cp_stat[i] == IN_RESET) { - SCpnt = HD(j)->cp[i].SCpnt; - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox is still waiting for its interrupt */ - HD(j)->cp_stat[i] = LOCKED; - - printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); - } - - else if (HD(j)->cp_stat[i] == ABORTING) { - SCpnt = HD(j)->cp[i].SCpnt; - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; - - /* This mailbox was never queued to the adapter */ - HD(j)->cp_stat[i] = FREE; - - printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); - } - - else - - /* Any other mailbox has already been set free by interrupt */ - continue; - - SCpnt->scsi_done(SCpnt); - } - - HD(j)->in_reset = FALSE; - do_trace = FALSE; - - if (arg_done) { - printk("%s: reset, exit, success.\n", BN(j)); - return SCSI_RESET_SUCCESS; - } - else { - printk("%s: reset, exit, wakeup.\n", BN(j)); - return SCSI_RESET_PUNT; - } -} - -int u14_34f_old_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) { - int rtn; - - rtn = do_old_reset(SCarg); - return rtn; -} - static inline int do_reset(Scsi_Cmnd *SCarg) { unsigned int i, j, time, k, c, limit = 0; int arg_done = FALSE; @@ -1663,7 +1441,7 @@ if (link_statistics) { if (cursec > sl[0]) iseek = cursec - sl[0]; else iseek = sl[0] - cursec; - batchcount++; readycount += n_ready, seeknosort += seek / 1024; + batchcount++; readycount += n_ready; seeknosort += seek / 1024; if (input_only) inputcount++; if (overlap) { ovlcount++; seeksorted += iseek / 1024; } else seeksorted += (iseek + maxsec - minsec) / 1024; @@ -1837,7 +1615,9 @@ if (tstatus == GOOD) HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE; - if (spp->target_status && SCpnt->device->type == TYPE_DISK) + if (spp->target_status && SCpnt->device->type == TYPE_DISK && + (!(tstatus == CHECK_CONDITION && HD(j)->iocount <= 1000 && + (SCpnt->sense_buffer[2] & 0xf) == NOT_READY))) printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\ "target_status 0x%x, sense key 0x%x.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun, @@ -1969,13 +1749,5 @@ #include "scsi_module.c" #ifndef MODULE - -#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,18) -void u14_34f_setup(char *str, int *ints) { - internal_setup(str, ints); -} -#else __setup("u14-34f=", option_setup); -#endif - #endif /* end MODULE */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h --- v2.4.0-test11/linux/drivers/scsi/u14-34f.h Fri Sep 8 12:54:34 2000 +++ linux/drivers/scsi/u14-34f.h Mon Nov 27 17:49:00 2000 @@ -5,30 +5,23 @@ #define _U14_34F_H #include -#include int u14_34f_detect(Scsi_Host_Template *); int u14_34f_release(struct Scsi_Host *); int u14_34f_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); int u14_34f_abort(Scsi_Cmnd *); -int u14_34f_old_abort(Scsi_Cmnd *); int u14_34f_reset(Scsi_Cmnd *); -int u14_34f_old_reset(Scsi_Cmnd *, unsigned int); int u14_34f_biosparam(Disk *, kdev_t, int *); -#define U14_34F_VERSION "5.11.00" - -#ifndef LinuxVersionCode -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) -#endif +#define U14_34F_VERSION "6.02.00" #define ULTRASTOR_14_34F { \ name: "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \ detect: u14_34f_detect, \ release: u14_34f_release, \ queuecommand: u14_34f_queuecommand, \ - abort: u14_34f_old_abort, \ - reset: u14_34f_old_reset, \ + abort: NULL, \ + reset: NULL, \ eh_abort_handler: u14_34f_abort, \ eh_device_reset_handler: NULL, \ eh_bus_reset_handler: NULL, \ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/wd33c93.c linux/drivers/scsi/wd33c93.c --- v2.4.0-test11/linux/drivers/scsi/wd33c93.c Mon Mar 27 09:48:11 2000 +++ linux/drivers/scsi/wd33c93.c Tue Dec 5 12:43:48 2000 @@ -66,8 +66,14 @@ * this thing into as good a shape as possible, and I'm positive * there are lots of lurking bugs and "Stupid Places". * + * Updates: + * + * Added support for pre -A chips, which don't have advanced features + * and will generate CSR_RESEL rather than CSR_RESEL_AM. + * Richard Hirst August 2000 */ +#include #include #include @@ -1251,11 +1257,16 @@ case CSR_RESEL_AM: -DB(DB_INTR,printk("RESEL")) + case CSR_RESEL: +DB(DB_INTR,printk("RESEL%s", sr == CSR_RESEL_AM ? "_AM" : "")) - /* First we have to make sure this reselection didn't */ - /* happen during Arbitration/Selection of some other device. */ - /* If yes, put losing command back on top of input_Q. */ + /* Old chips (pre -A ???) don't have advanced features and will + * generate CSR_RESEL. In that case we have to extract the LUN the + * hard way (see below). + * First we have to make sure this reselection didn't + * happen during Arbitration/Selection of some other device. + * If yes, put losing command back on top of input_Q. + */ if (hostdata->level2 <= L2_NONE) { @@ -1295,10 +1306,53 @@ * not the right way to go, but...) */ - lun = read_wd33c93(regp, WD_DATA); - if (hostdata->level2 < L2_RESELECT) - write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK); - lun &= 7; + if (sr == CSR_RESEL_AM) { + lun = read_wd33c93(regp, WD_DATA); + if (hostdata->level2 < L2_RESELECT) + write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK); + lun &= 7; + } + else { + /* Old chip; wait for msgin phase to pick up the LUN. */ + for (lun = 255; lun; lun--) { + if ((asr = READ_AUX_STAT()) & ASR_INT) + break; + udelay(10); + } + if (!(asr & ASR_INT)) { + printk("wd33c93: Reselected without IDENTIFY\n"); + lun = 0; + } + else { + /* Verify this is a change to MSG_IN and read the message */ + sr = read_wd33c93(regp, WD_SCSI_STATUS); + if (sr == (CSR_ABORT | PHS_MESS_IN) || + sr == (CSR_UNEXP | PHS_MESS_IN) || + sr == (CSR_SRV_REQ | PHS_MESS_IN)) { + /* Got MSG_IN, grab target LUN */ + lun = read_1_byte(regp); + /* Now we expect a 'paused with ACK asserted' int.. */ + asr = READ_AUX_STAT(); + if (!(asr & ASR_INT)) { + udelay(10); + asr = READ_AUX_STAT(); + if (!(asr & ASR_INT)) + printk("wd33c93: No int after LUN on RESEL (%02x)\n", + asr); + } + sr = read_wd33c93(regp, WD_SCSI_STATUS); + if (sr != CSR_MSGIN) + printk("wd33c93: Not paused with ACK on RESEL (%02x)\n", + sr); + lun &= 7; + write_wd33c93_cmd(regp,WD_CMD_NEGATE_ACK); + } + else { + printk("wd33c93: Not MSG_IN on reselect (%02x)\n", sr); + lun = 0; + } + } + } /* Now we look for the command that's reconnecting. */ @@ -1372,6 +1426,9 @@ write_wd33c93(regp, WD_SYNCHRONOUS_TRANSFER, calc_sync_xfer(hostdata->default_sx_per/4,DEFAULT_SX_OFF)); write_wd33c93(regp, WD_COMMAND, WD_CMD_RESET); +#ifdef CONFIG_MVME147_SCSI + udelay(25); /* The old wd33c93 on MVME147 needs this, at least */ +#endif while (!(READ_AUX_STAT() & ASR_INT)) ; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/scsi/wd33c93.h linux/drivers/scsi/wd33c93.h --- v2.4.0-test11/linux/drivers/scsi/wd33c93.h Thu Feb 24 22:51:47 2000 +++ linux/drivers/scsi/wd33c93.h Mon Nov 27 17:57:34 2000 @@ -190,7 +190,9 @@ /* This is what the 3393 chip looks like to us */ typedef struct { volatile unsigned char SASR; +#if !defined(CONFIG_MVME147_SCSI) char pad; +#endif #ifdef CONFIG_SGI_IP22 char pad2,pad3; #endif @@ -341,5 +343,6 @@ void wd33c93_intr (struct Scsi_Host *instance); int wd33c93_proc_info(char *, char **, off_t, int, int, int); int wd33c93_reset (Scsi_Cmnd *, unsigned int); +void wd33c93_release(void); #endif /* WD33C93_H */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/Config.in linux/drivers/sound/Config.in --- v2.4.0-test11/linux/drivers/sound/Config.in Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/Config.in Wed Dec 6 11:43:05 2000 @@ -142,7 +142,10 @@ dep_tristate ' Yamaha FM synthesizer (YM3812/OPL-3) support' CONFIG_SOUND_YM3812 $CONFIG_SOUND_OSS dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS - dep_tristate ' Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI + dep_tristate ' Yamaha YMF7xx PCI audio (legacy mode)' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI + if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then + dep_tristate ' Yamaha YMF7xx PCI audio (native mode) (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS $CONFIG_PCI $CONFIG_EXPERIMENTAL + fi dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS dep_tristate ' Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/Makefile linux/drivers/sound/Makefile --- v2.4.0-test11/linux/drivers/sound/Makefile Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/Makefile Sun Dec 3 23:58:10 2000 @@ -67,6 +67,7 @@ obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o +obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o obj-$(CONFIG_SOUND_VWSND) += vwsnd.o diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c --- v2.4.0-test11/linux/drivers/sound/ac97_codec.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/ac97_codec.c Thu Dec 7 00:21:37 2000 @@ -134,7 +134,7 @@ {SOUND_MIXER_PCM, 0x4343}, {SOUND_MIXER_SPEAKER, 0x4343}, {SOUND_MIXER_LINE, 0x4343}, - {SOUND_MIXER_MIC, 0x4343}, + {SOUND_MIXER_MIC, 0x0000}, {SOUND_MIXER_CD, 0x4343}, {SOUND_MIXER_ALTPCM, 0x4343}, {SOUND_MIXER_IGAIN, 0x4343}, @@ -284,6 +284,10 @@ if (oss_channel == SOUND_MIXER_IGAIN) { right = (right * mh->scale) / 100; left = (left * mh->scale) / 100; + if (right >= mh->scale) + right = mh->scale-1; + if (left >= mh->scale) + left = mh->scale-1; } else { /* these may have 5 or 6 bit resolution */ if (oss_channel == SOUND_MIXER_VOLUME || @@ -294,27 +298,49 @@ right = ((100 - right) * scale) / 100; left = ((100 - left) * scale) / 100; - } + if (right >= scale) + right = scale-1; + if (left >= scale) + left = scale-1; + } val = (left << 8) | right; } } else if (oss_channel == SOUND_MIXER_BASS) { val = codec->codec_read(codec , mh->offset) & ~0x0f00; - val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00; + left = ((100 - left) * mh->scale) / 100; + if (left >= mh->scale) + left = mh->scale-1; + val |= (left << 8) & 0x0e00; } else if (oss_channel == SOUND_MIXER_TREBLE) { val = codec->codec_read(codec , mh->offset) & ~0x000f; - val |= (((100 - left) * mh->scale) / 100) & 0x000e; + left = ((100 - left) * mh->scale) / 100; + if (left >= mh->scale) + left = mh->scale-1; + val |= left & 0x000e; } else if(left == 0) { val = AC97_MUTE; } else if (oss_channel == SOUND_MIXER_SPEAKER) { - val = (((100 - left) * mh->scale) / 100) << 1; + left = ((100 - left) * mh->scale) / 100; + if (left >= mh->scale) + left = mh->scale-1; + val = left << 1; } else if (oss_channel == SOUND_MIXER_PHONEIN) { - val = (((100 - left) * mh->scale) / 100); + left = ((100 - left) * mh->scale) / 100; + if (left >= mh->scale) + left = mh->scale-1; + val = left; } else if (oss_channel == SOUND_MIXER_PHONEOUT) { scale = (1 << codec->bit_resolution); - val = (((100 - left) * scale) / 100); + left = ((100 - left) * scale) / 100; + if (left >= mh->scale) + left = mh->scale-1; + val = left; } else if (oss_channel == SOUND_MIXER_MIC) { val = codec->codec_read(codec , mh->offset) & ~0x801f; - val |= (((100 - left) * mh->scale) / 100); + left = ((100 - left) * mh->scale) / 100; + if (left >= mh->scale) + left = mh->scale-1; + val |= left; /* the low bit is optional in the tone sliders and masking it lets us avoid the 0xf 'bypass'.. */ } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/cs4281.c linux/drivers/sound/cs4281.c --- v2.4.0-test11/linux/drivers/sound/cs4281.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/cs4281.c Sun Dec 10 09:19:32 2000 @@ -258,7 +258,7 @@ #define SNDCTL_DSP_CS_GETDBGMASK _SIOWR('P', 52, int) #define SNDCTL_DSP_CS_SETDBGMASK _SIOWR('P', 53, int) -void printioctl(unsigned int x) +static void printioctl(unsigned int x) { unsigned int i; unsigned char vidx; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/cs461x_image.h linux/drivers/sound/cs461x_image.h --- v2.4.0-test11/linux/drivers/sound/cs461x_image.h Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/cs461x_image.h Wed Dec 6 16:13:33 2000 @@ -1,3459 +1,316 @@ -struct BA1struct BA1Struct __initdata = { -{{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }}, -{0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000163,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00200040,0x00008010,0x00000000, -0x00000000,0x80000001,0x00000001,0x00060000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00900080,0x00000173,0x00000000, -0x00000000,0x00000010,0x00800000,0x00900000, -0xf2c0000f,0x00000200,0x00000000,0x00010600, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000163,0x330300c2, -0x06000000,0x00000000,0x80008000,0x80008000, -0x3fc0000f,0x00000301,0x00010400,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00b00000,0x00d0806d,0x330480c3, -0x04800000,0x00000001,0x00800001,0x0000ffff, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x066a0600,0x06350070,0x0000929d,0x929d929d, -0x00000000,0x0000735a,0x00000600,0x00000000, -0x929d735a,0x8734abfe,0x00010000,0x735a735a, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000804f,0x000000c3, -0x05000000,0x00a00010,0x00000000,0x80008000, -0x00000000,0x00000000,0x00000700,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000080,0x00a00000,0x0000809a,0x000000c2, -0x07400000,0x00000000,0x80008000,0xffffffff, -0x00c80028,0x00005555,0x00000000,0x000107a0, -0x00c80028,0x000000c2,0x06800000,0x00000000, -0x06e00080,0x00300000,0x000080bb,0x000000c9, -0x07a00000,0x04000000,0x80008000,0xffffffff, -0x00c80028,0x00005555,0x00000000,0x00000780, -0x00c80028,0x000000c5,0xff800000,0x00000000, -0x00640080,0x00c00000,0x00008197,0x000000c9, -0x07800000,0x04000000,0x80008000,0xffffffff, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000805e,0x000000c1, -0x00000000,0x00800000,0x80008000,0x80008000, -0x00020000,0x0000ffff,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x929d0600,0x929d929d,0x929d929d,0x929d0000, -0x929d929d,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0x00100635,0x060b013f,0x00000004, -0x00000001,0x007a0002,0x00000000,0x066e0610, -0x0105929d,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0xa431ac75,0x0001735a,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051, -0x00000000,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0x929d929d,0x929d929d,0x929d929d, -0x929d929d,0x929d929d,0x00000000,0x06400136, -0x0000270f,0x00010000,0x007a0000,0x00000000, -0x068e0645,0x0105929d,0x929d929d,0x929d929d, -0x929d929d,0x929d929d,0xa431ac75,0x0001735a, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, -0x735a0100,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00010004, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00001705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00009705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00011705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00019705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00021705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00029705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00031705,0x00001400,0x000a411e,0x00001003, -0x00040730,0x00001002,0x000f619e,0x00001003, -0x00039705,0x00001400,0x000a411e,0x00001003, -0x000fe19e,0x00001003,0x0009c730,0x00001003, -0x0008e19c,0x00001003,0x000083c1,0x00093040, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00009705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00011705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00019705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00021705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00029705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00031705,0x00001400,0x000a211e,0x00001003, -0x00098730,0x00001002,0x000ee19e,0x00001003, -0x00039705,0x00001400,0x000a211e,0x00001003, -0x0000a730,0x00001008,0x000e2730,0x00001002, -0x0000a731,0x00001002,0x0000a731,0x00001002, -0x0000a731,0x00001002,0x0000a731,0x00001002, -0x0000a731,0x00001002,0x0000a731,0x00001002, -0x00000000,0x00000000,0x000f619c,0x00001003, -0x0007f801,0x000c0000,0x00000037,0x00001000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x000c0000,0x00000000,0x00000000, -0x0000373c,0x00001000,0x00000000,0x00000000, -0x000ee19c,0x00001003,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000273c,0x00001000, -0x00000033,0x00001000,0x000e679e,0x00001003, -0x00007705,0x00001400,0x000ac71e,0x00001003, -0x00087fc1,0x000c3be0,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0000a730,0x00001003, -0x00000033,0x00001000,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x000c0000, -0x00000032,0x00001000,0x0000273d,0x00001000, -0x0004a730,0x00001003,0x00000f41,0x00097140, -0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, -0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, -0x00000000,0x00000000,0x0001bf05,0x0003fc40, -0x00002725,0x000aa400,0x00013705,0x00093a00, -0x0000002e,0x0009d6c0,0x00038630,0x00001004, -0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000, -0x00000000,0x000c70e0,0x0007d182,0x0002c640, -0x00000630,0x00001004,0x000799b8,0x0002c6c0, -0x00031705,0x00092240,0x00039f05,0x000932c0, -0x0003520a,0x00000000,0x00040731,0x0000100b, -0x00010705,0x000b20c0,0x00000000,0x000eba44, -0x00032108,0x000c60c4,0x00065208,0x000c2917, -0x000406b0,0x00001007,0x00012f05,0x00036880, -0x0002818e,0x000c0000,0x0004410a,0x00000000, -0x00040630,0x00001007,0x00029705,0x000c0000, -0x00000000,0x00000000,0x00003fc1,0x0003fc40, -0x000037c1,0x00091b40,0x00003fc1,0x000911c0, -0x000037c1,0x000957c0,0x00003fc1,0x000951c0, -0x000037c1,0x00000000,0x00003fc1,0x000991c0, -0x000037c1,0x00000000,0x00003fc1,0x0009d1c0, -0x000037c1,0x00000000,0x0001ccc1,0x000915c0, -0x0001c441,0x0009d800,0x0009cdc1,0x00091240, -0x0001c541,0x00091d00,0x0009cfc1,0x00095240, -0x0001c741,0x00095c80,0x000e8ca9,0x00099240, -0x000e85ad,0x00095640,0x00069ca9,0x00099d80, -0x000e952d,0x00099640,0x000eaca9,0x0009d6c0, -0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80, -0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0, -0x000ec5ad,0x0009da40,0x000edca9,0x0009d300, -0x000a6e0a,0x00001000,0x000ed52d,0x00091e40, -0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40, -0x0006fca9,0x00002500,0x000fb208,0x000c59a0, -0x000ef52d,0x0009de40,0x00068ca9,0x000912c1, -0x000683ad,0x00095241,0x00020f05,0x000991c1, -0x00000000,0x00000000,0x00086f88,0x00001000, -0x0009cf81,0x000b5340,0x0009c701,0x000b92c0, -0x0009de81,0x000bd300,0x0009d601,0x000b1700, -0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0, -0x000a0f81,0x000bd740,0x00020701,0x000b5c80, -0x000a1681,0x000b97c0,0x00021601,0x00002500, -0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0, -0x00021681,0x00002d00,0x00020f81,0x000bd800, -0x000a0701,0x000b5bc0,0x00021601,0x00003500, -0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0, -0x00021681,0x00003d00,0x00020f81,0x000b1d00, -0x000a0701,0x000b1fc0,0x00021601,0x00020500, -0x00020f81,0x000b1341,0x000a0701,0x000b9fc0, -0x00021681,0x00020d00,0x00020f81,0x000bde80, -0x000a0701,0x000bdfc0,0x00021601,0x00021500, -0x00020f81,0x000b9341,0x00020701,0x000b53c1, -0x00021681,0x00021d00,0x000a0f81,0x000d0380, -0x0000b601,0x000b15c0,0x00007b01,0x00000000, -0x00007b81,0x000bd1c0,0x00007b01,0x00000000, -0x00007b81,0x000b91c0,0x00007b01,0x000b57c0, -0x00007b81,0x000b51c0,0x00007b01,0x000b1b40, -0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0, -0x0007e488,0x000d7e45,0x00000000,0x000d7a44, -0x0007e48a,0x00000000,0x00011f05,0x00084080, -0x00000000,0x00000000,0x00001705,0x000b3540, -0x00008a01,0x000bf040,0x00007081,0x000bb5c0, -0x00055488,0x00000000,0x0000d482,0x0003fc40, -0x0003fc88,0x00000000,0x0001e401,0x000b3a00, -0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784, -0x000c86b0,0x00001007,0x00008281,0x000bb240, -0x0000b801,0x000b7140,0x00007888,0x00000000, -0x0000073c,0x00001000,0x0007f188,0x000c0000, -0x00000000,0x00000000,0x00055288,0x000c555c, -0x0005528a,0x000c0000,0x0009fa88,0x000c5d00, -0x0000fa88,0x00000000,0x00000032,0x00001000, -0x0000073d,0x00001000,0x0007f188,0x000c0000, -0x00000000,0x00000000,0x0008c01c,0x00001003, -0x00002705,0x00001008,0x0008b201,0x000c1392, -0x0000ba01,0x00000000,0x00008731,0x00001400, -0x0004c108,0x000fe0c4,0x00057488,0x00000000, -0x000a6388,0x00001001,0x0008b334,0x000bc141, -0x0003020e,0x00000000,0x000886b0,0x00001008, -0x00003625,0x000c5dfa,0x000a638a,0x00001001, -0x0008020e,0x00001002,0x0008a6b0,0x00001008, -0x0007f301,0x00000000,0x00000000,0x00000000, -0x00002725,0x000a8c40,0x000000ae,0x00000000, -0x000d8630,0x00001008,0x00000000,0x000c74e0, -0x0007d182,0x0002d640,0x000a8630,0x00001008, -0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5, -0x0007420a,0x000c0000,0x00062208,0x000c4117, -0x00070630,0x00001009,0x00000000,0x000c0000, -0x0001022e,0x00000000,0x0003a630,0x00001009, -0x00000000,0x000c0000,0x00000036,0x00001000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x0002a730,0x00001008,0x0007f801,0x000c0000, -0x00000037,0x00001000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x0002a730,0x00001008, -0x00000033,0x00001000,0x0002a705,0x00001008, -0x00007a01,0x000c0000,0x000e6288,0x000d550a, -0x0006428a,0x00000000,0x00060730,0x0000100a, -0x00000000,0x000c0000,0x00000000,0x00000000, -0x0007aab0,0x00034880,0x00078fb0,0x0000100b, -0x00057488,0x00000000,0x00033b94,0x00081140, -0x000183ae,0x00000000,0x000786b0,0x0000100b, -0x00022f05,0x000c3545,0x0000eb8a,0x00000000, -0x00042731,0x00001003,0x0007aab0,0x00034880, -0x00048fb0,0x0000100a,0x00057488,0x00000000, -0x00033b94,0x00081140,0x000183ae,0x00000000, -0x000806b0,0x0000100b,0x00022f05,0x00000000, -0x00007401,0x00091140,0x00048f05,0x000951c0, -0x00042731,0x00001003,0x0000473d,0x00001000, -0x000f19b0,0x000bbc47,0x00080000,0x000bffc7, -0x000fe19e,0x00001003,0x00000000,0x00000000, -0x0008e19c,0x00001003,0x000083c1,0x00093040, -0x00000f41,0x00097140,0x0000a841,0x0009b240, -0x0000a0c1,0x0009f040,0x0001c641,0x00093540, -0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44, -0x00055208,0x00000000,0x00010705,0x000a2880, -0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5, -0x0004ef0a,0x000c0000,0x00012f05,0x00036880, -0x00065308,0x000c2997,0x000d86b0,0x0000100a, -0x0004410a,0x000d40c7,0x00000000,0x00000000, -0x00080730,0x00001004,0x00056f0a,0x000ea105, -0x00000000,0x00000000,0x0000473d,0x00001000, -0x000f19b0,0x000bbc47,0x00080000,0x000bffc7, -0x0000273d,0x00001000,0x00000000,0x000eba44, -0x00048f05,0x0000f440,0x00007401,0x0000f7c0, -0x00000734,0x00001000,0x00010705,0x000a6880, -0x00006a88,0x000c75c4,0x00000000,0x000e5084, -0x00000000,0x000eba44,0x00087401,0x000e4782, -0x00000734,0x00001000,0x00010705,0x000a6880, -0x00006a88,0x000c75c4,0x0007c108,0x000c0000, -0x0007e721,0x000bed40,0x00005f25,0x000badc0, -0x0003ba97,0x000beb80,0x00065590,0x000b2e00, -0x00033217,0x00003ec0,0x00065590,0x000b8e40, -0x0003ed80,0x000491c0,0x00073fb0,0x00074c80, -0x000283a0,0x0000100c,0x000ee388,0x00042970, -0x00008301,0x00021ef2,0x000b8f14,0x0000000f, -0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6, -0x000032ac,0x000c3916,0x0004edc2,0x00074c80, -0x00078898,0x00001000,0x00038894,0x00000032, -0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6, -0x0004edc2,0x000c1956,0x0000722c,0x00034a00, -0x00041705,0x0009ed40,0x00058730,0x00001400, -0x000d7488,0x000c3a00,0x00048f05,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000, -0x00000000,0x00000000,0x00000000,0x00000000} - }; +/**************************************************************************** + * "CWCIMAGE.H"-- For CS46XX. Ver 1.04 + * Copyright 1998-2000 (c) Cirrus Logic Corp. + * Version 1.04 + **************************************************************************** + */ +#define CLEAR__COUNT 3 +#define FILL__COUNT 4 +#define BA1__DWORD_SIZE 13*1024+512 + +static struct +{ + unsigned BA1__DestByteOffset; + unsigned BA1__SourceSize; +} ClrStat[CLEAR__COUNT] ={ {0x00000000, 0x00003000 }, + {0x00010000, 0x00003800 }, + {0x00020000, 0x00007000 } }; + +static u32 FillArray1[]={ +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000163,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00200040,0x00008010,0x00000000, +0x00000000,0x80000001,0x00000001,0x00060000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00900080,0x00000173,0x00000000, +0x00000000,0x00000010,0x00800000,0x00900000, +0xf2c0000f,0x00000200,0x00000000,0x00010600, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000163,0x330300c2, +0x06000000,0x00000000,0x80008000,0x80008000, +0x3fc0000f,0x00000301,0x00010400,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00b00000,0x00d0806d,0x330480c3, +0x04800000,0x00000001,0x00800001,0x0000ffff, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x066a0600,0x06350070,0x0000929d,0x929d929d, +0x00000000,0x0000735a,0x00000600,0x00000000, +0x929d735a,0x00000000,0x00010000,0x735a735a, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x0000804f,0x000000c3, +0x05000000,0x00a00010,0x00000000,0x80008000, +0x00000000,0x00000000,0x00000700,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000080,0x00a00000,0x0000809a,0x000000c2, +0x07400000,0x00000000,0x80008000,0xffffffff, +0x00c80028,0x00005555,0x00000000,0x000107a0, +0x00c80028,0x000000c2,0x06800000,0x00000000, +0x06e00080,0x00300000,0x000080bb,0x000000c9, +0x07a00000,0x04000000,0x80008000,0xffffffff, +0x00c80028,0x00005555,0x00000000,0x00000780, +0x00c80028,0x000000c5,0xff800000,0x00000000, +0x00640080,0x00c00000,0x00008197,0x000000c9, +0x07800000,0x04000000,0x80008000,0xffffffff, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x0000805e,0x000000c1, +0x00000000,0x00800000,0x80008000,0x80008000, +0x00020000,0x0000ffff,0x00000000,0x00000000}; + +static u32 FillArray2[]={ +0x929d0600,0x929d929d,0x929d929d,0x929d0000, +0x929d929d,0x929d929d,0x929d929d,0x929d929d, +0x929d929d,0x00100635,0x060b013f,0x00000004, +0x00000001,0x007a0002,0x00000000,0x066e0610, +0x0105929d,0x929d929d,0x929d929d,0x929d929d, +0x929d929d,0xa431ac75,0x0001735a,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0x735a0051, +0x00000000,0x929d929d,0x929d929d,0x929d929d, +0x929d929d,0x929d929d,0x929d929d,0x929d929d, +0x929d929d,0x929d929d,0x00000000,0x06400136, +0x0000270f,0x00010000,0x007a0000,0x00000000, +0x068e0645,0x0105929d,0x929d929d,0x929d929d, +0x929d929d,0x929d929d,0xa431ac75,0x0001735a, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0xa431ac75,0xa431ac75,0xa431ac75,0xa431ac75, +0x735a0100,0x00000000,0x00000000,0x00000000}; + +static u32 FillArray3[]={ +0x00000000,0x00000000,0x00000000,0x00010004}; + +static u32 FillArray4[]={ +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00001705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00009705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00011705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00019705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00021705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00029705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00031705,0x00001400,0x000a411e,0x00001003, +0x00040730,0x00001002,0x000f619e,0x00001003, +0x00039705,0x00001400,0x000a411e,0x00001003, +0x000fe19e,0x00001003,0x0009c730,0x00001003, +0x0008e19c,0x00001003,0x000083c1,0x00093040, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00009705,0x00001400,0x000a211e,0x00001003, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00011705,0x00001400,0x000a211e,0x00001003, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00019705,0x00001400,0x000a211e,0x00001003, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00021705,0x00001400,0x000a211e,0x00001003, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00029705,0x00001400,0x000a211e,0x00001003, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00031705,0x00001400,0x000a211e,0x00001003, +0x00098730,0x00001002,0x000ee19e,0x00001003, +0x00039705,0x00001400,0x000a211e,0x00001003, +0x0000a730,0x00001008,0x000e2730,0x00001002, +0x0000a731,0x00001002,0x0000a731,0x00001002, +0x0000a731,0x00001002,0x0000a731,0x00001002, +0x0000a731,0x00001002,0x0000a731,0x00001002, +0x00000000,0x00000000,0x000f619c,0x00001003, +0x0007f801,0x000c0000,0x00000037,0x00001000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x000c0000,0x00000000,0x00000000, +0x0000373c,0x00001000,0x00000000,0x00000000, +0x000ee19c,0x00001003,0x0007f801,0x000c0000, +0x00000037,0x00001000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x0000273c,0x00001000, +0x00000033,0x00001000,0x000e679e,0x00001003, +0x00007705,0x00001400,0x000ac71e,0x00001003, +0x00087fc1,0x000c3be0,0x0007f801,0x000c0000, +0x00000037,0x00001000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x0000a730,0x00001003, +0x00000033,0x00001000,0x0007f801,0x000c0000, +0x00000037,0x00001000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x000c0000, +0x00000032,0x00001000,0x0000273d,0x00001000, +0x0004a730,0x00001003,0x00000f41,0x00097140, +0x0000a841,0x0009b240,0x0000a0c1,0x0009f040, +0x0001c641,0x00093540,0x0001cec1,0x0009b5c0, +0x00000000,0x00000000,0x0001bf05,0x0003fc40, +0x00002725,0x000aa400,0x00013705,0x00093a00, +0x0000002e,0x0009d6c0,0x00038630,0x00001004, +0x0004ef0a,0x000eb785,0x0003fc8a,0x00000000, +0x00000000,0x000c70e0,0x0007d182,0x0002c640, +0x00000630,0x00001004,0x000799b8,0x0002c6c0, +0x00031705,0x00092240,0x00039f05,0x000932c0, +0x0003520a,0x00000000,0x00040731,0x0000100b, +0x00010705,0x000b20c0,0x00000000,0x000eba44, +0x00032108,0x000c60c4,0x00065208,0x000c2917, +0x000406b0,0x00001007,0x00012f05,0x00036880, +0x0002818e,0x000c0000,0x0004410a,0x00000000, +0x00040630,0x00001007,0x00029705,0x000c0000, +0x00000000,0x00000000,0x00003fc1,0x0003fc40, +0x000037c1,0x00091b40,0x00003fc1,0x000911c0, +0x000037c1,0x000957c0,0x00003fc1,0x000951c0, +0x000037c1,0x00000000,0x00003fc1,0x000991c0, +0x000037c1,0x00000000,0x00003fc1,0x0009d1c0, +0x000037c1,0x00000000,0x0001ccc1,0x000915c0, +0x0001c441,0x0009d800,0x0009cdc1,0x00091240, +0x0001c541,0x00091d00,0x0009cfc1,0x00095240, +0x0001c741,0x00095c80,0x000e8ca9,0x00099240, +0x000e85ad,0x00095640,0x00069ca9,0x00099d80, +0x000e952d,0x00099640,0x000eaca9,0x0009d6c0, +0x000ea5ad,0x00091a40,0x0006bca9,0x0009de80, +0x000eb52d,0x00095a40,0x000ecca9,0x00099ac0, +0x000ec5ad,0x0009da40,0x000edca9,0x0009d300, +0x000a6e0a,0x00001000,0x000ed52d,0x00091e40, +0x000eeca9,0x00095ec0,0x000ee5ad,0x00099e40, +0x0006fca9,0x00002500,0x000fb208,0x000c59a0, +0x000ef52d,0x0009de40,0x00068ca9,0x000912c1, +0x000683ad,0x00095241,0x00020f05,0x000991c1, +0x00000000,0x00000000,0x00086f88,0x00001000, +0x0009cf81,0x000b5340,0x0009c701,0x000b92c0, +0x0009de81,0x000bd300,0x0009d601,0x000b1700, +0x0001fd81,0x000b9d80,0x0009f501,0x000b57c0, +0x000a0f81,0x000bd740,0x00020701,0x000b5c80, +0x000a1681,0x000b97c0,0x00021601,0x00002500, +0x000a0701,0x000b9b40,0x000a0f81,0x000b1bc0, +0x00021681,0x00002d00,0x00020f81,0x000bd800, +0x000a0701,0x000b5bc0,0x00021601,0x00003500, +0x000a0f81,0x000b5f40,0x000a0701,0x000bdbc0, +0x00021681,0x00003d00,0x00020f81,0x000b1d00, +0x000a0701,0x000b1fc0,0x00021601,0x00020500, +0x00020f81,0x000b1341,0x000a0701,0x000b9fc0, +0x00021681,0x00020d00,0x00020f81,0x000bde80, +0x000a0701,0x000bdfc0,0x00021601,0x00021500, +0x00020f81,0x000b9341,0x00020701,0x000b53c1, +0x00021681,0x00021d00,0x000a0f81,0x000d0380, +0x0000b601,0x000b15c0,0x00007b01,0x00000000, +0x00007b81,0x000bd1c0,0x00007b01,0x00000000, +0x00007b81,0x000b91c0,0x00007b01,0x000b57c0, +0x00007b81,0x000b51c0,0x00007b01,0x000b1b40, +0x00007b81,0x000b11c0,0x00087b01,0x000c3dc0, +0x0007e488,0x000d7e45,0x00000000,0x000d7a44, +0x0007e48a,0x00000000,0x00011f05,0x00084080, +0x00000000,0x00000000,0x00001705,0x000b3540, +0x00008a01,0x000bf040,0x00007081,0x000bb5c0, +0x00055488,0x00000000,0x0000d482,0x0003fc40, +0x0003fc88,0x00000000,0x0001e401,0x000b3a00, +0x0001ec81,0x000bd6c0,0x0004ef08,0x000eb784, +0x000c86b0,0x00001007,0x00008281,0x000bb240, +0x0000b801,0x000b7140,0x00007888,0x00000000, +0x0000073c,0x00001000,0x0007f188,0x000c0000, +0x00000000,0x00000000,0x00055288,0x000c555c, +0x0005528a,0x000c0000,0x0009fa88,0x000c5d00, +0x0000fa88,0x00000000,0x00000032,0x00001000, +0x0000073d,0x00001000,0x0007f188,0x000c0000, +0x00000000,0x00000000,0x0008c01c,0x00001003, +0x00002705,0x00001008,0x0008b201,0x000c1392, +0x0000ba01,0x00000000,0x00008731,0x00001400, +0x0004c108,0x000fe0c4,0x00057488,0x00000000, +0x000a6388,0x00001001,0x0008b334,0x000bc141, +0x0003020e,0x00000000,0x000886b0,0x00001008, +0x00003625,0x000c5dfa,0x000a638a,0x00001001, +0x0008020e,0x00001002,0x0008a6b0,0x00001008, +0x0007f301,0x00000000,0x00000000,0x00000000, +0x00002725,0x000a8c40,0x000000ae,0x00000000, +0x000d8630,0x00001008,0x00000000,0x000c74e0, +0x0007d182,0x0002d640,0x000a8630,0x00001008, +0x000799b8,0x0002d6c0,0x0000748a,0x000c3ec5, +0x0007420a,0x000c0000,0x00062208,0x000c4117, +0x00070630,0x00001009,0x00000000,0x000c0000, +0x0001022e,0x00000000,0x0003a630,0x00001009, +0x00000000,0x000c0000,0x00000036,0x00001000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x0002a730,0x00001008,0x0007f801,0x000c0000, +0x00000037,0x00001000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x0002a730,0x00001008, +0x00000033,0x00001000,0x0002a705,0x00001008, +0x00007a01,0x000c0000,0x000e6288,0x000d550a, +0x0006428a,0x00000000,0x00060730,0x0000100a, +0x00000000,0x000c0000,0x00000000,0x00000000, +0x0007aab0,0x00034880,0x00078fb0,0x0000100b, +0x00057488,0x00000000,0x00033b94,0x00081140, +0x000183ae,0x00000000,0x000786b0,0x0000100b, +0x00022f05,0x000c3545,0x0000eb8a,0x00000000, +0x00042731,0x00001003,0x0007aab0,0x00034880, +0x00048fb0,0x0000100a,0x00057488,0x00000000, +0x00033b94,0x00081140,0x000183ae,0x00000000, +0x000806b0,0x0000100b,0x00022f05,0x00000000, +0x00007401,0x00091140,0x00048f05,0x000951c0, +0x00042731,0x00001003,0x0000473d,0x00001000, +0x000f19b0,0x000bbc47,0x00080000,0x000bffc7, +0x000fe19e,0x00001003,0x00000000,0x00000000, +0x0008e19c,0x00001003,0x000083c1,0x00093040, +0x00000f41,0x00097140,0x0000a841,0x0009b240, +0x0000a0c1,0x0009f040,0x0001c641,0x00093540, +0x0001cec1,0x0009b5c0,0x00000000,0x000fdc44, +0x00055208,0x00000000,0x00010705,0x000a2880, +0x0000a23a,0x00093a00,0x0003fc8a,0x000df6c5, +0x0004ef0a,0x000c0000,0x00012f05,0x00036880, +0x00065308,0x000c2997,0x000d86b0,0x0000100a, +0x0004410a,0x000d40c7,0x00000000,0x00000000, +0x00080730,0x00001004,0x00056f0a,0x000ea105, +0x00000000,0x00000000,0x0000473d,0x00001000, +0x000f19b0,0x000bbc47,0x00080000,0x000bffc7, +0x0000273d,0x00001000,0x00000000,0x000eba44, +0x00048f05,0x0000f440,0x00007401,0x0000f7c0, +0x00000734,0x00001000,0x00010705,0x000a6880, +0x00006a88,0x000c75c4,0x00000000,0x000e5084, +0x00000000,0x000eba44,0x00087401,0x000e4782, +0x00000734,0x00001000,0x00010705,0x000a6880, +0x00006a88,0x000c75c4,0x0007c108,0x000c0000, +0x0007e721,0x000bed40,0x00005f25,0x000badc0, +0x0003ba97,0x000beb80,0x00065590,0x000b2e00, +0x00033217,0x00003ec0,0x00065590,0x000b8e40, +0x0003ed80,0x000491c0,0x00073fb0,0x00074c80, +0x000283a0,0x0000100c,0x000ee388,0x00042970, +0x00008301,0x00021ef2,0x000b8f14,0x0000000f, +0x000c4d8d,0x0000001b,0x000d6dc2,0x000e06c6, +0x000032ac,0x000c3916,0x0004edc2,0x00074c80, +0x00078898,0x00001000,0x00038894,0x00000032, +0x000c4d8d,0x00092e1b,0x000d6dc2,0x000e06c6, +0x0004edc2,0x000c1956,0x0000722c,0x00034a00, +0x00041705,0x0009ed40,0x00058730,0x00001400, +0x000d7488,0x000c3a00,0x00048f05,0x00000000}; + +static struct +{ u32 Offset; + u32 Size; + u32 *pFill; +} FillStat[FILL__COUNT] = { + {0x00000000, sizeof(FillArray1), FillArray1}, + {0x00001800, sizeof(FillArray2), FillArray2}, + {0x000137f0, sizeof(FillArray3), FillArray3}, + {0x00020000, sizeof(FillArray4), FillArray4} + }; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c --- v2.4.0-test11/linux/drivers/sound/cs46xx.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/cs46xx.c Sun Dec 10 09:19:32 2000 @@ -1,6 +1,7 @@ /* * Crystal SoundFusion CS46xx driver * + * Copyright 1998-2000 Cirrus Logic Corporation * Copyright 1999-2000 Jaroslav Kysela * Copyright 2000 Alan Cox * @@ -22,12 +23,31 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * Changes: - * 20000815 Updated driver to kernel 2.4, some cleanups/fixes - * Nils Faerber - * 20001110 Added __initdata to BA1Struct in cs461x_image.h - * and three more __init here - * Bartlomiej Zolnierkiewicz + * Current maintainers: + * Cirrus Logic Corporation, Thomas Woller (tw) + * + * Nils Faerber (nf) + * + * Thanks to David Pollard for testing. + * + * Changes: + * 20000909-nf Changed cs_read, cs_write and drain_dac + * 20001025-tw Separate Playback/Capture structs and buffers. + * Added Scatter/Gather support for Playback. + * Added Capture. + * 20001027-nf Port to kernel 2.4.0-test9, some clean-ups + * Start of powermanagement support (CS46XX_PM). + * 20001128-tw Add module parm for default buffer order. + * added DMA_GFP flag to kmalloc dma buffer allocs. + * backfill silence to eliminate stuttering on + * underruns. + * 20001201-tw add resyncing of swptr on underruns. + * 20001205-tw-nf fixed GETOSPACE ioctl() after open() + * + * + * Status: + * Playback/Capture supported from 8k-48k. + * 16Bit Signed LE & 8Bit Unsigned, with Mono or Stereo supported. */ #include @@ -41,6 +61,9 @@ #include #include #include +#ifdef CS46XX_PM +#include +#endif #include #include #include @@ -53,6 +76,11 @@ #include "cs461x.h" + +/* MIDI buffer sizes */ +#define CS_MIDIINBUF 500 +#define CS_MIDIOUTBUF 500 + #define ADC_RUNNING 1 #define DAC_RUNNING 2 @@ -60,6 +88,8 @@ #define CS_FMT_STEREO 2 #define CS_FMT_MASK 3 +#define CS_TYPE_ADC 1 +#define CS_TYPE_DAC 2 /* * CS461x definitions */ @@ -72,18 +102,58 @@ #define GOF_PER_SEC 200 +#define CSDEBUG_INTERFACE 1 +#define CSDEBUG 1 +/* + * Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG + * + * + * CSDEBUG is usual mode is set to 1, then use the + * cs_debuglevel and cs_debugmask to turn on or off debugging. + * Debug level of 1 has been defined to be kernel errors and info + * that should be printed on any released driver. + */ +#if CSDEBUG +#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} +#else +#define CS_DBGOUT(mask,level,x) +#endif /* - * Define this to enable recording, - * this is curently broken and using it will cause data corruption - * in kernel- and user-space! + * cs_debugmask areas */ -/* #define CS46XX_ENABLE_RECORD */ +#define CS_INIT 0x00000001 /* initialization and probe functions */ +#define CS_ERROR 0x00000002 /* tmp debugging bit placeholder */ +#define CS_INTERRUPT 0x00000004 /* interrupt handler (separate from all other) */ +#define CS_FUNCTION 0x00000008 /* enter/leave functions */ +#define CS_WAVE_WRITE 0x00000010 /* write information for wave */ +#define CS_WAVE_READ 0x00000020 /* read information for wave */ +#define CS_MIDI_WRITE 0x00000040 /* write information for midi */ +#define CS_MIDI_READ 0x00000080 /* read information for midi */ +#define CS_MPU401_WRITE 0x00000100 /* write information for mpu401 */ +#define CS_MPU401_READ 0x00000200 /* read information for mpu401 */ +#define CS_OPEN 0x00000400 /* all open functions in the driver */ +#define CS_RELEASE 0x00000800 /* all release functions in the driver */ +#define CS_PARMS 0x00001000 /* functional and operational parameters */ +#define CS_IOCTL 0x00002000 /* ioctl (non-mixer) */ +#define CS_TMP 0x10000000 /* tmp debug mask bit */ + +#if CSDEBUG +static unsigned long cs_debuglevel=1; /* levels range from 1-9 */ +static unsigned long cs_debugmask=CS_INIT | CS_ERROR; /* use CS_DBGOUT with various mask values */ +#endif +#define DMABUF_DEFAULTORDER 3 +static unsigned long defaultorder=DMABUF_DEFAULTORDER; +#if MODULE +MODULE_PARM(defaultorder, "i"); +MODULE_PARM(cs_debuglevel, "i"); +MODULE_PARM(cs_debugmask, "i"); +#endif static int external_amp = 0; static int thinkpad = 0; -/* an instance of the 4610 channel */ +/* An instance of the 4610 channel */ struct cs_channel { @@ -92,11 +162,11 @@ void *state; }; -#define DRIVER_VERSION "0.09" +#define DRIVER_VERSION "1.10" /* magic numbers to protect our data structures */ -#define CS_CARD_MAGIC 0x46524F4D /* "FROM" */ -#define CS_STATE_MAGIC 0x414c5341 /* "ALSA" */ +#define CS_CARD_MAGIC 0x43525553 /* "CRUS" */ +#define CS_STATE_MAGIC 0x4c4f4749 /* "LOGI" */ #define NR_HW_CH 3 /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ @@ -128,7 +198,6 @@ /* hardware channel */ struct cs_channel *channel; int pringbuf; /* Software ring slot */ - int ppingbuf; /* Hardware ring slot */ void *pbuf; /* 4K hardware DMA buffer */ /* OSS buffer management stuff */ @@ -137,14 +206,21 @@ unsigned buforder; unsigned numfrag; unsigned fragshift; + unsigned divisor; + unsigned type; + void *tmpbuff; /* tmp buffer for sample conversions */ + dma_addr_t dma_handle_tmpbuff; + unsigned buforder_tmpbuff; /* Log base 2 of size in bytes.. */ /* our buffer acts like a circular ring */ unsigned hwptr; /* where dma last started, updated by update_ptr */ unsigned swptr; /* where driver last clear/filled, updated by read/write */ int count; /* bytes to be comsumed or been generated by dma machine */ unsigned total_bytes; /* total bytes dmaed by hardware */ + unsigned blocks; /* total blocks */ unsigned error; /* number of over/underruns */ + unsigned underrun; /* underrun pending before next write has occurred */ wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ /* redundant, but makes calculations easier */ @@ -156,6 +232,7 @@ unsigned mapped:1; unsigned ready:1; unsigned endcleared:1; + unsigned SGok:1; unsigned update_flag; unsigned ossfragshift; int ossmaxfrags; @@ -182,16 +259,17 @@ /* soundcore stuff */ int dev_audio; + int dev_midi; /* structures for abstraction of hardware facilities, codecs, banks and channels*/ struct ac97_codec *ac97_codec[NR_AC97]; - struct cs_state *states[NR_HW_CH]; + struct cs_state *states[2]; u16 ac97_features; - + int amplifier; /* Amplifier control */ void (*amplifier_ctrl)(struct cs_card *, int); - + int active; /* Active clocking */ void (*active_ctrl)(struct cs_card *, int); @@ -218,6 +296,20 @@ struct cs_channel *(*alloc_pcm_channel)(struct cs_card *); struct cs_channel *(*alloc_rec_pcm_channel)(struct cs_card *); void (*free_pcm_channel)(struct cs_card *, int chan); + + /* /dev/midi stuff */ + struct { + unsigned ird, iwr, icnt; + unsigned ord, owr, ocnt; + wait_queue_head_t open_wait; + wait_queue_head_t iwait; + wait_queue_head_t owait; + spinlock_t lock; + unsigned char ibuf[CS_MIDIINBUF]; + unsigned char obuf[CS_MIDIOUTBUF]; + mode_t open_mode; + struct semaphore open_sem; + } midi; }; static struct cs_card *devs = NULL; @@ -253,6 +345,224 @@ return r; } +#if CSDEBUG + +/* DEBUG ROUTINES */ + +#define SOUND_MIXER_CS_GETDBGLEVEL _SIOWR('M',120, int) +#define SOUND_MIXER_CS_SETDBGLEVEL _SIOWR('M',121, int) +#define SOUND_MIXER_CS_GETDBGMASK _SIOWR('M',122, int) +#define SOUND_MIXER_CS_SETDBGMASK _SIOWR('M',123, int) + +#define SNDCTL_DSP_CS_GETDBGLEVEL _SIOWR('P', 50, int) +#define SNDCTL_DSP_CS_SETDBGLEVEL _SIOWR('P', 51, int) +#define SNDCTL_DSP_CS_GETDBGMASK _SIOWR('P', 52, int) +#define SNDCTL_DSP_CS_SETDBGMASK _SIOWR('P', 53, int) + +static void printioctl(unsigned int x) +{ + unsigned int i; + unsigned char vidx; + /* these values are incorrect for the ac97 driver, fix. + * Index of mixtable1[] member is Device ID + * and must be <= SOUND_MIXER_NRDEVICES. + * Value of array member is index into s->mix.vol[] + */ + static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = { + [SOUND_MIXER_PCM] = 1, /* voice */ + [SOUND_MIXER_LINE1] = 2, /* AUX */ + [SOUND_MIXER_CD] = 3, /* CD */ + [SOUND_MIXER_LINE] = 4, /* Line */ + [SOUND_MIXER_SYNTH] = 5, /* FM */ + [SOUND_MIXER_MIC] = 6, /* Mic */ + [SOUND_MIXER_SPEAKER] = 7, /* Speaker */ + [SOUND_MIXER_RECLEV] = 8, /* Recording level */ + [SOUND_MIXER_VOLUME] = 9 /* Master Volume */ + }; + + switch(x) + { + case SOUND_MIXER_CS_GETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGMASK: ") ); + break; + case SOUND_MIXER_CS_GETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_GETDBGLEVEL: ") ); + break; + case SOUND_MIXER_CS_SETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGMASK: ") ); + break; + case SOUND_MIXER_CS_SETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CS_SETDBGLEVEL: ") ); + break; + case OSS_GETVERSION: + CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION: ") ); + break; + case SNDCTL_DSP_SYNC: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC: ") ); + break; + case SNDCTL_DSP_SETDUPLEX: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX: ") ); + break; + case SNDCTL_DSP_GETCAPS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS: ") ); + break; + case SNDCTL_DSP_RESET: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET: ") ); + break; + case SNDCTL_DSP_SPEED: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED: ") ); + break; + case SNDCTL_DSP_STEREO: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO: ") ); + break; + case SNDCTL_DSP_CHANNELS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS: ") ); + break; + case SNDCTL_DSP_GETFMTS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS: ") ); + break; + case SNDCTL_DSP_SETFMT: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT: ") ); + break; + case SNDCTL_DSP_POST: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST: ") ); + break; + case SNDCTL_DSP_GETTRIGGER: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER: ") ); + break; + case SNDCTL_DSP_SETTRIGGER: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER: ") ); + break; + case SNDCTL_DSP_GETOSPACE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE: ") ); + break; + case SNDCTL_DSP_GETISPACE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE: ") ); + break; + case SNDCTL_DSP_NONBLOCK: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK: ") ); + break; + case SNDCTL_DSP_GETODELAY: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY: ") ); + break; + case SNDCTL_DSP_GETIPTR: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR: ") ); + break; + case SNDCTL_DSP_GETOPTR: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR: ") ); + break; + case SNDCTL_DSP_GETBLKSIZE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE: ") ); + break; + case SNDCTL_DSP_SETFRAGMENT: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFRAGMENT: ") ); + break; + case SNDCTL_DSP_SUBDIVIDE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE: ") ); + break; + case SOUND_PCM_READ_RATE: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE: ") ); + break; + case SOUND_PCM_READ_CHANNELS: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_CHANNELS: ") ); + break; + case SOUND_PCM_READ_BITS: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS: ") ); + break; + case SOUND_PCM_WRITE_FILTER: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_WRITE_FILTER: ") ); + break; + case SNDCTL_DSP_SETSYNCRO: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO: ") ); + break; + case SOUND_PCM_READ_FILTER: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER: ") ); + break; + case SNDCTL_DSP_CS_GETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_GETDBGMASK: ") ); + break; + case SNDCTL_DSP_CS_GETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_GETDBGLEVEL: ") ); + break; + case SNDCTL_DSP_CS_SETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_SETDBGMASK: ") ); + break; + case SNDCTL_DSP_CS_SETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CS_SETDBGLEVEL: ") ); + break; + + case SOUND_MIXER_PRIVATE1: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1: ") ); + break; + case SOUND_MIXER_PRIVATE2: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2: ") ); + break; + case SOUND_MIXER_PRIVATE3: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3: ") ); + break; + case SOUND_MIXER_PRIVATE4: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4: ") ); + break; + case SOUND_MIXER_PRIVATE5: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5: ") ); + break; + case SOUND_MIXER_INFO: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO: ") ); + break; + case SOUND_OLD_MIXER_INFO: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO: ") ); + break; + + default: + switch (_IOC_NR(x)) + { + case SOUND_MIXER_VOLUME: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_VOLUME: ") ); + break; + case SOUND_MIXER_SPEAKER: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SPEAKER: ") ); + break; + case SOUND_MIXER_RECLEV: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECLEV: ") ); + break; + case SOUND_MIXER_MIC: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_MIC: ") ); + break; + case SOUND_MIXER_SYNTH: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_SYNTH: ") ); + break; + case SOUND_MIXER_RECSRC: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECSRC: ") ); + break; + case SOUND_MIXER_DEVMASK: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_DEVMASK: ") ); + break; + case SOUND_MIXER_RECMASK: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_RECMASK: ") ); + break; + case SOUND_MIXER_STEREODEVS: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_STEREODEVS: ") ); + break; + case SOUND_MIXER_CAPS: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:") ); + break; + default: + i = _IOC_NR(x); + if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) + { + CS_DBGOUT(CS_IOCTL, 4, printk("UNKNOWN IOCTL: 0x%.8x NR=%d ",x,i) ); + } + else + { + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d ", + x,i) ); + } + break; + } + } + CS_DBGOUT(CS_IOCTL, 4, printk("command = 0x%x IOC_NR=%d\n",x, _IOC_NR(x)) ); +} +#endif /* * common I/O routines @@ -306,6 +616,34 @@ card->channel[channel].used=0; } +/* + * setup a divisor value to help with conversion from + * 16bit Stereo, down to 8bit stereo/mono or 16bit mono. + * assign a divisor of 1 if using 16bit Stereo as that is + * the only format that the static image will capture. + */ +static void cs_set_divisor(struct dmabuf *dmabuf) +{ + if(dmabuf->type == CS_TYPE_DAC) + dmabuf->divisor = 1; + else if( !(dmabuf->fmt & CS_FMT_STEREO) && + (dmabuf->fmt & CS_FMT_16BIT)) + dmabuf->divisor = 2; + else if( (dmabuf->fmt & CS_FMT_STEREO) && + !(dmabuf->fmt & CS_FMT_16BIT)) + dmabuf->divisor = 2; + else if( !(dmabuf->fmt & CS_FMT_STEREO) && + !(dmabuf->fmt & CS_FMT_16BIT)) + dmabuf->divisor = 4; + else + dmabuf->divisor = 1; + + CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, printk( + "cs46xx: cs_set_divisor()- %s %d\n", + (dmabuf->type == CS_TYPE_ADC) ? "ADC" : "DAC", + dmabuf->divisor) ); +} + /* set playback sample rate */ static unsigned int cs_set_dac_rate(struct cs_state * state, unsigned int rate) { @@ -313,6 +651,7 @@ unsigned int tmp1, tmp2; unsigned int phiIncr; unsigned int correctionPerGOF, correctionPerSec; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()+ %d\n",rate) ); /* * Compute the values used to drive the actual sample rate conversion. @@ -354,6 +693,7 @@ spin_unlock_irq(&state->card->lock); dmabuf->rate = rate; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_dac_rate()- %d\n",rate) ); return rate; } @@ -365,6 +705,7 @@ unsigned int phiIncr, coeffIncr, tmp1, tmp2; unsigned int correctionPerGOF, correctionPerSec, initialDelay; unsigned int frameGroupLength, cnt; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()+ %d\n",rate) ); /* * We can only decimate by up to a factor of 1/9th the hardware rate. @@ -464,6 +805,7 @@ cs461x_poke(card, (BA1_CSPB + 4), 0x0000FFFF); spin_unlock_irq(&card->lock); dmabuf->rate = rate; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_set_adc_rate()- %d\n",rate) ); return rate; } @@ -472,27 +814,69 @@ { struct dmabuf *dmabuf = &state->dmabuf; struct cs_card *card = state->card; - unsigned int tmp, tmp1; + unsigned int tmp, Count, playFormat; + + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()+\n") ); + cs461x_poke(card, BA1_PVOL, 0x80008000); + if(!dmabuf->SGok) + cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf)); + + Count = 4; + playFormat=cs461x_peek(card, BA1_PFIE); + if ((dmabuf->fmt & CS_FMT_STEREO)) { + playFormat &= ~DMA_RQ_C2_AC_MONO_TO_STEREO; + Count *= 2; + } + else + playFormat |= DMA_RQ_C2_AC_MONO_TO_STEREO; + + if ((dmabuf->fmt & CS_FMT_16BIT)) { + playFormat &= ~(DMA_RQ_C2_AC_8_TO_16_BIT + | DMA_RQ_C2_AC_SIGNED_CONVERT); + Count *= 2; + } + else + playFormat |= (DMA_RQ_C2_AC_8_TO_16_BIT + | DMA_RQ_C2_AC_SIGNED_CONVERT); + + cs461x_poke(card, BA1_PFIE, playFormat); + + tmp = cs461x_peek(card, BA1_PDTC); + tmp &= 0xfffffe00; + cs461x_poke(card, BA1_PDTC, tmp | --Count); + + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_play_setup()-\n") ); + +} + +struct InitStruct +{ + u32 long off; + u32 long val; +} InitArray[] = { {0x00000040, 0x3fc0000f}, + {0x0000004c, 0x04800000}, + + {0x000000b3, 0x00000780}, + {0x000000b7, 0x00000000}, + {0x000000bc, 0x07800000}, + + {0x000000cd, 0x00800000}, + }; - tmp1=16; - if (!(dmabuf->fmt & CS_FMT_STEREO)) - tmp1>>=1; - cs461x_poke(card, BA1_PVOL, 0x80008000); - cs461x_poke(card, BA1_PBA, virt_to_bus(dmabuf->pbuf)); - - tmp=cs461x_peek(card, BA1_PDTC); - tmp&=~0x000003FF; - tmp|=tmp1-1; - cs461x_poke(card, BA1_PDTC, tmp); - - tmp=cs461x_peek(card, BA1_PFIE); - tmp&=~0x0000F03F; - if(!(dmabuf->fmt & CS_FMT_STEREO)) +/* + * "SetCaptureSPValues()" -- Initialize record task values before each + * capture startup. + */ +void SetCaptureSPValues(struct cs_card *card) +{ + unsigned i, offset; + CS_DBGOUT(CS_FUNCTION, 8, printk("cs46xx: SetCaptureSPValues()+\n") ); + for(i=0; icard; struct dmabuf *dmabuf = &state->dmabuf; - /* set the attenuation to 0dB */ + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()+\n") ); + + SetCaptureSPValues(card); + + /* + * set the attenuation to 0dB + */ cs461x_poke(card, BA1_CVOL, 0x80008000); - cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->pbuf)); + + /* + * set the physical address of the capture buffer into the SP + */ + cs461x_poke(card, BA1_CBA, virt_to_bus(dmabuf->rawbuf)); + + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_rec_setup()-\n") ); } @@ -514,10 +910,30 @@ struct dmabuf *dmabuf = &state->dmabuf; u32 offset; - if (!dmabuf->enable) + if ( (!(dmabuf->enable & DAC_RUNNING)) && + (!(dmabuf->enable & ADC_RUNNING) ) ) + { + CS_DBGOUT(CS_ERROR, 2, printk( + "cs46xx: ERROR cs_get_dma_addr(): not enabled \n") ); return 0; + } - offset = dmabuf->pringbuf * 2048; + /* + * ganularity is byte boundry, good part. + */ + if(dmabuf->enable & DAC_RUNNING) + { + offset = cs461x_peek(state->card, BA1_PBA); + } + else /* ADC_RUNNING must be set */ + { + offset = cs461x_peek(state->card, BA1_CBA); + } + CS_DBGOUT(CS_PARMS | CS_FUNCTION, 9, + printk("cs46xx: cs_get_dma_addr() %d\n",offset) ); + offset = (u32)bus_to_virt((unsigned long)offset) - (u32)dmabuf->rawbuf; + CS_DBGOUT(CS_PARMS | CS_FUNCTION, 8, + printk("cs46xx: cs_get_dma_addr()- %d\n",offset) ); return offset; } @@ -526,14 +942,11 @@ struct dmabuf *dmabuf = &state->dmabuf; int offset; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()+ \n") ); offset = 0; dmabuf->hwptr=dmabuf->swptr = 0; - dmabuf->ppingbuf = dmabuf->pringbuf = 0; - dmabuf->ppingbuf = 1; - if(dmabuf->fmt&CS_FMT_16BIT) - memset(dmabuf->pbuf, 0, PAGE_SIZE); - else - memset(dmabuf->pbuf, 0x80, PAGE_SIZE); + dmabuf->pringbuf = 0; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: resync_dma_ptrs()- \n") ); } /* Stop recording (lock held) */ @@ -545,20 +958,20 @@ dmabuf->enable &= ~ADC_RUNNING; - tmp=cs461x_peek(card, BA1_CCTL); - tmp&=0xFFFF; - cs461x_poke(card, BA1_CCTL, tmp); - + tmp = cs461x_peek(card, BA1_CCTL); + tmp &= 0xFFFF0000; + cs461x_poke(card, BA1_CCTL, tmp ); } static void stop_adc(struct cs_state *state) { - struct cs_card *card = state->card; unsigned long flags; - spin_lock_irqsave(&card->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()+ \n") ); + spin_lock_irqsave(&state->card->lock, flags); __stop_adc(state); - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irqrestore(&state->card->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_adc()- \n") ); } static void start_adc(struct cs_state *state) @@ -569,11 +982,17 @@ unsigned int tmp; spin_lock_irqsave(&card->lock, flags); - if ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) && dmabuf->ready) { + if (!(dmabuf->enable & ADC_RUNNING) && + ((dmabuf->mapped || dmabuf->count < (signed)dmabuf->dmasize) + && dmabuf->ready)) + { dmabuf->enable |= ADC_RUNNING; - tmp=cs461x_peek(card, BA1_CCTL); - tmp&=0xFFFF; - tmp|=card->cctl; + cs_set_divisor(dmabuf); + tmp = cs461x_peek(card, BA1_CCTL); + tmp &= 0xFFFF0000; + tmp |= card->cctl; + CS_DBGOUT(CS_FUNCTION, 2, printk( + "cs46xx: start_adc() poke 0x%x \n",tmp) ); cs461x_poke(card, BA1_CCTL, tmp); } spin_unlock_irqrestore(&card->lock, flags); @@ -595,12 +1014,13 @@ static void stop_dac(struct cs_state *state) { - struct cs_card *card = state->card; unsigned long flags; - spin_lock_irqsave(&card->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()+ \n") ); + spin_lock_irqsave(&state->card->lock, flags); __stop_dac(state); - spin_unlock_irqrestore(&card->lock, flags); + spin_unlock_irqrestore(&state->card->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: stop_dac()- \n") ); } static void start_dac(struct cs_state *state) @@ -610,53 +1030,79 @@ unsigned long flags; int tmp; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()+ \n") ); spin_lock_irqsave(&card->lock, flags); - if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) { - if(!(dmabuf->enable&DAC_RUNNING)) - { - dmabuf->enable |= DAC_RUNNING; - tmp = cs461x_peek(card, BA1_PCTL); - tmp &= 0xFFFF; - tmp |= card->pctl; - cs461x_poke(card, BA1_PCTL, tmp); - } + if (!(dmabuf->enable & DAC_RUNNING) && + ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready)) { + dmabuf->enable |= DAC_RUNNING; + tmp = cs461x_peek(card, BA1_PCTL); + tmp &= 0xFFFF; + tmp |= card->pctl; + CS_DBGOUT(CS_PARMS, 6, printk( + "cs46xx: start_dac() poke card=0x%.08x tmp=0x%.08x addr=0x%.08x \n", + (unsigned)card, (unsigned)tmp, + (unsigned)card->ba1.idx[(BA1_PCTL >> 16) & 3]+(BA1_PCTL&0xffff) ) ); + cs461x_poke(card, BA1_PCTL, tmp); } spin_unlock_irqrestore(&card->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: start_dac()- \n") ); } -#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) #define DMABUF_MINORDER 1 -/* allocate DMA buffer, playback and recording buffer should be allocated seperately */ +/* + * allocate DMA buffer, playback and recording buffers are separate. + */ static int alloc_dmabuf(struct cs_state *state) { struct dmabuf *dmabuf = &state->dmabuf; void *rawbuf = NULL; + void *tmpbuff = NULL; int order; struct page *page, *pend; /* alloc as big a chunk as we can */ - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order))) + for (order = defaultorder; order >= DMABUF_MINORDER; order--) + if((rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order))) break; if (!rawbuf) return -ENOMEM; -#ifdef DEBUG - printk("cs461x: allocated %ld (order = %d) bytes at %p\n", - PAGE_SIZE << order, order, rawbuf); -#endif - - dmabuf->ready = dmabuf->mapped = 0; - dmabuf->rawbuf = rawbuf; dmabuf->buforder = order; - + dmabuf->rawbuf = rawbuf; + /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ pend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); for (page = virt_to_page(rawbuf); page <= pend; page++) mem_map_reserve(page); + CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n", + PAGE_SIZE << order, order, rawbuf) ); +/* + * now the temp buffer for 16/8 conversions + */ + for (order = defaultorder; order >= DMABUF_MINORDER; order--) + if((tmpbuff = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order))) + break; + if (!tmpbuff) + return -ENOMEM; + CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n", + PAGE_SIZE << order, order, tmpbuff) ); + + dmabuf->tmpbuff = tmpbuff; + dmabuf->buforder_tmpbuff = order; + + /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ + pend = virt_to_page(tmpbuff + (PAGE_SIZE << order) - 1); + for (page = virt_to_page(tmpbuff); page <= pend; page++) + mem_map_reserve(page); + + CS_DBGOUT(CS_PARMS, 9, printk("cs461x: allocated %ld (order = %d) bytes at %p\n", + PAGE_SIZE << order, order, tmpbuff) ); + + dmabuf->ready = dmabuf->mapped = 0; + dmabuf->SGok = 0; return 0; } @@ -667,85 +1113,208 @@ struct page *page, *pend; if (dmabuf->rawbuf) { - /* undo marking the pages as reserved */ pend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); for (page = virt_to_page(dmabuf->rawbuf); page <= pend; page++) mem_map_unreserve(page); pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder, - dmabuf->rawbuf, dmabuf->dma_handle); + dmabuf->rawbuf, dmabuf->dma_handle); } dmabuf->rawbuf = NULL; + + if (dmabuf->tmpbuff) { + /* undo marking the pages as reserved */ + pend = virt_to_page(dmabuf->tmpbuff + (PAGE_SIZE << dmabuf->buforder_tmpbuff) - 1); + for (page = virt_to_page(dmabuf->tmpbuff); page <= pend; page++) + mem_map_unreserve(page); + pci_free_consistent(state->card->pci_dev, PAGE_SIZE << dmabuf->buforder_tmpbuff, + dmabuf->tmpbuff, dmabuf->dma_handle_tmpbuff); + } + + dmabuf->rawbuf = NULL; + dmabuf->tmpbuff = NULL; dmabuf->mapped = dmabuf->ready = 0; + dmabuf->SGok = 0; } -static int prog_dmabuf(struct cs_state *state, unsigned rec) +static int prog_dmabuf(struct cs_state *state) { - struct dmabuf *dmabuf = &state->dmabuf; - unsigned bytepersec; - unsigned bufsize; - unsigned long flags; - int ret; - - spin_lock_irqsave(&state->card->lock, flags); - resync_dma_ptrs(state); - dmabuf->total_bytes = 0; - dmabuf->count = dmabuf->error = 0; - spin_unlock_irqrestore(&state->card->lock, flags); + struct dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + unsigned long allocated_pages, allocated_bytes; + unsigned long tmp1, tmp2, fmt=0; + unsigned long *ptmp = (unsigned long *) dmabuf->pbuf; + unsigned long SGarray[9], nSGpages=0; + int ret; - /* allocate DMA buffer if not allocated yet */ - if (!dmabuf->rawbuf) - if ((ret = alloc_dmabuf(state))) - return ret; + CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()+ \n")); +/* + * check for CAPTURE and use only non-sg for initial release + */ + if(dmabuf->type == CS_TYPE_ADC) + { + CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() ADC\n")); + /* + * add in non-sg support for capture. + */ + spin_lock_irqsave(&state->card->lock, flags); + /* add code to reset the rawbuf memory. TRW */ + resync_dma_ptrs(state); + dmabuf->total_bytes = dmabuf->blocks = 0; + dmabuf->count = dmabuf->error = dmabuf->underrun = 0; - /* FIXME: figure out all this OSS fragment stuff */ - bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt]; - bufsize = PAGE_SIZE << dmabuf->buforder; - if (dmabuf->ossfragshift) { - if ((1000 << dmabuf->ossfragshift) < bytepersec) - dmabuf->fragshift = ld2(bytepersec/1000); - else - dmabuf->fragshift = dmabuf->ossfragshift; - } else { - /* lets hand out reasonable big ass buffers by default */ - dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT -2); - } - dmabuf->numfrag = bufsize >> dmabuf->fragshift; - while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) { - dmabuf->fragshift--; - dmabuf->numfrag = bufsize >> dmabuf->fragshift; - } - dmabuf->fragsize = 1 << dmabuf->fragshift; - if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag) - dmabuf->numfrag = dmabuf->ossmaxfrags; - dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt]; - dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; + dmabuf->SGok = 0; + + spin_unlock_irqrestore(&state->card->lock, flags); + + /* allocate DMA buffer if not allocated yet */ + if (!dmabuf->rawbuf || !dmabuf->tmpbuff) + if ((ret = alloc_dmabuf(state))) + return ret; + /* + * static image only supports 16Bit signed, stereo - hard code fmt + */ + fmt = CS_FMT_16BIT | CS_FMT_STEREO; + + dmabuf->numfrag = 2; + dmabuf->fragsize = 2048; + dmabuf->fragsamples = 2048 >> sample_shift[fmt]; + dmabuf->dmasize = 4096; + dmabuf->fragshift = 11; + + memset(dmabuf->rawbuf, (fmt & CS_FMT_16BIT) ? 0 : 0x80, + dmabuf->dmasize); + memset(dmabuf->tmpbuff, (fmt & CS_FMT_16BIT) ? 0 : 0x80, + PAGE_SIZE<buforder_tmpbuff); + + /* + * Now set up the ring + */ - memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, - dmabuf->dmasize); + spin_lock_irqsave(&state->card->lock, flags); + cs_rec_setup(state); + spin_unlock_irqrestore(&state->card->lock, flags); + + /* set the ready flag for the dma buffer */ + dmabuf->ready = 1; + CS_DBGOUT(CS_PARMS, 4, printk( + "cs461x: prog_dmabuf(): CAPTURE rate=%d fmt=0x%x numfrag=%d " + "fragsize=%d dmasize=%d\n", + dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, + dmabuf->fragsize, dmabuf->dmasize) ); + + CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- 0 \n")); + return 0; + } + else if (dmabuf->type == CS_TYPE_DAC) + { /* - * Now set up the ring + * Must be DAC */ + CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf() DAC\n")); + spin_lock_irqsave(&state->card->lock, flags); + resync_dma_ptrs(state); + dmabuf->total_bytes = dmabuf->blocks = 0; + dmabuf->count = dmabuf->error = dmabuf->underrun = 0; - spin_lock_irqsave(&state->card->lock, flags); - if (rec) { - cs_rec_setup(state); - } else { + dmabuf->SGok = 0; + + spin_unlock_irqrestore(&state->card->lock, flags); + + /* allocate DMA buffer if not allocated yet */ + if (!dmabuf->rawbuf) + if ((ret = alloc_dmabuf(state))) + return ret; + + allocated_pages = 1 << dmabuf->buforder; + allocated_bytes = allocated_pages*PAGE_SIZE; + + if(allocated_pages < 2) + { + CS_DBGOUT(CS_FUNCTION, 4, printk( + "cs46xx: prog_dmabuf() Error: allocated_pages too small (%d)\n", + (unsigned)allocated_pages)); + return -ENOMEM; + } + + /* Use all the pages allocated, fragsize 4k. */ + /* Use 'pbuf' for S/G page map table. */ + dmabuf->SGok = 1; /* Use S/G. */ + + nSGpages = allocated_bytes/4096; /* S/G pages always 4k. */ + + /* Set up S/G variables. */ + *ptmp = virt_to_bus(dmabuf->rawbuf); + *(ptmp+1) = 0x00000008; + for(tmp1= 1; tmp1 < nSGpages; tmp1++) { + *(ptmp+2*tmp1) = virt_to_bus( (dmabuf->rawbuf)+4096*tmp1); + if( tmp1 == nSGpages-1) + tmp2 = 0xbfff0000; + else + tmp2 = 0x80000000+8*(tmp1+1); + *(ptmp+2*tmp1+1) = tmp2; + } + SGarray[0] = 0x82c0200d; + SGarray[1] = 0xffff0000; + SGarray[2] = *ptmp; + SGarray[3] = 0x00010600; + SGarray[4] = *(ptmp+2); + SGarray[5] = 0x80000010; + SGarray[6] = *ptmp; + SGarray[7] = *(ptmp+2); + SGarray[8] = (virt_to_bus(dmabuf->pbuf) & 0xffff000) | 0x10; + + if (dmabuf->SGok) { + dmabuf->numfrag = nSGpages; + dmabuf->fragsize = 4096; + dmabuf->fragsamples = 4096 >> sample_shift[dmabuf->fmt]; + dmabuf->fragshift = 12; + dmabuf->dmasize = dmabuf->numfrag*4096; + } + else { + SGarray[0] = 0xf2c0000f; + SGarray[1] = 0x00000200; + SGarray[2] = 0; + SGarray[3] = 0x00010600; + SGarray[4]=SGarray[5]=SGarray[6]=SGarray[7]=SGarray[8] = 0; + dmabuf->numfrag = 2; + dmabuf->fragsize = 2048; + dmabuf->fragsamples = 2048 >> sample_shift[dmabuf->fmt]; + dmabuf->dmasize = 4096; + dmabuf->fragshift = 11; + } + for(tmp1 = 0; tmp1 < sizeof(SGarray)/4; tmp1++) + cs461x_poke( state->card, BA1_PDTC+tmp1*4, SGarray[tmp1]); + + memset(dmabuf->rawbuf, (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, + dmabuf->dmasize); + + /* + * Now set up the ring + */ + + spin_lock_irqsave(&state->card->lock, flags); cs_play_setup(state); - } - spin_unlock_irqrestore(&state->card->lock, flags); + spin_unlock_irqrestore(&state->card->lock, flags); - /* set the ready flag for the dma buffer */ - dmabuf->ready = 1; + /* set the ready flag for the dma buffer */ + dmabuf->ready = 1; -#ifdef DEBUG - printk("cs461x: prog_dmabuf, sample rate = %d, format = %d, numfrag = %d, " - "fragsize = %d dmasize = %d\n", - dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, - dmabuf->fragsize, dmabuf->dmasize); -#endif + CS_DBGOUT(CS_PARMS, 4, printk( + "cs461x: prog_dmabuf(): PLAYBACK rate=%d fmt=0x%x numfrag=%d " + "fragsize=%d dmasize=%d\n", + dmabuf->rate, dmabuf->fmt, dmabuf->numfrag, + dmabuf->fragsize, dmabuf->dmasize) ); - return 0; + CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- \n")); + return 0; + } + else + { + CS_DBGOUT(CS_FUNCTION, 4, printk("cs46xx: prog_dmabuf()- Invalid Type %d\n", + dmabuf->type)); + } + return 1; } static void cs_clear_tail(struct cs_state *state) @@ -787,8 +1356,8 @@ tmo = (dmabuf->dmasize * HZ) / dmabuf->rate; tmo >>= sample_shift[dmabuf->fmt]; - tmo += (4096*HZ)/dmabuf->rate; - + tmo += (2048*HZ)/dmabuf->rate; + if (!schedule_timeout(tmo ? tmo : 1) && tmo){ printk(KERN_ERR "cs461x: drain_dac, dma timeout? %d\n", count); break; @@ -802,91 +1371,149 @@ return 0; } + /* update buffer manangement pointers, especially, dmabuf->count and dmabuf->hwptr */ -static void cs_update_ptr(struct cs_state *state) +static void cs_update_ptr(void) { - struct dmabuf *dmabuf = &state->dmabuf; - unsigned hwptr, swptr; - int clear_cnt = 0; + struct cs_card *card=devs; + struct cs_state *state; + struct dmabuf *dmabuf; + unsigned hwptr; int diff; - unsigned char silence; - /* update hardware pointer */ - hwptr = cs_get_dma_addr(state); - diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; - dmabuf->hwptr = hwptr; - dmabuf->total_bytes += diff; - - /* error handling and process wake up for DAC */ - if (dmabuf->enable == ADC_RUNNING) { - if (dmabuf->mapped) { - dmabuf->count -= diff; - if (dmabuf->count >= (signed)dmabuf->fragsize) - wake_up(&dmabuf->wait); - } else { + /* error handling and process wake up for ADC */ + state = card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + if (dmabuf->enable & ADC_RUNNING) { + /* update hardware pointer */ + hwptr = cs_get_dma_addr(state); + + diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + CS_DBGOUT(CS_PARMS, 9, printk( + "cs46xx: cs_update_ptr()+ ADC hwptr=%d diff=%d\n", + hwptr,diff) ); + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; dmabuf->count += diff; + if (dmabuf->count > dmabuf->dmasize) + dmabuf->count = dmabuf->dmasize; - if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { - /* buffer underrun or buffer overrun, we have no way to recover - it here, just stop the machine and let the process force hwptr - and swptr to sync */ - __stop_adc(state); - dmabuf->error++; - } - else if (!dmabuf->endcleared) { - swptr = dmabuf->swptr; - silence = (dmabuf->fmt & CS_FMT_16BIT ? 0 : 0x80); - if (dmabuf->count < (signed) dmabuf->fragsize) - { - clear_cnt = dmabuf->fragsize; - if ((swptr + clear_cnt) > dmabuf->dmasize) - clear_cnt = dmabuf->dmasize - swptr; - memset (dmabuf->rawbuf + swptr, silence, clear_cnt); - dmabuf->endcleared = 1; - } - } - wake_up(&dmabuf->wait); + if(dmabuf->mapped) + { + if (dmabuf->count >= (signed)dmabuf->fragsize) + wake_up(&dmabuf->wait); + } else + { + if (dmabuf->count > 0) + wake_up(&dmabuf->wait); + } } } - /* error handling and process wake up for DAC */ - if (dmabuf->enable == DAC_RUNNING) { - if (dmabuf->mapped) { - dmabuf->count += diff; - if (dmabuf->count >= (signed)dmabuf->fragsize) - wake_up(&dmabuf->wait); - } else { - dmabuf->count -= diff; - if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { - /* buffer underrun or buffer overrun, we have no way to recover - it here, just stop the machine and let the process force hwptr - and swptr to sync */ - __stop_dac(state); - dmabuf->error++; +/* + * Now the DAC + */ + state = card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + /* error handling and process wake up for DAC */ + if (dmabuf->enable & DAC_RUNNING) { + /* update hardware pointer */ + hwptr = cs_get_dma_addr(state); + + diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize; + CS_DBGOUT(CS_PARMS, 9, printk( + "cs46xx: cs_update_ptr()+ DAC hwptr=%d diff=%d\n", + hwptr,diff) ); + dmabuf->hwptr = hwptr; + dmabuf->total_bytes += diff; + if (dmabuf->mapped) { + dmabuf->count += diff; + if (dmabuf->count >= (signed)dmabuf->fragsize) + wake_up(&dmabuf->wait); + /* + * other drivers use fragsize, but don't see any sense + * in that, since dmasize is the buffer asked for + * via mmap. + */ + if( dmabuf->count > dmabuf->dmasize) + dmabuf->count &= dmabuf->dmasize-1; + } else { + dmabuf->count -= diff; + /* + * backfill with silence and clear out the last + * "diff" number of bytes. + */ + if(hwptr >= diff) + { + memset(dmabuf->rawbuf + hwptr - diff, + (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, diff); + } + else + { + memset(dmabuf->rawbuf, + (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, + (unsigned)hwptr); + memset((void *)((unsigned)dmabuf->rawbuf + + dmabuf->dmasize + hwptr - diff), + (dmabuf->fmt & CS_FMT_16BIT) ? 0 : 0x80, + diff - hwptr); + } + + if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) { + CS_DBGOUT(CS_ERROR, 2, printk( + "cs46xx: ERROR DAC count<0 or count > dmasize (%d)\n", + dmabuf->count)); + /* + * buffer underrun or buffer overrun, reset the + * count of bytes written back to 0. + */ + if(dmabuf->count < 0) + dmabuf->underrun=1; + dmabuf->count = 0; + dmabuf->error++; + } + if (dmabuf->count < (signed)dmabuf->dmasize/2) + wake_up(&dmabuf->wait); } - wake_up(&dmabuf->wait); } } } -static void cs_record_interrupt(struct cs_state *state) -{ - memcpy(state->dmabuf.rawbuf + (2048*state->dmabuf.pringbuf++), - state->dmabuf.pbuf+2048*state->dmabuf.ppingbuf++, 2048); - state->dmabuf.ppingbuf&=1; - if(state->dmabuf.pringbuf > (PAGE_SIZE<dmabuf.buforder)/2048) - state->dmabuf.pringbuf=0; - cs_update_ptr(state); -} -static void cs_play_interrupt(struct cs_state *state) +/* hold spinlock for the following! */ +static void cs_handle_midi(struct cs_card *card) { - memcpy(state->dmabuf.pbuf+2048*state->dmabuf.ppingbuf++, - state->dmabuf.rawbuf + (2048*state->dmabuf.pringbuf++), 2048); - state->dmabuf.ppingbuf&=1; - if(state->dmabuf.pringbuf >= (PAGE_SIZE<dmabuf.buforder)/2048) - state->dmabuf.pringbuf=0; - cs_update_ptr(state); + unsigned char ch; + int wake; + unsigned temp1; + + wake = 0; + while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_RBE)) { + ch = cs461x_peekBA0(card, BA0_MIDRP); + if (card->midi.icnt < CS_MIDIINBUF) { + card->midi.ibuf[card->midi.iwr] = ch; + card->midi.iwr = (card->midi.iwr + 1) % CS_MIDIINBUF; + card->midi.icnt++; + } + wake = 1; + } + if (wake) + wake_up(&card->midi.iwait); + wake = 0; + while (!(cs461x_peekBA0(card, BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) { + temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff; + cs461x_pokeBA0(card, BA0_MIDWP,temp1); + card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF; + card->midi.ocnt--; + if (card->midi.ocnt < CS_MIDIOUTBUF-16) + wake = 1; + } + if (wake) + wake_up(&card->midi.owait); } static void cs_interrupt(int irq, void *dev_id, struct pt_regs *regs) @@ -897,126 +1524,489 @@ struct cs_state *playstate = card->channel[1].state; u32 status; + CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()+ \n")); + spin_lock(&card->lock); status = cs461x_peekBA0(card, BA0_HISR); - if((status&0x7fffffff)==0) + if ((status & 0x7fffffff) == 0) { cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV); spin_unlock(&card->lock); return; } - if((status & HISR_VC0) && playstate && playstate->dmabuf.ready) - cs_play_interrupt(playstate); - if((status & HISR_VC1) && recstate && recstate->dmabuf.ready) - cs_record_interrupt(recstate); + /* + * check for playback or capture interrupt only + */ + if( ((status & HISR_VC0) && playstate && playstate->dmabuf.ready) || + (((status & HISR_VC1) && recstate && recstate->dmabuf.ready)) ) + { + CS_DBGOUT(CS_INTERRUPT, 8, printk( + "cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status)); + cs_update_ptr(); + } + + if( status & HISR_MIDI ) + cs_handle_midi(card); /* clear 'em */ cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV); spin_unlock(&card->lock); + CS_DBGOUT(CS_INTERRUPT, 4, printk("cs46xx: cs_interrupt()- \n")); +} + + +/**********************************************************************/ + +static ssize_t cs_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + struct cs_card *card = (struct cs_card *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned ptr; + int cnt; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; + while (count > 0) { + spin_lock_irqsave(&card->lock, flags); + ptr = card->midi.ird; + cnt = CS_MIDIINBUF - ptr; + if (card->midi.icnt < cnt) + cnt = card->midi.icnt; + spin_unlock_irqrestore(&card->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + interruptible_sleep_on(&card->midi.iwait); + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt)) + return ret ? ret : -EFAULT; + ptr = (ptr + cnt) % CS_MIDIINBUF; + spin_lock_irqsave(&card->lock, flags); + card->midi.ird = ptr; + card->midi.icnt -= cnt; + spin_unlock_irqrestore(&card->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + } + return ret; +} + + +static ssize_t cs_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct cs_card *card = (struct cs_card *)file->private_data; + ssize_t ret; + unsigned long flags; + unsigned ptr; + int cnt; + + if (ppos != &file->f_pos) + return -ESPIPE; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; + while (count > 0) { + spin_lock_irqsave(&card->lock, flags); + ptr = card->midi.owr; + cnt = CS_MIDIOUTBUF - ptr; + if (card->midi.ocnt + cnt > CS_MIDIOUTBUF) + cnt = CS_MIDIOUTBUF - card->midi.ocnt; + if (cnt <= 0) + cs_handle_midi(card); + spin_unlock_irqrestore(&card->lock, flags); + if (cnt > count) + cnt = count; + if (cnt <= 0) { + if (file->f_flags & O_NONBLOCK) + return ret ? ret : -EAGAIN; + interruptible_sleep_on(&card->midi.owait); + if (signal_pending(current)) + return ret ? ret : -ERESTARTSYS; + continue; + } + if (copy_from_user(card->midi.obuf + ptr, buffer, cnt)) + return ret ? ret : -EFAULT; + ptr = (ptr + cnt) % CS_MIDIOUTBUF; + spin_lock_irqsave(&card->lock, flags); + card->midi.owr = ptr; + card->midi.ocnt += cnt; + spin_unlock_irqrestore(&card->lock, flags); + count -= cnt; + buffer += cnt; + ret += cnt; + spin_lock_irqsave(&card->lock, flags); + cs_handle_midi(card); + spin_unlock_irqrestore(&card->lock, flags); + } + return ret; +} + + +static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait) +{ + struct cs_card *card = (struct cs_card *)file->private_data; + unsigned long flags; + unsigned int mask = 0; + + if (file->f_flags & FMODE_WRITE) + poll_wait(file, &card->midi.owait, wait); + if (file->f_flags & FMODE_READ) + poll_wait(file, &card->midi.iwait, wait); + spin_lock_irqsave(&card->lock, flags); + if (file->f_flags & FMODE_READ) { + if (card->midi.icnt > 0) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_flags & FMODE_WRITE) { + if (card->midi.ocnt < CS_MIDIOUTBUF) + mask |= POLLOUT | POLLWRNORM; + } + spin_unlock_irqrestore(&card->lock, flags); + return mask; } + +static int cs_midi_open(struct inode *inode, struct file *file) +{ + int minor = MINOR(inode->i_rdev); + struct cs_card *card = devs; + unsigned long flags; + while (card && card->dev_midi != minor) + card = card->next; + if (!card) + return -ENODEV; + file->private_data = card; + /* wait for device to become free */ + down(&card->midi.open_sem); + while (card->midi.open_mode & file->f_mode) { + if (file->f_flags & O_NONBLOCK) { + up(&card->midi.open_sem); + return -EBUSY; + } + up(&card->midi.open_sem); + interruptible_sleep_on(&card->midi.open_wait); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&card->midi.open_sem); + } + spin_lock_irqsave(&card->midi.lock, flags); + if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) { + card->midi.ird = card->midi.iwr = card->midi.icnt = 0; + card->midi.ord = card->midi.owr = card->midi.ocnt = 0; + card->midi.ird = card->midi.iwr = card->midi.icnt = 0; + cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f); /* Enable xmit, rcv. */ + cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM); /* Enable interrupts */ + } + if (file->f_mode & FMODE_READ) { + card->midi.ird = card->midi.iwr = card->midi.icnt = 0; + } + if (file->f_mode & FMODE_WRITE) { + card->midi.ord = card->midi.owr = card->midi.ocnt = 0; + } + spin_unlock_irqrestore(&card->midi.lock, flags); + card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE)); + up(&card->midi.open_sem); + MOD_INC_USE_COUNT; + return 0; +} + + +static int cs_midi_release(struct inode *inode, struct file *file) +{ + struct cs_card *card = (struct cs_card *)file->private_data; + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + unsigned count, tmo; + + if (file->f_mode & FMODE_WRITE) { + current->state = TASK_INTERRUPTIBLE; + add_wait_queue(&card->midi.owait, &wait); + for (;;) { + spin_lock_irqsave(&card->midi.lock, flags); + count = card->midi.ocnt; + spin_unlock_irqrestore(&card->midi.lock, flags); + if (count <= 0) + break; + if (signal_pending(current)) + break; + if (file->f_flags & O_NONBLOCK) { + remove_wait_queue(&card->midi.owait, &wait); + current->state = TASK_RUNNING; + return -EBUSY; + } + tmo = (count * HZ) / 3100; + if (!schedule_timeout(tmo ? : 1) && tmo) + printk(KERN_DEBUG "cs46xx: midi timed out??\n"); + } + remove_wait_queue(&card->midi.owait, &wait); + current->state = TASK_RUNNING; + } + down(&card->midi.open_sem); + card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE))); + up(&card->midi.open_sem); + wake_up(&card->midi.open_wait); + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Midi file operations struct. + */ +static /*const*/ struct file_operations cs_midi_fops = { + llseek: cs_llseek, + read: cs_midi_read, + write: cs_midi_write, + poll: cs_midi_poll, + open: cs_midi_open, + release: cs_midi_release, +}; + static loff_t cs_llseek(struct file *file, loff_t offset, int origin) { return -ESPIPE; } +/* + * + * CopySamples copies 16-bit stereo signed samples from the source to the + * destination, possibly converting down to unsigned 8-bit and/or mono. + * count specifies the number of output bytes to write. + * + * Arguments: + * + * dst - Pointer to a destination buffer. + * src - Pointer to a source buffer + * count - The number of bytes to copy into the destination buffer. + * fmt - CS_FMT_16BIT and/or CS_FMT_STEREO bits + * dmabuf - pointer to the dma buffer structure + * + * NOTES: only call this routine if the output desired is not 16 Signed Stereo + * + * + */ +static void CopySamples(char *dst, char *src, int count, unsigned fmt, + struct dmabuf *dmabuf) +{ + + s32 s32AudioSample; + s16 *psSrc=(s16 *)src; + s16 *psDst=(s16 *)dst; + u8 *pucDst=(u8 *)dst; + + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: CopySamples()+ ") ); + CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO + " dst=0x%x src=0x%x count=%d fmt=0x%x\n", + (unsigned)dst,(unsigned)src,(unsigned)count,(unsigned)fmt) ); + + /* + * See if the data should be output as 8-bit unsigned stereo. + */ + if((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) + { + /* + * Convert each 16-bit signed stereo sample to 8-bit unsigned + * stereo using rounding. + */ + psSrc = (s16 *)src; + count = count/2; + while(count--) + { + *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8); + } + } + /* + * See if the data should be output at 8-bit unsigned mono. + */ + else if(!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT)) + { + /* + * Convert each 16-bit signed stereo sample to 8-bit unsigned + * mono using averaging and rounding. + */ + psSrc = (s16 *)src; + count = count/2; + while(count--) + { + s32AudioSample = ((*psSrc)+(*(psSrc + 1)))/2 + (s32)0x80; + if(s32AudioSample > 0x7fff) + s32AudioSample = 0x7fff; + *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8); + psSrc += 2; + } + } + /* + * See if the data should be output at 16-bit signed mono. + */ + else if(!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT)) + { + /* + * Convert each 16-bit signed stereo sample to 16-bit signed + * mono using averaging. + */ + psSrc = (s16 *)src; + count = count/2; + while(count--) + { + *(psDst++) = (s16)((*psSrc)+(*(psSrc + 1)))/2; + psSrc += 2; + } + } +} + +/* + * cs_copy_to_user() + * replacement for the standard copy_to_user, to allow for a conversion from + * 16 bit to 8 bit and from stereo to mono, if the record conversion is active. + * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo, + * so we convert from any of the other format combinations. + */ +static unsigned cs_copy_to_user( + struct cs_state *s, + void *dest, + void *hwsrc, + unsigned cnt, + unsigned *copied) +{ + struct dmabuf *dmabuf = &s->dmabuf; + void *src = hwsrc; /* default to the standard destination buffer addr */ + + CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO + "cs_copy_to_user()+ fmt=0x%x cnt=%d dest=0x%.8x\n", + dmabuf->fmt,(unsigned)cnt,(unsigned)dest) ); + + if(cnt > dmabuf->dmasize) + { + cnt = dmabuf->dmasize; + } + if(!cnt) + { + *copied = 0; + return 0; + } + if(dmabuf->divisor != 1) + { + if(!dmabuf->tmpbuff) + { + *copied = cnt/dmabuf->divisor; + return 0; + } + + CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, + dmabuf->fmt, dmabuf); + src = dmabuf->tmpbuff; + cnt = cnt/dmabuf->divisor; + } + if (copy_to_user(dest, src, cnt)) + { + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR + "cs4281: cs_copy_to_user()- fault dest=0x%x src=0x%x cnt=%d\n", + (unsigned)dest,(unsigned)src,cnt) ); + *copied = 0; + return -EFAULT; + } + *copied = cnt; + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO + "cs4281: cs_copy_to_user()- copied bytes is %d \n",cnt) ); + return 0; +} + /* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to the user's buffer. it is filled by the dma machine and drained by this loop. */ static ssize_t cs_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { - struct cs_state *state = (struct cs_state *)file->private_data; - struct dmabuf *dmabuf = &state->dmabuf; - ssize_t ret; + struct cs_card *card=devs; + struct cs_state *state; + DECLARE_WAITQUEUE(wait, current); + struct dmabuf *dmabuf; + ssize_t ret = 0; unsigned long flags; unsigned swptr; int cnt; + unsigned copied=0; -#ifdef DEBUG - printk("cs461x: cs_read called, count = %d\n", count); -#endif + CS_DBGOUT(CS_WAVE_READ, 4, printk("cs461x: cs_read()+ %d\n",count) ); + state = (struct cs_state *)card->states[0]; + if(!state) + return -ENODEV; + dmabuf = &state->dmabuf; if (ppos != &file->f_pos) return -ESPIPE; if (dmabuf->mapped) return -ENXIO; - if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) + if (!dmabuf->ready && (ret = prog_dmabuf(state))) return ret; if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; - ret = 0; + add_wait_queue(&state->dmabuf.wait, &wait); while (count > 0) { spin_lock_irqsave(&state->card->lock, flags); - if (dmabuf->count > (signed) dmabuf->dmasize) { - /* buffer overrun, we are recovering from sleep_on_timeout, - resync hwptr and swptr, make process flush the buffer */ - dmabuf->count = dmabuf->dmasize; - dmabuf->swptr = dmabuf->hwptr; - } swptr = dmabuf->swptr; cnt = dmabuf->dmasize - swptr; if (dmabuf->count < cnt) cnt = dmabuf->count; + if (cnt <= 0) + __set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&state->card->lock, flags); - if (cnt > count) - cnt = count; + if (cnt > (count * dmabuf->divisor)) + cnt = count * dmabuf->divisor; if (cnt <= 0) { - unsigned long tmo; /* buffer is empty, start the dma machine and wait for data to be recorded */ start_adc(state); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; - return ret; - } - /* This isnt strictly right for the 810 but it'll do */ - tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); - tmo >>= sample_shift[dmabuf->fmt]; - /* There are two situations when sleep_on_timeout returns, one is when - the interrupt is serviced correctly and the process is waked up by - ISR ON TIME. Another is when timeout is expired, which means that - either interrupt is NOT serviced correctly (pending interrupt) or it - is TOO LATE for the process to be scheduled to run (scheduler latency) - which results in a (potential) buffer overrun. And worse, there is - NOTHING we can do to prevent it. */ - if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { -#ifdef DEBUG - printk(KERN_ERR "cs461x: recording schedule timeout, " - "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", - dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, - dmabuf->hwptr, dmabuf->swptr); -#endif - /* a buffer overrun, we delay the recovery untill next time the - while loop begin and we REALLY have space to record */ - } + remove_wait_queue(&state->dmabuf.wait, &wait); + break; + } + schedule(); if (signal_pending(current)) { ret = ret ? ret : -ERESTARTSYS; - return ret; + break; } continue; } - if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { + CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO + "_read() copy_to cnt=%d count=%d ", cnt,count) ); + CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO + " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n", + dmabuf->dmasize,dmabuf->count,(unsigned)buffer,ret) ); + + if (cs_copy_to_user(state, buffer, + (void *)((unsigned)dmabuf->rawbuf + swptr), cnt, &copied)) + { if (!ret) ret = -EFAULT; - return ret; + break; } - - swptr = (swptr + cnt) % dmabuf->dmasize; - - spin_lock_irqsave(&state->card->lock, flags); - dmabuf->swptr = swptr; - dmabuf->count -= cnt; - spin_unlock_irqrestore(&state->card->lock, flags); - - count -= cnt; - buffer += cnt; - ret += cnt; - start_adc(state); - } + swptr = (swptr + cnt) % dmabuf->dmasize; + spin_lock_irqsave(&card->lock, flags); + dmabuf->swptr = swptr; + dmabuf->count -= cnt; + spin_unlock_irqrestore(&card->lock, flags); + count -= copied; + buffer += copied; + ret += copied; + start_adc(state); + } + remove_wait_queue(&state->dmabuf.wait, &wait); + set_current_state(TASK_RUNNING); + CS_DBGOUT(CS_WAVE_READ, 4, printk("cs461x: cs_read()- %d\n",ret) ); return ret; } @@ -1024,27 +2014,31 @@ the soundcard. it is drained by the dma machine and filled by this loop. */ static ssize_t cs_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) { - struct cs_state *state = (struct cs_state *)file->private_data; - struct dmabuf *dmabuf = &state->dmabuf; - ssize_t ret; + struct cs_card *card=devs; + struct cs_state *state; + DECLARE_WAITQUEUE(wait, current); + struct dmabuf *dmabuf; + ssize_t ret = 0; unsigned long flags; unsigned swptr; int cnt; -#ifdef DEBUG - printk("cs461x: cs_write called, count = %d\n", count); -#endif + CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 4, + printk("cs461x: cs_write called, count = %d\n", count) ); + state = (struct cs_state *)card->states[1]; + if(!state) + return -ENODEV; + dmabuf = &state->dmabuf; if (ppos != &file->f_pos) return -ESPIPE; if (dmabuf->mapped) return -ENXIO; - if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) + if (!dmabuf->ready && (ret = prog_dmabuf(state))) return ret; if (!access_ok(VERIFY_READ, buffer, count)) return -EFAULT; - ret = 0; - + add_wait_queue(&state->dmabuf.wait, &wait); while (count > 0) { spin_lock_irqsave(&state->card->lock, flags); if (dmabuf->count < 0) { @@ -1053,49 +2047,37 @@ dmabuf->count = 0; dmabuf->swptr = dmabuf->hwptr; } + if (dmabuf->underrun) + { + dmabuf->underrun = 0; + dmabuf->hwptr = cs_get_dma_addr(state); + dmabuf->swptr = dmabuf->hwptr; + } swptr = dmabuf->swptr; cnt = dmabuf->dmasize - swptr; if (dmabuf->count + cnt > dmabuf->dmasize) cnt = dmabuf->dmasize - dmabuf->count; + if (cnt <= 0) + __set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(&state->card->lock, flags); if (cnt > count) cnt = count; if (cnt <= 0) { - unsigned long tmo; /* buffer is full, start the dma machine and wait for data to be played */ start_dac(state); if (file->f_flags & O_NONBLOCK) { if (!ret) ret = -EAGAIN; - return ret; - } - /* Not strictly correct but works */ - tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); - tmo >>= sample_shift[dmabuf->fmt]; - /* There are two situations when sleep_on_timeout returns, one is when - the interrupt is serviced correctly and the process is waked up by - ISR ON TIME. Another is when timeout is expired, which means that - either interrupt is NOT serviced correctly (pending interrupt) or it - is TOO LATE for the process to be scheduled to run (scheduler latency) - which results in a (potential) buffer underrun. And worse, there is - NOTHING we can do to prevent it. */ - if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { -#ifdef DEBUG - printk(KERN_ERR "cs461x: playback schedule timeout, " - "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", - dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, - dmabuf->hwptr, dmabuf->swptr); -#endif - /* a buffer underrun, we delay the recovery untill next time the - while loop begin and we REALLY have data to play */ - } - if (signal_pending(current)) { - if (!ret) ret = -ERESTARTSYS; - return ret; - } - continue; - } + break; + } + schedule(); + if (signal_pending(current)) { + ret = ret ? ret : -ERESTARTSYS; + break; + } + continue; + } if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { if (!ret) ret = -EFAULT; return ret; @@ -1106,6 +2088,12 @@ spin_lock_irqsave(&state->card->lock, flags); dmabuf->swptr = swptr; dmabuf->count += cnt; + if(dmabuf->count > dmabuf->dmasize) + { + CS_DBGOUT(CS_WAVE_WRITE | CS_ERROR, 2, printk( + "cs46xx: cs_write() d->count > dmasize - resetting\n")); + dmabuf->count = dmabuf->dmasize; + } dmabuf->endcleared = 0; spin_unlock_irqrestore(&state->card->lock, flags); @@ -1114,63 +2102,142 @@ ret += cnt; start_dac(state); } + remove_wait_queue(&state->dmabuf.wait, &wait); + set_current_state(TASK_RUNNING); + + CS_DBGOUT(CS_WAVE_WRITE | CS_FUNCTION, 2, + printk("cs46xx: cs_write()- ret=0x%x\n", ret) ); return ret; } static unsigned int cs_poll(struct file *file, struct poll_table_struct *wait) { - struct cs_state *state = (struct cs_state *)file->private_data; - struct dmabuf *dmabuf = &state->dmabuf; + struct cs_card *card = (struct cs_card *)file->private_data; + struct dmabuf *dmabuf; + struct cs_state *state; + unsigned long flags; unsigned int mask = 0; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()+ \n")); + if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) + { + return -EINVAL; + } if (file->f_mode & FMODE_WRITE) - poll_wait(file, &dmabuf->wait, wait); + { + state = card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + poll_wait(file, &dmabuf->wait, wait); + } + } if (file->f_mode & FMODE_READ) - poll_wait(file, &dmabuf->wait, wait); + { + state = card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + poll_wait(file, &dmabuf->wait, wait); + } + } - spin_lock_irqsave(&state->card->lock, flags); - cs_update_ptr(state); + spin_lock_irqsave(&card->lock, flags); + cs_update_ptr(); if (file->f_mode & FMODE_READ) { - if (dmabuf->count >= (signed)dmabuf->fragsize) - mask |= POLLIN | POLLRDNORM; + state = card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + if (dmabuf->count >= (signed)dmabuf->fragsize) + mask |= POLLIN | POLLRDNORM; + } } if (file->f_mode & FMODE_WRITE) { - if (dmabuf->mapped) { - if (dmabuf->count >= (signed)dmabuf->fragsize) - mask |= POLLOUT | POLLWRNORM; - } else { - if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize) - mask |= POLLOUT | POLLWRNORM; + state = card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + if (dmabuf->mapped) { + if (dmabuf->count >= (signed)dmabuf->fragsize) + mask |= POLLOUT | POLLWRNORM; + } else { + if ((signed)dmabuf->dmasize >= dmabuf->count + + (signed)dmabuf->fragsize) + mask |= POLLOUT | POLLWRNORM; + } } } - spin_unlock_irqrestore(&state->card->lock, flags); + spin_unlock_irqrestore(&card->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_poll()- \n")); return mask; } +/* + * We let users mmap the ring buffer. Its not the real DMA buffer but + * that side of the code is hidden in the IRQ handling. We do a software + * emulation of DMA from a 64K or so buffer into a 2K FIFO. + * (the hardware probably deserves a moan here but Crystal send me nice + * toys ;)). + */ + static int cs_mmap(struct file *file, struct vm_area_struct *vma) { - return -EINVAL; -#if 0 - struct cs_state *state = (struct cs_state *)file->private_data; - struct dmabuf *dmabuf = &state->dmabuf; + struct cs_card *card=devs; + struct cs_state *state; + struct dmabuf *dmabuf; int ret; unsigned long size; + CS_DBGOUT(CS_FUNCTION | CS_PARMS, 2, printk("cs46xx: cs_mmap()+ file=0x%x %s %s\n", + (unsigned)file, vma->vm_flags & VM_WRITE ? "VM_WRITE" : "", + vma->vm_flags & VM_READ ? "VM_READ" : "") ); if (vma->vm_flags & VM_WRITE) { - if ((ret = prog_dmabuf(state, 0)) != 0) - return ret; + state = card->states[1]; + if(state) + { + CS_DBGOUT(CS_OPEN, 2, printk( + "cs46xx: cs_mmap() VM_WRITE - state TRUE prog_dmabuf DAC\n") ); + if ((ret = prog_dmabuf(state)) != 0) + return ret; + } } else if (vma->vm_flags & VM_READ) { - if ((ret = prog_dmabuf(state, 1)) != 0) - return ret; - } else + state = card->states[0]; + if(state) + { + CS_DBGOUT(CS_OPEN, 2, printk( + "cs46xx: cs_mmap() VM_READ - state TRUE prog_dmabuf ADC\n") ); + if ((ret = prog_dmabuf(state)) != 0) + return ret; + } + } else { + CS_DBGOUT(CS_ERROR, 2, printk( + "cs46xx: cs_mmap() return -EINVAL\n") ); + return -EINVAL; + } + +/* + * For now ONLY support playback, but seems like the only way to use + * mmap() is to open an FD with RDWR, just read or just write access + * does not function, get an error back from the kernel. + * Also, QuakeIII opens with RDWR! So, there must be something + * to needing read/write access mapping. So, allow read/write but + * use the DAC only. + */ + state = card->states[1]; + if(!(unsigned)state) return -EINVAL; - if (vma->vm_offset != 0) + dmabuf = &state->dmabuf; + if (vma->vm_pgoff != 0) return -EINVAL; size = vma->vm_end - vma->vm_start; + + CS_DBGOUT(CS_PARMS, 2, printk("cs46xx: cs_mmap(): size=%d\n",(unsigned)size) ); + if (size > (PAGE_SIZE << dmabuf->buforder)) return -EINVAL; if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), @@ -1178,24 +2245,35 @@ return -EAGAIN; dmabuf->mapped = 1; + CS_DBGOUT(CS_FUNCTION, 2, printk("cs46xx: cs_mmap()-\n") ); return 0; -#endif } static int cs_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct cs_state *state = (struct cs_state *)file->private_data; - struct dmabuf *dmabuf = &state->dmabuf; + struct cs_card *card = (struct cs_card *)file->private_data; + struct cs_state *state; + struct dmabuf *dmabuf=0; unsigned long flags; audio_buf_info abinfo; count_info cinfo; - int val, mapped, ret; + int val, valsave, mapped, ret; - mapped = ((file->f_mode & FMODE_WRITE) && dmabuf->mapped) || - ((file->f_mode & FMODE_READ) && dmabuf->mapped); -#ifdef DEBUG - printk("cs461x: cs_ioctl, command = %2d, arg = 0x%08x\n", - _IOC_NR(cmd), arg ? *(int *)arg : 0); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + mapped = (file->f_mode & FMODE_READ) && dmabuf->mapped; + } + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + mapped |= (file->f_mode & FMODE_WRITE) && dmabuf->mapped; + } + +#if CSDEBUG + printioctl(cmd); #endif switch (cmd) @@ -1206,21 +2284,36 @@ case SNDCTL_DSP_RESET: /* FIXME: spin_lock ? */ if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - synchronize_irq(); - dmabuf->ready = 0; - resync_dma_ptrs(state); - dmabuf->swptr = dmabuf->hwptr = 0; - dmabuf->count = dmabuf->total_bytes = 0; + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + stop_dac(state); + synchronize_irq(); + dmabuf->ready = 0; + resync_dma_ptrs(state); + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; + dmabuf->blocks = 0; + dmabuf->SGok = 0; + } } if (file->f_mode & FMODE_READ) { - stop_adc(state); - synchronize_irq(); - resync_dma_ptrs(state); - dmabuf->ready = 0; - dmabuf->swptr = dmabuf->hwptr = 0; - dmabuf->count = dmabuf->total_bytes = 0; + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + stop_adc(state); + synchronize_irq(); + resync_dma_ptrs(state); + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; + dmabuf->blocks = 0; + dmabuf->SGok = 0; + } } + CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_RESET()-\n") ); return 0; case SNDCTL_DSP_SYNC: @@ -1228,170 +2321,335 @@ return drain_dac(state, file->f_flags & O_NONBLOCK); return 0; - case SNDCTL_DSP_SPEED: /* set smaple rate */ + case SNDCTL_DSP_SPEED: /* set sample rate */ if (get_user(val, (int *)arg)) return -EFAULT; if (val >= 0) { - if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - dmabuf->ready = 0; - cs_set_dac_rate(state, val); - } if (file->f_mode & FMODE_READ) { - stop_adc(state); - dmabuf->ready = 0; - cs_set_adc_rate(state, val); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + stop_adc(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + cs_set_adc_rate(state, val); + cs_set_divisor(dmabuf); + } + } + if (file->f_mode & FMODE_WRITE) { + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + stop_dac(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + cs_set_dac_rate(state, val); + cs_set_divisor(dmabuf); + } } + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( + "cs46xx: cs_ioctl() DSP_SPEED %s %s %d\n", + file->f_mode & FMODE_WRITE ? "DAC" : "", + file->f_mode & FMODE_READ ? "ADC" : "", + dmabuf->rate ) ); + return put_user(dmabuf->rate, (int *)arg); } - return put_user(dmabuf->rate, (int *)arg); + return put_user(0, (int *)arg); case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - dmabuf->ready = 0; - if(val) - dmabuf->fmt |= CS_FMT_STEREO; - else - dmabuf->fmt &= ~CS_FMT_STEREO; + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + stop_dac(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + if(val) + dmabuf->fmt |= CS_FMT_STEREO; + else + dmabuf->fmt &= ~CS_FMT_STEREO; + cs_set_divisor(dmabuf); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( + "cs46xx: DSP_STEREO() DAC %s\n", + (dmabuf->fmt & CS_FMT_STEREO) ? + "STEREO":"MONO") ); + } } if (file->f_mode & FMODE_READ) { - stop_adc(state); - dmabuf->ready = 0; - if(val) + state = (struct cs_state *)card->states[0]; + if(state) { - dmabuf->fmt |= CS_FMT_STEREO; - return put_user(1, (int *)arg); + dmabuf = &state->dmabuf; + stop_adc(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + if(val) + dmabuf->fmt |= CS_FMT_STEREO; + else + dmabuf->fmt &= ~CS_FMT_STEREO; + cs_set_divisor(dmabuf); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( + "cs46xx: DSP_STEREO() ADC %s\n", + (dmabuf->fmt & CS_FMT_STEREO) ? + "STEREO":"MONO") ); } -#if 0 - /* Needs extra work to support this */ - - else - dmabuf->fmt &= ~CS_FMT_STEREO; -#endif } return 0; case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { - if ((val = prog_dmabuf(state, 0))) - return val; - return put_user(dmabuf->fragsize, (int *)arg); + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + if ((val = prog_dmabuf(state))) + return val; + return put_user(dmabuf->fragsize, (int *)arg); + } } if (file->f_mode & FMODE_READ) { - if ((val = prog_dmabuf(state, 1))) - return val; - return put_user(dmabuf->fragsize, (int *)arg); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + if ((val = prog_dmabuf(state))) + return val; + return put_user(dmabuf->fragsize/dmabuf->divisor, + (int *)arg); + } } + return put_user(0, (int *)arg); case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ - return put_user(AFMT_S16_LE, (int *)arg); + return put_user(AFMT_S16_LE | AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Select sample format */ if (get_user(val, (int *)arg)) return -EFAULT; + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk( + "cs46xx: cs_ioctl() DSP_SETFMT %s %s %s %s\n", + file->f_mode & FMODE_WRITE ? "DAC" : "", + file->f_mode & FMODE_READ ? "ADC" : "", + val == AFMT_S16_LE ? "16Bit Signed" : "", + val == AFMT_U8 ? "8Bit Unsigned" : "") ); + valsave = val; if (val != AFMT_QUERY) { - if(val==AFMT_S16_LE/* || val==AFMT_U8*/) + if(val==AFMT_S16_LE || val==AFMT_U8) { if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - dmabuf->ready = 0; + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + stop_dac(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + if(val==AFMT_S16_LE) + dmabuf->fmt |= CS_FMT_16BIT; + else + dmabuf->fmt &= ~CS_FMT_16BIT; + cs_set_divisor(dmabuf); + if((ret = prog_dmabuf(state))) + return ret; + } } if (file->f_mode & FMODE_READ) { - stop_adc(state); - dmabuf->ready = 0; + val = valsave; + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + stop_adc(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + if(val==AFMT_S16_LE) + dmabuf->fmt |= CS_FMT_16BIT; + else + dmabuf->fmt &= ~CS_FMT_16BIT; + cs_set_divisor(dmabuf); + if((ret = prog_dmabuf(state))) + return ret; + } } - if(val==AFMT_S16_LE) - dmabuf->fmt |= CS_FMT_16BIT; - else - dmabuf->fmt &= ~CS_FMT_16BIT; + } + else + { + CS_DBGOUT(CS_IOCTL | CS_ERROR, 2, printk( + "cs46xx: DSP_SETFMT() Unsupported format (0x%x)\n", + valsave) ); } } - if(dmabuf->fmt&CS_FMT_16BIT) - return put_user(AFMT_S16_LE, (int *)arg); else - return put_user(AFMT_U8, (int *)arg); + { + if(file->f_mode & FMODE_WRITE) + { + state = (struct cs_state *)card->states[1]; + if(state) + dmabuf = &state->dmabuf; + } + else if(file->f_mode & FMODE_READ) + { + state = (struct cs_state *)card->states[0]; + if(state) + dmabuf = &state->dmabuf; + } + } + if(dmabuf) + { + if(dmabuf->fmt & CS_FMT_16BIT) + return put_user(AFMT_S16_LE, (int *)arg); + else + return put_user(AFMT_U8, (int *)arg); + } + return put_user(0, (int *)arg); case SNDCTL_DSP_CHANNELS: if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - dmabuf->ready = 0; - if (val > 1) - dmabuf->fmt |= CS_FMT_STEREO; - else - dmabuf->fmt &= ~CS_FMT_STEREO; + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + stop_dac(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + if(val>1) + dmabuf->fmt |= CS_FMT_STEREO; + else + dmabuf->fmt &= ~CS_FMT_STEREO; + cs_set_divisor(dmabuf); + if (prog_dmabuf(state)) + return 0; + } } if (file->f_mode & FMODE_READ) { - stop_adc(state); - dmabuf->ready = 0; + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + stop_adc(state); + dmabuf->ready = 0; + dmabuf->SGok = 0; + if(val>1) + dmabuf->fmt |= CS_FMT_STEREO; + else + dmabuf->fmt &= ~CS_FMT_STEREO; + cs_set_divisor(dmabuf); + if (prog_dmabuf(state)) + return 0; + } } } return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, (int *)arg); case SNDCTL_DSP_POST: - /* FIXME: the same as RESET ?? */ + /* + * There will be a longer than normal pause in the data. + * so... do nothing, because there is nothing that we can do. + */ return 0; case SNDCTL_DSP_SUBDIVIDE: - if (dmabuf->subdivision) - return -EINVAL; - if (get_user(val, (int *)arg)) - return -EFAULT; - if (val != 1 && val != 2) - return -EINVAL; - dmabuf->subdivision = val; + if (file->f_mode & FMODE_WRITE) { + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + if (dmabuf->subdivision) + return -EINVAL; + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != 1 && val != 2) + return -EINVAL; + dmabuf->subdivision = val; + } + } + if (file->f_mode & FMODE_READ) { + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + if (dmabuf->subdivision) + return -EINVAL; + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != 1 && val != 2) + return -EINVAL; + dmabuf->subdivision = val; + } + } return 0; case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, (int *)arg)) return -EFAULT; - dmabuf->ossfragshift = val & 0xffff; - dmabuf->ossmaxfrags = (val >> 16) & 0xffff; - switch(dmabuf->ossmaxfrags) - { - case 1: - dmabuf->ossfragshift=12; - return 0; - default: - /* Fragments must be 2K long */ - dmabuf->ossfragshift = 11; - dmabuf->ossmaxfrags=2; + if (file->f_mode & FMODE_WRITE) { + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + dmabuf->ossfragshift = val & 0xffff; + dmabuf->ossmaxfrags = (val >> 16) & 0xffff; + } + } + if (file->f_mode & FMODE_READ) { + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + dmabuf->ossfragshift = val & 0xffff; + dmabuf->ossmaxfrags = (val >> 16) & 0xffff; + } } return 0; case SNDCTL_DSP_GETOSPACE: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - if (!dmabuf->enable && (val = prog_dmabuf(state, 0)) != 0) - return val; - spin_lock_irqsave(&state->card->lock, flags); - cs_update_ptr(state); - abinfo.fragsize = dmabuf->fragsize; - abinfo.bytes = dmabuf->dmasize - dmabuf->count; - abinfo.fragstotal = dmabuf->numfrag; - abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; - spin_unlock_irqrestore(&state->card->lock, flags); - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + spin_lock_irqsave(&state->card->lock, flags); + cs_update_ptr(); + abinfo.fragsize = dmabuf->fragsize; + abinfo.fragstotal = dmabuf->numfrag; + /* + * for mmap we always have total space available + */ + if (dmabuf->mapped) + abinfo.bytes = dmabuf->dmasize; + else + abinfo.bytes = dmabuf->dmasize - dmabuf->count; + + abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; + spin_unlock_irqrestore(&state->card->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + } + return -ENODEV; case SNDCTL_DSP_GETISPACE: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - if (!dmabuf->enable && (val = prog_dmabuf(state, 1)) != 0) - return val; - spin_lock_irqsave(&state->card->lock, flags); - cs_update_ptr(state); - abinfo.fragsize = dmabuf->fragsize; - abinfo.bytes = dmabuf->count; - abinfo.fragstotal = dmabuf->numfrag; - abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; - spin_unlock_irqrestore(&state->card->lock, flags); - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + spin_lock_irqsave(&state->card->lock, flags); + cs_update_ptr(); + abinfo.fragsize = dmabuf->fragsize/dmabuf->divisor; + abinfo.bytes = dmabuf->count/dmabuf->divisor; + abinfo.fragstotal = dmabuf->numfrag; + abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; + spin_unlock_irqrestore(&state->card->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + } + return -ENODEV; case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; @@ -1403,58 +2661,106 @@ case SNDCTL_DSP_GETTRIGGER: val = 0; - if (file->f_mode & FMODE_READ && dmabuf->enable) - val |= PCM_ENABLE_INPUT; - if (file->f_mode & FMODE_WRITE && dmabuf->enable) - val |= PCM_ENABLE_OUTPUT; + CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()+\n") ); + if (file->f_mode & FMODE_WRITE) + { + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + if(dmabuf->enable & DAC_RUNNING) + val |= PCM_ENABLE_INPUT; + } + } + if (file->f_mode & FMODE_READ) + { + if(state) + { + state = (struct cs_state *)card->states[0]; + dmabuf = &state->dmabuf; + if(dmabuf->enable & ADC_RUNNING) + val |= PCM_ENABLE_OUTPUT; + } + } + CS_DBGOUT(CS_IOCTL, 2, printk("cs46xx: DSP_GETTRIGGER()- val=0x%x\n",val) ); return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: if (get_user(val, (int *)arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { - if (val & PCM_ENABLE_INPUT) { - if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) - return ret; - start_adc(state); - } else - stop_adc(state); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + if (val & PCM_ENABLE_INPUT) { + if (!dmabuf->ready && (ret = prog_dmabuf(state))) + return ret; + start_adc(state); + } else + stop_adc(state); + } } if (file->f_mode & FMODE_WRITE) { - if (val & PCM_ENABLE_OUTPUT) { - if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) - return ret; - start_dac(state); - } else - stop_dac(state); + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + if (val & PCM_ENABLE_OUTPUT) { + if (!dmabuf->ready && (ret = prog_dmabuf(state))) + return ret; + start_dac(state); + } else + stop_dac(state); + } } return 0; case SNDCTL_DSP_GETIPTR: - if (!(file->f_mode & FMODE_READ)) - return -EINVAL; - spin_lock_irqsave(&state->card->lock, flags); - cs_update_ptr(state); - cinfo.bytes = dmabuf->total_bytes; - cinfo.blocks = dmabuf->count >> dmabuf->fragshift; - cinfo.ptr = dmabuf->hwptr; - if (dmabuf->mapped) - dmabuf->count &= dmabuf->fragsize-1; - spin_unlock_irqrestore(&state->card->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + spin_lock_irqsave(&state->card->lock, flags); + cs_update_ptr(); + cinfo.bytes = dmabuf->total_bytes/dmabuf->divisor; + cinfo.blocks = dmabuf->count/dmabuf->divisor >> dmabuf->fragshift; + cinfo.ptr = dmabuf->hwptr/dmabuf->divisor; + spin_unlock_irqrestore(&state->card->lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + } + return -ENODEV; case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; - spin_lock_irqsave(&state->card->lock, flags); - cs_update_ptr(state); - cinfo.bytes = dmabuf->total_bytes; - cinfo.blocks = dmabuf->count >> dmabuf->fragshift; - cinfo.ptr = dmabuf->hwptr; - if (dmabuf->mapped) - dmabuf->count &= dmabuf->fragsize-1; - spin_unlock_irqrestore(&state->card->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + spin_lock_irqsave(&state->card->lock, flags); + cs_update_ptr(); + cinfo.bytes = dmabuf->total_bytes; + if (dmabuf->mapped) + { + cinfo.blocks = (cinfo.bytes >> dmabuf->fragshift) + - dmabuf->blocks; + CS_DBGOUT(CS_PARMS, 8, + printk("total_bytes=%d blocks=%d dmabuf->blocks=%d\n", + cinfo.bytes,cinfo.blocks,dmabuf->blocks) ); + dmabuf->blocks = cinfo.bytes >> dmabuf->fragshift; + } + else + { + cinfo.blocks = dmabuf->count >> dmabuf->fragshift; + } + cinfo.ptr = dmabuf->hwptr; + + CS_DBGOUT(CS_PARMS, 4, printk( + "cs46xx: GETOPTR bytes=%d blocks=%d ptr=%d\n", + cinfo.bytes,cinfo.blocks,cinfo.ptr) ); + spin_unlock_irqrestore(&state->card->lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + } + return -ENODEV; case SNDCTL_DSP_SETDUPLEX: return -EINVAL; @@ -1462,21 +2768,47 @@ case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - spin_lock_irqsave(&state->card->lock, flags); - cs_update_ptr(state); - val = dmabuf->count; - spin_unlock_irqrestore(&state->card->lock, flags); + state = (struct cs_state *)card->states[1]; + if(state) + { + dmabuf = &state->dmabuf; + spin_lock_irqsave(&state->card->lock, flags); + cs_update_ptr(); + val = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); + } + else + val = 0; return put_user(val, (int *)arg); case SOUND_PCM_READ_RATE: - return put_user(dmabuf->rate, (int *)arg); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + return put_user(dmabuf->rate, (int *)arg); + } + return put_user(0, (int *)arg); + case SOUND_PCM_READ_CHANNELS: - return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + return put_user((dmabuf->fmt & CS_FMT_STEREO) ? 2 : 1, (int *)arg); + } + return put_user(0, (int *)arg); case SOUND_PCM_READ_BITS: - return put_user(AFMT_S16_LE, (int *)arg); + state = (struct cs_state *)card->states[0]; + if(state) + { + dmabuf = &state->dmabuf; + return put_user(AFMT_S16_LE | AFMT_U8, (int *)arg); + } + return put_user(0, (int *)arg); case SNDCTL_DSP_MAPINBUF: case SNDCTL_DSP_MAPOUTBUF: @@ -1492,20 +2824,22 @@ /* * AMP control - null AMP */ - + static void amp_none(struct cs_card *card, int change) -{ +{ } /* * Crystal EAPD mode */ - + static void amp_voyetra(struct cs_card *card, int change) { - /* Manage the EAPD bit on the Crystal 4297 */ + /* Manage the EAPD bit on the Crystal 4297 + and the Analog AD1885 */ + int old=card->amplifier; - + card->amplifier+=change; if(card->amplifier && !old) { @@ -1528,12 +2862,11 @@ /* * Untested */ -#if 0 + static void amp_voyetra_4294(struct cs_card *card, int change) { struct ac97_codec *c=card->ac97_codec[0]; - int old = card->amplifier; - + card->amplifier+=change; if(card->amplifier) @@ -1549,7 +2882,6 @@ cs_ac97_set(c, 0x54, cs_ac97_get(c, 0x54) | 0x0180); } } -#endif /* * Handle the CLKRUN on a thinkpad. We must disable CLKRUN support @@ -1559,7 +2891,7 @@ * Linuxcare. Perhaps one day Crystal will document their chips well * enough to make them useful. */ - + static void clkrun_hack(struct cs_card *card, int change) { struct pci_dev *acpi_dev; @@ -1567,20 +2899,19 @@ u8 pp; unsigned long port; int old=card->amplifier; - - card->amplifier += change; - + + card->amplifier+=change; + acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL); if(acpi_dev == NULL) return; /* Not a thinkpad thats for sure */ - - /* Find the control port */ + /* Find the control port */ pci_read_config_byte(acpi_dev, 0x41, &pp); - port = pp<<8; + port=pp<<8; - /* Read ACPI port */ - control = inw(port+0x10); + /* Read ACPI port */ + control=inw(port+0x10); /* Flip CLKRUN off while running */ if(!card->amplifier && old) @@ -1589,142 +2920,227 @@ outw(control&~0x2000, port+0x10); } - + static int cs_open(struct inode *inode, struct file *file) { - int i = 0; struct cs_card *card = devs; struct cs_state *state = NULL; struct dmabuf *dmabuf = NULL; + int ret=0; -#ifndef CS46XX_ENABLE_RECORD - if (file->f_mode & FMODE_READ) - return -ENODEV; -#endif + CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()+ file=0x%x %s %s\n", + (unsigned)file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "", + file->f_mode & FMODE_READ ? "FMODE_READ" : "") ); - /* find an avaiable virtual channel (instance of /dev/dsp) */ - while (card != NULL) { - for (i = 0; i < NR_HW_CH; i++) { - if (card->states[i] == NULL) { - state = card->states[i] = (struct cs_state *) - kmalloc(sizeof(struct cs_state), GFP_KERNEL); - if (state == NULL) - return -ENOMEM; - memset(state, 0, sizeof(struct cs_state)); - dmabuf = &state->dmabuf; - dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL); - if(dmabuf->pbuf==NULL) - { - kfree(state); - card->states[i]=NULL; - return -ENOMEM; - } - goto found_virt; + /* + * hardcode state[0] for capture, [1] for playback + */ + if(file->f_mode & FMODE_READ) + { + CS_DBGOUT(CS_WAVE_READ, 2, printk("cs46xx: cs_open() FMODE_READ\n") ); + if (card->states[0] == NULL) { + state = card->states[0] = (struct cs_state *) + kmalloc(sizeof(struct cs_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + memset(state, 0, sizeof(struct cs_state)); + dmabuf = &state->dmabuf; + dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL | GFP_DMA); + if(dmabuf->pbuf==NULL) + { + kfree(state); + card->states[0]=NULL; + return -ENOMEM; } } - card = card->next; - } - /* no more virtual channel avaiable */ - if (!state) - return -ENODEV; - - found_virt: - /* found a free virtual channel, allocate hardware channels */ - if(file->f_mode & FMODE_READ) + else + { + state = card->states[0]; + if(state->open_mode & FMODE_READ) + return -EBUSY; + } dmabuf->channel = card->alloc_rec_pcm_channel(card); - else - dmabuf->channel = card->alloc_pcm_channel(card); + + if (dmabuf->channel == NULL) { + kfree (card->states[0]); + card->states[0] = NULL;; + return -ENODEV; + } + + /* Now turn on external AMP if needed */ + state->card = card; + state->card->active_ctrl(state->card,1); + state->card->amplifier_ctrl(state->card,1); - if (dmabuf->channel == NULL) { - kfree (card->states[i]); - card->states[i] = NULL;; - return -ENODEV; - } + dmabuf->channel->state = state; + /* initialize the virtual channel */ + state->virt = 0; + state->magic = CS_STATE_MAGIC; + init_waitqueue_head(&dmabuf->wait); + init_MUTEX(&state->open_sem); + file->private_data = card; + + down(&state->open_sem); + + /* set default sample format. According to OSS Programmer's Guide /dev/dsp + should be default to unsigned 8-bits, mono, with sample rate 8kHz and + /dev/dspW will accept 16-bits sample */ - /* Now turn on external AMP if needed */ - state->card = card; - state->card->active_ctrl(state->card,1); - state->card->amplifier_ctrl(state->card,1); - - dmabuf->channel->state = state; - /* initialize the virtual channel */ - state->virt = i; - state->magic = CS_STATE_MAGIC; - init_waitqueue_head(&dmabuf->wait); - init_MUTEX(&state->open_sem); - file->private_data = state; - - down(&state->open_sem); - - /* set default sample format. According to OSS Programmer's Guide /dev/dsp - should be default to unsigned 8-bits, mono, with sample rate 8kHz and - /dev/dspW will accept 16-bits sample */ - if (file->f_mode & FMODE_WRITE) { - /* Output is 16bit only mono or stereo */ + /* Default input is 8bit mono */ dmabuf->fmt &= ~CS_FMT_MASK; - dmabuf->fmt |= CS_FMT_16BIT; + dmabuf->type = CS_TYPE_ADC; dmabuf->ossfragshift = 0; dmabuf->ossmaxfrags = 0; dmabuf->subdivision = 0; - cs_set_dac_rate(state, 8000); + cs_set_adc_rate(state, 8000); + cs_set_divisor(dmabuf); + + state->open_mode |= FMODE_READ; + up(&state->open_sem); + MOD_INC_USE_COUNT; } + if(file->f_mode & FMODE_WRITE) + { + CS_DBGOUT(CS_OPEN, 2, printk("cs46xx: cs_open() FMODE_WRITE\n") ); + if (card->states[1] == NULL) { + state = card->states[1] = (struct cs_state *) + kmalloc(sizeof(struct cs_state), GFP_KERNEL); + if (state == NULL) + return -ENOMEM; + memset(state, 0, sizeof(struct cs_state)); + dmabuf = &state->dmabuf; + dmabuf->pbuf = (void *)get_free_page(GFP_KERNEL | GFP_DMA); + if(dmabuf->pbuf==NULL) + { + kfree(state); + card->states[1]=NULL; + return -ENOMEM; + } + } + else + { + state = card->states[1]; + if(state->open_mode & FMODE_WRITE) + return -EBUSY; + } + dmabuf->channel = card->alloc_pcm_channel(card); + + if (dmabuf->channel == NULL) { + kfree (card->states[1]); + card->states[1] = NULL;; + return -ENODEV; + } - if (file->f_mode & FMODE_READ) { - /* Input is 16bit stereo only */ + /* Now turn on external AMP if needed */ + state->card = card; + state->card->active_ctrl(state->card,1); + state->card->amplifier_ctrl(state->card,1); + + dmabuf->channel->state = state; + /* initialize the virtual channel */ + state->virt = 1; + state->magic = CS_STATE_MAGIC; + init_waitqueue_head(&dmabuf->wait); + init_MUTEX(&state->open_sem); + file->private_data = card; + + down(&state->open_sem); + + /* set default sample format. According to OSS Programmer's Guide /dev/dsp + should be default to unsigned 8-bits, mono, with sample rate 8kHz and + /dev/dspW will accept 16-bits sample */ + + /* Default output is 8bit mono. */ dmabuf->fmt &= ~CS_FMT_MASK; - dmabuf->fmt |= CS_FMT_16BIT|CS_FMT_STEREO; + dmabuf->type = CS_TYPE_DAC; dmabuf->ossfragshift = 0; dmabuf->ossmaxfrags = 0; dmabuf->subdivision = 0; - cs_set_adc_rate(state, 8000); - } - - state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&state->open_sem); + cs_set_dac_rate(state, 8000); + cs_set_divisor(dmabuf); + state->open_mode |= FMODE_WRITE; + up(&state->open_sem); + MOD_INC_USE_COUNT; + if((ret = prog_dmabuf(state))) + return ret; + } - MOD_INC_USE_COUNT; + CS_DBGOUT(CS_OPEN | CS_FUNCTION, 2, printk("cs46xx: cs_open()- 0\n") ); return 0; } static int cs_release(struct inode *inode, struct file *file) { - struct cs_state *state = (struct cs_state *)file->private_data; - struct dmabuf *dmabuf = &state->dmabuf; + struct cs_card *card = (struct cs_card *)file->private_data; + struct dmabuf *dmabuf; + struct cs_state *state; + CS_DBGOUT(CS_RELEASE | CS_FUNCTION, 2, printk("cs46xx: cs_release()+ file=0x%x %s %s\n", + (unsigned)file, file->f_mode & FMODE_WRITE ? "FMODE_WRITE" : "", + file->f_mode & FMODE_READ ? "FMODE_READ" : "") ); - if (file->f_mode & FMODE_WRITE) { - /* FIXME :.. */ - cs_clear_tail(state); - drain_dac(state, file->f_flags & O_NONBLOCK); + if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) + { + return -EINVAL; } + state = card->states[1]; + if(state) + { + if ( (state->open_mode & FMODE_WRITE) & (file->f_mode & FMODE_WRITE) ) + { + CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_WRITE\n") ); + dmabuf = &state->dmabuf; + cs_clear_tail(state); + drain_dac(state, file->f_flags & O_NONBLOCK); + /* stop DMA state machine and free DMA buffers/channels */ + down(&state->open_sem); + stop_dac(state); + dealloc_dmabuf(state); + state->card->free_pcm_channel(state->card, dmabuf->channel->num); + free_page((unsigned long)state->dmabuf.pbuf); + + /* we're covered by the open_sem */ + up(&state->open_sem); + state->card->states[state->virt] = NULL; + state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + + /* Now turn off external AMP if needed */ + state->card->amplifier_ctrl(state->card, -1); + state->card->active_ctrl(state->card, -1); - /* stop DMA state machine and free DMA buffers/channels */ - down(&state->open_sem); - - if (file->f_mode & FMODE_WRITE) { - stop_dac(state); - dealloc_dmabuf(state); - state->card->free_pcm_channel(state->card, dmabuf->channel->num); - } - if (file->f_mode & FMODE_READ) { - stop_adc(state); - dealloc_dmabuf(state); - state->card->free_pcm_channel(state->card, dmabuf->channel->num); + kfree(state); + } + MOD_DEC_USE_COUNT; } - free_page((unsigned long)state->dmabuf.pbuf); - - /* we're covered by the open_sem */ - up(&state->open_sem); - state->card->states[state->virt] = NULL; - state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + state = card->states[0]; + if(state) + { + if ( (state->open_mode & FMODE_READ) & (file->f_mode & FMODE_READ) ) + { + CS_DBGOUT(CS_RELEASE, 2, printk("cs46xx: cs_release() FMODE_READ\n") ); + dmabuf = &state->dmabuf; + down(&state->open_sem); + stop_adc(state); + dealloc_dmabuf(state); + state->card->free_pcm_channel(state->card, dmabuf->channel->num); + free_page((unsigned long)state->dmabuf.pbuf); + + /* we're covered by the open_sem */ + up(&state->open_sem); + state->card->states[state->virt] = NULL; + state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE); + + /* Now turn off external AMP if needed */ + state->card->amplifier_ctrl(state->card, -1); + state->card->active_ctrl(state->card, -1); - /* Now turn off external AMP if needed */ - state->card->amplifier_ctrl(state->card, -1); - state->card->active_ctrl(state->card, -1); + kfree(state); + } + MOD_DEC_USE_COUNT; + } - kfree(state); - MOD_DEC_USE_COUNT; + CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk("cs46xx: cs_release()- 0\n") ); return 0; } @@ -1841,6 +3257,12 @@ { struct cs_card *card = dev->private_data; int count; + int val2 = 0; + + if(reg == AC97_CD_VOL) + { + val2 = cs_ac97_get(dev, AC97_CD_VOL); + } /* * 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address @@ -1883,6 +3305,47 @@ */ if (cs461x_peekBA0(card, BA0_ACCTL) & ACCTL_DCV) printk(KERN_WARNING "cs461x: AC'97 write problem, reg = 0x%x, val = 0x%x\n", reg, val); + + /* + * Adjust power if the mixer is selected/deselected according + * to the CD. + * + * IF the CD is a valid input source (mixer or direct) AND + * the CD is not muted THEN power is needed + * + * We do two things. When record select changes the input to + * add/remove the CD we adjust the power count if the CD is + * unmuted. + * + * When the CD mute changes we adjust the power level if the + * CD was a valid input. + * + * We also check for CD volume != 0, as the CD mute isn't + * normally tweaked from userspace. + */ + + /* CD mute change ? */ + + if(reg==AC97_CD_VOL) + { + /* Mute bit change ? */ + if((val2^val)&0x8000 || ((val2 == 0x1f1f || val == 0x1f1f) && val2 != val)) + { + /* This is a hack but its cleaner than the alternatives. + Right now card->ac97_codec[0] might be NULL as we are + still doing codec setup. This does an early assignment + to avoid the problem if it occurs */ + + if(card->ac97_codec[0]==NULL) + card->ac97_codec[0]=dev; + + /* Mute on */ + if(val&0x8000 || val == 0x1f1f) + card->amplifier_ctrl(card, -1); + else /* Mute off power on */ + card->amplifier_ctrl(card, 1); + } + } } @@ -1916,7 +3379,7 @@ int minor = MINOR(inode->i_rdev); struct cs_card *card = devs; int i; - + for (card = devs; card != NULL; card = card->next) for (i = 0; i < NR_AC97; i++) if (card->ac97_codec[i] != NULL && @@ -1927,7 +3390,6 @@ return -ENODEV; match: card->active_ctrl(card, -1); - MOD_DEC_USE_COUNT; return 0; } @@ -1937,6 +3399,41 @@ { struct ac97_codec *codec = (struct ac97_codec *)file->private_data; +#if CSDEBUG_INTERFACE + int val; + + if( (cmd == SOUND_MIXER_CS_GETDBGMASK) || + (cmd == SOUND_MIXER_CS_SETDBGMASK) || + (cmd == SOUND_MIXER_CS_GETDBGLEVEL) || + (cmd == SOUND_MIXER_CS_SETDBGLEVEL) ) + { + switch(cmd) + { + + case SOUND_MIXER_CS_GETDBGMASK: + return put_user(cs_debugmask, (unsigned long *)arg); + + case SOUND_MIXER_CS_GETDBGLEVEL: + return put_user(cs_debuglevel, (unsigned long *)arg); + + case SOUND_MIXER_CS_SETDBGMASK: + if (get_user(val, (unsigned long *)arg)) + return -EFAULT; + cs_debugmask = val; + return 0; + + case SOUND_MIXER_CS_SETDBGLEVEL: + if (get_user(val, (unsigned long *)arg)) + return -EFAULT; + cs_debuglevel = val; + return 0; + default: + CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO + "cs4281: mixer_ioctl(): ERROR unknown debug cmd\n") ); + return 0; + } + } +#endif return codec->mixer_ioctl(codec, cmd, arg); } @@ -1981,7 +3478,6 @@ } card->ac97_features = eid; - if ((codec->dev_mixer = register_sound_mixer(&cs_mixer_fops, -1)) < 0) { printk(KERN_ERR "cs461x: couldn't register mixer!\n"); @@ -1998,47 +3494,35 @@ return num_ac97; } -/* Boot the card +/* + * load the static image into the DSP */ - -static void __init cs461x_download(struct cs_card *card, u32 *src, unsigned long offset, unsigned long len) -{ - unsigned long counter; - void *dst; - - dst = card->ba1.idx[(offset>>16)&3]; - dst += (offset&0xFFFF)<<2; - for(counter=0;counter> 2; - } + unsigned i, j, temp1, temp2, offset, count; + unsigned char *pBA1 = ioremap(card->ba1_addr, 0x40000); + for( i=0; i < CLEAR__COUNT; i++) + { + offset = ClrStat[i].BA1__DestByteOffset; + count = ClrStat[i].BA1__SourceSize; + for( temp1 = offset; temp1<(offset+count); temp1+=4 ); + writel(0, pBA1+temp1); + } + + for(i=0; idata; + + if (state) { + switch(rqst) { + case PM_RESUME: + printk( KERN_DEBUG "cs46xx: PM resume request\n"); + cs_hardware_init(state->card); + break; + case PM_SUSPEND: + printk( KERN_DEBUG "cs46xx: PM suspend request\n"); + stop_dac(state); + resync_dma_ptrs(state); + break; + } + } + +return 0; +} +#endif + static int __init cs_install(struct pci_dev *pci_dev) { struct cs_card *card; struct cs_card_type *cp = &cards[0]; +#ifdef CS46XX_PM + struct pm_dev *pmdev; +#endif u16 ss_card, ss_vendor; - - + + pci_read_config_word(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor); pci_read_config_word(pci_dev, PCI_SUBSYSTEM_ID, &ss_card); @@ -2526,8 +4036,8 @@ card->free_pcm_channel = cs_free_pcm_channel; card->amplifier_ctrl = amp_none; card->active_ctrl = amp_none; - - while(cp->name) + + while (cp->name) { if(cp->vendor == ss_vendor && cp->id == ss_card) { @@ -2538,38 +4048,37 @@ } cp++; } - if(cp->name==NULL) + if (cp->name==NULL) { - printk(KERN_INFO "cs461x: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n", - ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq); + printk(KERN_INFO "cs461x: Unknown card (%04X:%04X) at 0x%08lx/0x%08lx, IRQ %d\n", + ss_vendor, ss_card, card->ba0_addr, card->ba1_addr, card->irq); } else { printk(KERN_INFO "cs461x: %s at 0x%08lx/0x%08lx, IRQ %d\n", cp->name, card->ba0_addr, card->ba1_addr, card->irq); } - - if(card->amplifier_ctrl==NULL) + + if (card->amplifier_ctrl==NULL) { - printk(KERN_ERR "cs461x: Unsupported configuration due to lack of documentation.\n"); - kfree(card); - return -EINVAL; - } - - if(external_amp == 1) + card->amplifier_ctrl = amp_none; + card->active_ctrl = clkrun_hack; + } + + if (external_amp == 1) { printk(KERN_INFO "cs461x: Crystal EAPD support forced on.\n"); card->amplifier_ctrl = amp_voyetra; } - if(thinkpad == 1) + if (thinkpad == 1) { card->active_ctrl = clkrun_hack; printk(KERN_INFO "cs461x: Activating CLKRUN hack for Thinkpad.\n"); } - + card->active_ctrl(card, 1); - + /* claim our iospace and irq */ card->ba0 = ioremap(card->ba0_addr, CS461X_BA0_SIZE); @@ -2578,6 +4087,13 @@ card->ba1.name.pmem = ioremap(card->ba1_addr + BA1_SP_PMEM, CS461X_BA1_PRG_SIZE); card->ba1.name.reg = ioremap(card->ba1_addr + BA1_SP_REG, CS461X_BA1_REG_SIZE); + CS_DBGOUT(CS_INIT, 4, printk("card->ba0=0x%.08x\n",(unsigned)card->ba0) ); + CS_DBGOUT(CS_INIT, 4, printk("card->ba1=0x%.08x 0x%.08x 0x%.08x 0x%.08x\n", + (unsigned)card->ba1.name.data0, + (unsigned)card->ba1.name.data1, + (unsigned)card->ba1.name.pmem, + (unsigned)card->ba1.name.reg) ); + if(card->ba0 == 0 || card->ba1.name.data0 == 0 || card->ba1.name.data1 == 0 || card->ba1.name.pmem == 0 || card->ba1.name.reg == 0) @@ -2593,17 +4109,34 @@ goto fail; } - if (cs_hardware_init(card)<0) - { - unregister_sound_dsp(card->dev_audio); - goto fail; - } - card->next = devs; - devs = card; - - card->active_ctrl(card, -1); - return 0; - + /* register /dev/midi */ + if((card->dev_midi = register_sound_midi(&cs_midi_fops, -1)) < 0) + printk(KERN_ERR "cs461x: unable to register midi\n"); + + if (cs_hardware_init(card)<0) + { + unregister_sound_dsp(card->dev_audio); + if(card->dev_midi) + unregister_sound_midi(card->dev_midi); + goto fail; + } + init_waitqueue_head(&card->midi.open_wait); + init_MUTEX(&card->midi.open_sem); + init_waitqueue_head(&card->midi.iwait); + init_waitqueue_head(&card->midi.owait); + card->next = devs; + devs = card; + cs461x_pokeBA0(card, BA0_MIDCR, MIDCR_MRST); + cs461x_pokeBA0(card, BA0_MIDCR, 0); + + card->active_ctrl(card, -1); +#ifdef CS46XX_PM + pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(pci_dev), cs46xx_pm_callback); + if (pmdev) + pmdev->data = card; +#endif + return 0; + fail: free_irq(card->irq, card); fail2: @@ -2628,7 +4161,7 @@ unsigned int tmp; card->active_ctrl(card,1); - + tmp = cs461x_peek(card, BA1_PFIE); tmp &= ~0x0000f03f; tmp |= 0x00000010; @@ -2693,10 +4226,12 @@ kfree (card->ac97_codec[i]); } unregister_sound_dsp(card->dev_audio); + if(card->dev_midi) + unregister_sound_midi(card->dev_midi); kfree(card); } -MODULE_AUTHOR("Alan Cox , Jaroslav Kysela"); +MODULE_AUTHOR("Alan Cox , Jaroslav Kysela, "); MODULE_DESCRIPTION("Crystal SoundFusion Audio Support"); int __init cs_probe(void) @@ -2728,18 +4263,19 @@ return foundone; } -#ifdef MODULE - -int init_module(void) +int __init init_module(void) { if(cs_probe()==0) printk(KERN_ERR "cs461x: No devices found.\n"); return 0; } -void cleanup_module (void) +void __exit cleanup_module (void) { struct cs_card *next; +#ifdef CS46XX_PM + pm_unregister_all(cs46xx_pm_callback); +#endif while(devs) { next=devs->next; @@ -2750,5 +4286,3 @@ MODULE_PARM(external_amp, "i"); MODULE_PARM(thinkpad, "i"); - -#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/dmasound/dmasound_atari.c linux/drivers/sound/dmasound/dmasound_atari.c --- v2.4.0-test11/linux/drivers/sound/dmasound/dmasound_atari.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/dmasound/dmasound_atari.c Mon Nov 27 17:57:34 2000 @@ -816,7 +816,7 @@ static void *AtaAlloc(unsigned int size, int flags) { - return atari_stram_alloc( size, NULL, "dmasound" ); + return atari_stram_alloc(size, "dmasound"); } static void AtaFree(void *obj, unsigned int size) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/dmasound/dmasound_paula.c linux/drivers/sound/dmasound/dmasound_paula.c --- v2.4.0-test11/linux/drivers/sound/dmasound/dmasound_paula.c Tue Apr 25 17:58:46 2000 +++ linux/drivers/sound/dmasound/dmasound_paula.c Mon Nov 27 17:57:34 2000 @@ -27,8 +27,6 @@ /* * The minimum period for audio depends on htotal (for OCS/ECS/AGA) * (Imported from arch/m68k/amiga/amisound.c) - * - * FIXME: if amifb is not used, there should be a method to change htotal */ extern volatile u_short amiga_audio_min_period; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.4.0-test11/linux/drivers/sound/es1370.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/es1370.c Tue Nov 28 22:41:34 2000 @@ -116,6 +116,7 @@ * 08.01.2000 0.32 Prevent some ioctl's from returning bad count values on underrun/overrun; * Tim Janik's BSE (Bedevilled Sound Engine) found this * 07.02.2000 0.33 Use pci_alloc_consistent and pci_register_driver + * 21.11.2000 0.34 Initialize dma buffers in poll, otherwise poll may return a bogus mask * * some important things missing in Ensoniq documentation: * @@ -1280,10 +1281,16 @@ unsigned int mask = 0; VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + if (!s->dma_dac2.ready && prog_dmabuf_dac2(s)) + return 0; poll_wait(file, &s->dma_dac2.wait, wait); - if (file->f_mode & FMODE_READ) + } + if (file->f_mode & FMODE_READ) { + if (!s->dma_adc.ready && prog_dmabuf_adc(s)) + return 0; poll_wait(file, &s->dma_adc.wait, wait); + } spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); if (file->f_mode & FMODE_READ) { @@ -1855,6 +1862,8 @@ unsigned int mask = 0; VALIDATE_STATE(s); + if (!s->dma_dac1.ready && prog_dmabuf_dac1(s)) + return 0; poll_wait(file, &s->dma_dac1.wait, wait); spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); @@ -2655,7 +2664,7 @@ { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.33 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.34 time " __TIME__ " " __DATE__ "\n"); return pci_module_init(&es1370_driver); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c --- v2.4.0-test11/linux/drivers/sound/es1371.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/es1371.c Tue Nov 28 22:41:34 2000 @@ -101,6 +101,7 @@ * 07.02.2000 0.25 Use ac97_codec * 01.03.2000 0.26 SPDIF patch by Mikael Bouillot * Use pci_module_init + * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask */ /*****************************************************************************/ @@ -1463,10 +1464,16 @@ unsigned int mask = 0; VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + if (!s->dma_dac2.ready && prog_dmabuf_dac2(s)) + return 0; poll_wait(file, &s->dma_dac2.wait, wait); - if (file->f_mode & FMODE_READ) + } + if (file->f_mode & FMODE_READ) { + if (!s->dma_adc.ready && prog_dmabuf_adc(s)) + return 0; poll_wait(file, &s->dma_adc.wait, wait); + } spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); if (file->f_mode & FMODE_READ) { @@ -2035,6 +2042,8 @@ unsigned int mask = 0; VALIDATE_STATE(s); + if (!s->dma_dac1.ready && prog_dmabuf_dac1(s)) + return 0; poll_wait(file, &s->dma_dac1.wait, wait); spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); @@ -2927,7 +2936,7 @@ { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO PFX "version v0.26 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO PFX "version v0.27 time " __TIME__ " " __DATE__ "\n"); return pci_module_init(&es1371_driver); } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.4.0-test11/linux/drivers/sound/esssolo1.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/esssolo1.c Tue Nov 28 22:41:34 2000 @@ -69,6 +69,7 @@ * 07.02.2000 0.13 Use pci_alloc_consistent and pci_register_driver * 19.02.2000 0.14 Use pci_dma_supported to determine if recording should be disabled * 13.03.2000 0.15 Reintroduce initialization of a couple of PCI config space registers + * 21.11.2000 0.16 Initialize dma buffers in poll, otherwise poll may return a bogus mask */ /*****************************************************************************/ @@ -1168,10 +1169,16 @@ unsigned int mask = 0; VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + if (!s->dma_dac.ready && prog_dmabuf_dac(s)) + return 0; poll_wait(file, &s->dma_dac.wait, wait); - if (file->f_mode & FMODE_READ) + } + if (file->f_mode & FMODE_READ) { + if (!s->dma_adc.ready && prog_dmabuf_adc(s)) + return 0; poll_wait(file, &s->dma_adc.wait, wait); + } spin_lock_irqsave(&s->lock, flags); solo1_update_ptr(s); if (file->f_mode & FMODE_READ) { @@ -2384,7 +2391,7 @@ { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "solo1: version v0.15 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "solo1: version v0.16 time " __TIME__ " " __DATE__ "\n"); if (!pci_register_driver(&solo1_driver)) { pci_unregister_driver(&solo1_driver); return -ENODEV; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- v2.4.0-test11/linux/drivers/sound/maestro.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/maestro.c Sun Dec 3 17:45:23 2000 @@ -115,6 +115,8 @@ * themselves, but we'll see. * * History + * (still kind of v0.14) Nov 23 - Alan Cox + * Add clocking= for people with seriously warped hardware * (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz * add __init to maestro_ac97_init() and maestro_install() * (still based on v0.14) Mar 29 2000 - Zach Brown @@ -262,6 +264,10 @@ static int dsps_order=0; /* wether or not we mess around with power management */ static int use_pm=2; /* set to 1 for force */ +/* clocking for broken hardware - a few laptops seem to use a 50Khz clock + ie insmod with clocking=50000 or so */ + +static int clocking=48000; /* --------------------------------------------------------------------- */ #define DRIVER_VERSION "0.14" @@ -1200,7 +1206,10 @@ { u32 clock = clock_freq[s->card->card_type]; - if (freq == 48000) return 0x10000; + freq = (freq * clocking)/48000; + + if (freq == 48000) + return 0x10000; return ((freq / clock) <<16 )+ (((freq % clock) << 16) / clock); @@ -1958,6 +1967,7 @@ static int mixer_ioctl(struct ess_card *card, unsigned int cmd, unsigned long arg) { int i, val=0; + unsigned long flags; VALIDATE_CARD(card); if (cmd == SOUND_MIXER_INFO) { @@ -1990,9 +2000,9 @@ if(!card->mix.recmask_io) { val = 0; } else { - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); val = card->mix.recmask_io(card,1,0); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); } break; @@ -2019,9 +2029,9 @@ return -EINVAL; /* do we ever want to touch the hardware? */ -/* spin_lock(&card->lock); +/* spin_lock_irqsave(&card->lock, flags); val = card->mix.read_mixer(card,i); - spin_unlock(&card->lock);*/ + spin_unlock_irqrestore(&card->lock, flags);*/ val = card->mix.mixer_state[i]; /* M_printk("returned 0x%x for mixer %d\n",val,i);*/ @@ -2046,9 +2056,9 @@ if(!val) return 0; if(! (val &= card->mix.record_sources)) return -EINVAL; - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); card->mix.recmask_io(card,0,val); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); return 0; default: @@ -2057,9 +2067,9 @@ if ( ! supported_mixer(card,i)) return -EINVAL; - spin_lock(&card->lock); + spin_lock_irqsave(&card->lock, flags); set_mixer(card,i,val); - spin_unlock(&card->lock); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -3392,6 +3402,19 @@ ess = &card->channels[0]; + if (pci_enable_device(pcidev)) { + printk (KERN_ERR "maestro: pci_enable_device() failed\n"); + for (i = 0; i < NR_DSPS; i++) { + struct ess_state *s = &card->channels[i]; + if (s->dev_audio != -1) + unregister_sound_dsp(s->dev_audio); + } + release_region(card->iobase, 256); + unregister_reboot_notifier(&maestro_nb); + kfree(card); + return 0; + } + /* * Ok card ready. Begin setup proper */ @@ -3564,6 +3587,7 @@ #endif MODULE_PARM(dsps_order,"i"); MODULE_PARM(use_pm,"i"); +MODULE_PARM(clocking, "i"); void cleanup_module(void) { M_printk("maestro: unloading\n"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.4.0-test11/linux/drivers/sound/sonicvibes.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/sonicvibes.c Tue Nov 28 22:41:34 2000 @@ -87,6 +87,7 @@ * Tim Janik's BSE (Bedevilled Sound Engine) found this * use Martin Mares' pci_assign_resource * 07.02.2000 0.26 Use pci_alloc_consistent and pci_register_driver + * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask * */ @@ -1484,10 +1485,16 @@ unsigned int mask = 0; VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + if (!s->dma_dac.ready && prog_dmabuf(s, 1)) + return 0; poll_wait(file, &s->dma_dac.wait, wait); - if (file->f_mode & FMODE_READ) + } + if (file->f_mode & FMODE_READ) { + if (!s->dma_adc.ready && prog_dmabuf(s, 0)) + return 0; poll_wait(file, &s->dma_adc.wait, wait); + } spin_lock_irqsave(&s->lock, flags); sv_update_ptr(s); if (file->f_mode & FMODE_READ) { @@ -2666,7 +2673,7 @@ { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.26 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.27 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c --- v2.4.0-test11/linux/drivers/sound/sound_core.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/sound_core.c Sun Dec 3 17:45:23 2000 @@ -454,11 +454,8 @@ static struct file_operations soundcore_fops= { -/* owner: THIS_MODULE, * this is a bug: if we have an owner, the kernel - generates a MOD_INC_USE_COUNT - thus - the module cannot be unloaded since the device - is never released here ! - solution: owner - has to be NULL. Patch by Peter Wahl */ + /* We must have an owner or the module locking fails */ + owner: THIS_MODULE, open: soundcore_open, }; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/vwsnd.c linux/drivers/sound/vwsnd.c --- v2.4.0-test11/linux/drivers/sound/vwsnd.c Sun Nov 19 18:44:15 2000 +++ linux/drivers/sound/vwsnd.c Mon Dec 11 13:13:51 2000 @@ -144,6 +144,8 @@ #include #include +#include +#include #include #include #include diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c --- v2.4.0-test11/linux/drivers/sound/ymfpci.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/ymfpci.c Mon Dec 11 13:32:24 2000 @@ -0,0 +1,2385 @@ +/* + * Copyright 1999 Jaroslav Kysela + * Copyright 2000 Alan Cox + * + * Yamaha YMF7xx driver. + * + * This code is a result of high-speed collision + * between ymfpci.c of ALSA and cs46xx.c of Linux. + * -- Pete Zaitcev ; 2000/09/18 + * + * 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. + * + * TODO: + * - Use P44Slot for 44.1 playback. + * - Capture and duplex + * - 96KHz playback for DVD - use pitch of 2.0. + * - uLaw for Sun apps. + * - Retain DMA buffer on close, do not wait the end of frame. + * - Cleanup + * ? merge ymf_pcm and state + * ? pcm interrupt no pointer + * ? underused structure members + * - Remove remaining P3 tags (debug messages). + * - Resolve XXX tagged questions. + * - Cannot play 5133Hz. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "ymfpci.h" + +#define snd_magic_cast(t, p, err) ((t *)(p)) + +/* Channels, such as play and record. I do only play a.t.m. XXX */ +#define NR_HW_CH 1 + +static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd); +static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, + int pair, ymfpci_voice_t **rvoice); +static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice); +static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state); +static int ymf_state_alloc(ymfpci_t *unit, int nvirt); + +static LIST_HEAD(ymf_devs); + +/* + * constants + */ + +static struct pci_device_id ymf_id_tbl[] __devinitdata = { +#define DEV(v, d, data) \ + { PCI_VENDOR_ID_##v, PCI_DEVICE_ID_##v##_##d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)data } + DEV (YAMAHA, 724, "YMF724"), + DEV (YAMAHA, 724F, "YMF724F"), + DEV (YAMAHA, 740, "YMF740"), + DEV (YAMAHA, 740C, "YMF740C"), + DEV (YAMAHA, 744, "YMF744"), + DEV (YAMAHA, 754, "YMF754"), +#undef DEV + { } +}; +MODULE_DEVICE_TABLE(pci, ymf_id_tbl); + +/* + * Mindlessly copied from cs46xx XXX + */ +extern __inline__ unsigned ld2(unsigned int x) +{ + unsigned r = 0; + + if (x >= 0x10000) { + x >>= 16; + r += 16; + } + if (x >= 0x100) { + x >>= 8; + r += 8; + } + if (x >= 0x10) { + x >>= 4; + r += 4; + } + if (x >= 4) { + x >>= 2; + r += 2; + } + if (x >= 2) + r++; + return r; +} + +/* + * common I/O routines + */ + +static inline u8 ymfpci_readb(ymfpci_t *codec, u32 offset) +{ + return readb(codec->reg_area_virt + offset); +} + +static inline void ymfpci_writeb(ymfpci_t *codec, u32 offset, u8 val) +{ + writeb(val, codec->reg_area_virt + offset); +} + +static inline u16 ymfpci_readw(ymfpci_t *codec, u32 offset) +{ + return readw(codec->reg_area_virt + offset); +} + +static inline void ymfpci_writew(ymfpci_t *codec, u32 offset, u16 val) +{ + writew(val, codec->reg_area_virt + offset); +} + +static inline u32 ymfpci_readl(ymfpci_t *codec, u32 offset) +{ + return readl(codec->reg_area_virt + offset); +} + +static inline void ymfpci_writel(ymfpci_t *codec, u32 offset, u32 val) +{ + writel(val, codec->reg_area_virt + offset); +} + +static int ymfpci_codec_ready(ymfpci_t *codec, int secondary, int sched) +{ + signed long end_time; + u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; + + end_time = jiffies + 3 * (HZ / 4); + do { + if ((ymfpci_readw(codec, reg) & 0x8000) == 0) + return 0; + if (sched) { + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout(1); + } + } while (end_time - (signed long)jiffies >= 0); + printk("ymfpci_codec_ready: codec %i is not ready [0x%x]\n", + secondary, ymfpci_readw(codec, reg)); + return -EBUSY; +} + +static void ymfpci_codec_write(struct ac97_codec *dev, u8 reg, u16 val) +{ + ymfpci_t *codec = dev->private_data; + u32 cmd; + + /* XXX Do make use of dev->id */ + ymfpci_codec_ready(codec, 0, 0); + cmd = ((YDSXG_AC97WRITECMD | reg) << 16) | val; + ymfpci_writel(codec, YDSXGR_AC97CMDDATA, cmd); +} + +static u16 ymfpci_codec_read(struct ac97_codec *dev, u8 reg) +{ + ymfpci_t *codec = dev->private_data; + + if (ymfpci_codec_ready(codec, 0, 0)) + return ~0; + ymfpci_writew(codec, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg); + if (ymfpci_codec_ready(codec, 0, 0)) + return ~0; + if (codec->pci->device == PCI_DEVICE_ID_YAMAHA_744 && codec->rev < 2) { + int i; + for (i = 0; i < 600; i++) + ymfpci_readw(codec, YDSXGR_PRISTATUSDATA); + } + return ymfpci_readw(codec, YDSXGR_PRISTATUSDATA); +} + +/* + * Misc routines + */ + +/* + * Calculate the actual sampling rate relatetively to the base clock (48kHz). + */ +static u32 ymfpci_calc_delta(u32 rate) +{ + switch (rate) { + case 8000: return 0x02aaab00; + case 11025: return 0x03accd00; + case 16000: return 0x05555500; + case 22050: return 0x07599a00; + case 32000: return 0x0aaaab00; + case 44100: return 0x0eb33300; + default: return ((rate << 16) / 48000) << 12; + } +} + +static u32 def_rate[8] = { + 100, 2000, 8000, 11025, 16000, 22050, 32000, 48000 +}; + +static u32 ymfpci_calc_lpfK(u32 rate) +{ + u32 i; + static u32 val[8] = { + 0x00570000, 0x06AA0000, 0x18B20000, 0x20930000, + 0x2B9A0000, 0x35A10000, 0x3EAA0000, 0x40000000 + }; + + if (rate == 44100) + return 0x40000000; /* FIXME: What's the right value? */ + for (i = 0; i < 8; i++) + if (rate <= def_rate[i]) + return val[i]; + return val[0]; +} + +static u32 ymfpci_calc_lpfQ(u32 rate) +{ + u32 i; + static u32 val[8] = { + 0x35280000, 0x34A70000, 0x32020000, 0x31770000, + 0x31390000, 0x31C90000, 0x33D00000, 0x40000000 + }; + + if (rate == 44100) + return 0x370A0000; + for (i = 0; i < 8; i++) + if (rate <= def_rate[i]) + return val[i]; + return val[0]; +} + +static u32 ymf_calc_lend(u32 rate) +{ + return (rate * YMF_SAMPF) / 48000; +} + +/* + * XXX Find if this function exists in the OSS framework. + * XXX Make sure we do no panic when ADPCM is selected. + */ +static int ymf_pcm_format_width(int format) +{ + static int mask16 = AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE; + + if ((format & (format-1)) != 0) { + printk(KERN_ERR "ymfpci: format 0x%x is not a power of 2\n", format); + return 8; + } + + if (format == AFMT_IMA_ADPCM) return 4; + if ((format & mask16) != 0) return 16; + return 8; +} + +static void ymf_pcm_update_shift(struct ymf_pcm_format *f) +{ + f->shift = 0; + if (f->voices == 2) + f->shift++; + if (ymf_pcm_format_width(f->format) == 16) + f->shift++; +} + +/* + * Whole OSS-style DMA machinery is taken from cs46xx. + */ + +/* Are you sure 32K is not too much? See if mpg123 skips on loaded systems. */ +#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) +#define DMABUF_MINORDER 1 + +/* allocate DMA buffer, playback and recording buffer should be allocated seperately */ +static int alloc_dmabuf(struct ymf_state *state) +{ + struct ymf_dmabuf *dmabuf = &state->dmabuf; + void *rawbuf = NULL; + int order; + struct page * map, * mapend; + + /* alloc as big a chunk as we can */ + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) + if((rawbuf = (void *)__get_free_pages(GFP_KERNEL|GFP_DMA, order))) + break; + + if (!rawbuf) + return -ENOMEM; + +#if 0 + printk(KERN_DEBUG "ymfpci: allocated %ld (order = %d) bytes at %p\n", + PAGE_SIZE << order, order, rawbuf); +#endif + + dmabuf->ready = dmabuf->mapped = 0; + dmabuf->rawbuf = rawbuf; + dmabuf->buforder = order; + + /* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */ + mapend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); + for (map = virt_to_page(rawbuf); map <= mapend; map++) + set_bit(PG_reserved, &map->flags); + + return 0; +} + +/* free DMA buffer */ +static void dealloc_dmabuf(struct ymf_state *state) +{ + struct ymf_dmabuf *dmabuf = &state->dmabuf; + struct page *map, *mapend; + + if (dmabuf->rawbuf) { + /* undo marking the pages as reserved */ + mapend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); + for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) + clear_bit(PG_reserved, &map->flags); + free_pages((unsigned long)dmabuf->rawbuf,dmabuf->buforder); + } + dmabuf->rawbuf = NULL; + dmabuf->mapped = dmabuf->ready = 0; +} + +static int prog_dmabuf(struct ymf_state *state, unsigned rec) +{ + struct ymf_dmabuf *dmabuf = &state->dmabuf; + int w_16; + unsigned bytepersec; + unsigned bufsize; + unsigned long flags; + int redzone; + int ret; + + w_16 = ymf_pcm_format_width(state->format.format) == 16; + + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->hwptr = dmabuf->swptr = 0; + dmabuf->total_bytes = 0; + dmabuf->count = dmabuf->error = 0; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + + /* allocate DMA buffer if not allocated yet */ + if (!dmabuf->rawbuf) + if ((ret = alloc_dmabuf(state))) + return ret; + + bytepersec = state->format.rate << state->format.shift; + + /* + * Create fake fragment sizes and numbers for OSS ioctls. + */ + bufsize = PAGE_SIZE << dmabuf->buforder; + if (dmabuf->ossfragshift) { + if ((1000 << dmabuf->ossfragshift) < bytepersec) + dmabuf->fragshift = ld2(bytepersec/1000); + else + dmabuf->fragshift = dmabuf->ossfragshift; + } else { + /* lets hand out reasonable big ass buffers by default */ + dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT -2); + } + dmabuf->numfrag = bufsize >> dmabuf->fragshift; + while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) { + dmabuf->fragshift--; + dmabuf->numfrag = bufsize >> dmabuf->fragshift; + } + dmabuf->fragsize = 1 << dmabuf->fragshift; + dmabuf->fragsamples = dmabuf->fragsize >> state->format.shift; + dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; + + /* + * Import what Doom might have set with SNDCTL_DSD_SETFRAGMENT. + */ + if (dmabuf->ossmaxfrags >= 2 && dmabuf->ossmaxfrags < dmabuf->numfrag) { + dmabuf->numfrag = dmabuf->ossmaxfrags; + dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; + + redzone = ymf_calc_lend(state->format.rate); + redzone <<= (state->format.shift + 1); + if (dmabuf->dmasize < redzone*3) { + /* + * The driver works correctly with minimum dmasize + * of redzone*2, but it produces stoppage and clicks. + * So, make it little larger for smoother sound. + * XXX Make dmasize a wholy divisible by fragsize. + */ +// printk(KERN_ERR "ymfpci: dmasize=%d < redzone=%d * 3\n", +// dmabuf->dmasize, redzone); + dmabuf->dmasize = redzone*3; + } + } + + memset(dmabuf->rawbuf, w_16 ? 0 : 0x80, dmabuf->dmasize); + + /* + * Now set up the ring + */ + + spin_lock_irqsave(&state->unit->reg_lock, flags); + if (rec) { + /* ymf_rec_setup(state); */ + } else { + if ((ret = ymf_playback_prepare(state->unit, state)) != 0) { + return ret; + } + } + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + + /* set the ready flag for the dma buffer (this comment is not stupid) */ + dmabuf->ready = 1; + +#if 0 + printk("prog_dmabuf: rate %d format 0x%x," + " numfrag %d fragsize %d dmasize %d\n", + state->format.rate, state->format.format, dmabuf->numfrag, + dmabuf->fragsize, dmabuf->dmasize); +#endif + + return 0; +} + +static void ymf_start_dac(struct ymf_state *state) +{ + ymf_playback_trigger(state->unit, &state->ypcm, 1); +} + +/* + * Wait until output is drained. + * This does not kill the hardware for the sake of ioctls. + */ +static void ymf_wait_dac(struct ymf_state *state) +{ + struct ymf_unit *unit = state->unit; + ymfpci_pcm_t *ypcm = &state->ypcm; + DECLARE_WAITQUEUE(waita, current); + unsigned long flags; + + add_wait_queue(&state->dmabuf.wait, &waita); + + spin_lock_irqsave(&unit->reg_lock, flags); + if (state->dmabuf.count != 0 && !state->ypcm.running) { + ymf_playback_trigger(unit, ypcm, 1); + } + +#if 0 + if (file->f_flags & O_NONBLOCK) { + /* + * XXX Our mistake is to attach DMA buffer to state + * rather than to some per-device structure. + * Cannot skip waiting, can only make it shorter. + */ + } +#endif + + while (ypcm->running) { + spin_unlock_irqrestore(&unit->reg_lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule(); + spin_lock_irqsave(&unit->reg_lock, flags); + } + spin_unlock_irqrestore(&unit->reg_lock, flags); + + set_current_state(TASK_RUNNING); + remove_wait_queue(&state->dmabuf.wait, &waita); + + /* + * This function may take up to 4 seconds to reach this point + * (32K circular buffer, 8000 Hz). User notices. + */ +} + +/* + * Hardware start management + */ + +static void ymfpci_hw_start(ymfpci_t *codec) +{ + unsigned long flags; + + spin_lock_irqsave(&codec->reg_lock, flags); + if (codec->start_count++ == 0) { + ymfpci_writel(codec, YDSXGR_MODE, 3); + codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1; + } + spin_unlock_irqrestore(&codec->reg_lock, flags); +} + +static void ymfpci_hw_stop(ymfpci_t *codec) +{ + unsigned long flags; + long timeout = 1000; + + spin_lock_irqsave(&codec->reg_lock, flags); + if (--codec->start_count == 0) { + ymfpci_writel(codec, YDSXGR_MODE, 0); + while (timeout-- > 0) { + if ((ymfpci_readl(codec, YDSXGR_STATUS) & 2) == 0) + break; + } + } + spin_unlock_irqrestore(&codec->reg_lock, flags); +} + +/* + * Playback voice management + */ + +static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfpci_voice_t **rvoice) +{ + ymfpci_voice_t *voice, *voice2; + int idx; + + *rvoice = NULL; + for (idx = 0; idx < 64; idx += pair ? 2 : 1) { + voice = &codec->voices[idx]; + voice2 = pair ? &codec->voices[idx+1] : NULL; + if (voice->use || (voice2 && voice2->use)) + continue; + voice->use = 1; + if (voice2) + voice2->use = 1; + switch (type) { + case YMFPCI_PCM: + voice->pcm = 1; + if (voice2) + voice2->pcm = 1; + break; + case YMFPCI_SYNTH: + voice->synth = 1; + break; + case YMFPCI_MIDI: + voice->midi = 1; + break; + } + ymfpci_hw_start(codec); + if (voice2) + ymfpci_hw_start(codec); + *rvoice = voice; + return 0; + } + return -ENOMEM; +} + +static int ymfpci_voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, + int pair, ymfpci_voice_t **rvoice) +{ + unsigned long flags; + int result; + + spin_lock_irqsave(&codec->voice_lock, flags); + for (;;) { + result = voice_alloc(codec, type, pair, rvoice); + if (result == 0 || type != YMFPCI_PCM) + break; + /* TODO: synth/midi voice deallocation */ + break; + } + spin_unlock_irqrestore(&codec->voice_lock, flags); + return result; +} + +static int ymfpci_voice_free(ymfpci_t *codec, ymfpci_voice_t *pvoice) +{ + unsigned long flags; + + ymfpci_hw_stop(codec); + spin_lock_irqsave(&codec->voice_lock, flags); + pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; + pvoice->ypcm = NULL; + pvoice->interrupt = NULL; + spin_unlock_irqrestore(&codec->voice_lock, flags); + return 0; +} + +/* + * PCM part + */ + +static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice) +{ + ymfpci_pcm_t *ypcm; + int redzone; + int pos, delta, swptr; + int played, distance; + struct ymf_state *state; + struct ymf_dmabuf *dmabuf; + char silence; + + if ((ypcm = voice->ypcm) == NULL) { + return; + } + if ((state = ypcm->state) == NULL) { + ypcm->running = 0; // lock it + return; + } + dmabuf = &state->dmabuf; + spin_lock(&codec->reg_lock); + if (ypcm->running) { +/* P3 */ /** printk("ymfpci: %d, intr bank %d count %d start 0x%x:%x\n", + voice->number, codec->active_bank, dmabuf->count, + voice->bank[0].start, voice->bank[1].start); **/ + silence = (ymf_pcm_format_width(state->format.format) == 16) ? + 0 : 0x80; + /* We need actual left-hand-side redzone size here. */ + redzone = ymf_calc_lend(state->format.rate); + redzone <<= (state->format.shift + 1); + swptr = dmabuf->swptr; + + pos = voice->bank[codec->active_bank].start; + pos <<= state->format.shift; + if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */ + printk(KERN_ERR + "ymfpci%d: %d: runaway: hwptr %d dmasize %d\n", + codec->dev_audio, voice->number, + dmabuf->hwptr, dmabuf->dmasize); + pos = 0; + } + if (pos < dmabuf->hwptr) { + delta = dmabuf->dmasize - dmabuf->hwptr; + memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta); + delta += pos; + memset(dmabuf->rawbuf, silence, pos); + } else { + delta = pos - dmabuf->hwptr; + memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta); + } + dmabuf->hwptr = pos; + + if (dmabuf->count == 0) { + printk("ymfpci%d: %d: strain: hwptr %d\n", + codec->dev_audio, voice->number, dmabuf->hwptr); + ymf_playback_trigger(codec, ypcm, 0); + } + + if (swptr <= pos) { + distance = pos - swptr; + } else { + distance = dmabuf->dmasize - (swptr - pos); + } + if (distance < redzone) { + /* + * hwptr inside redzone => DMA ran out of samples. + */ + if (delta < dmabuf->count) { + /* + * Lost interrupt or other screwage. + */ + printk("ymfpci%d: %d: lost: delta %d" + " hwptr %d swptr %d distance %d count %d\n", + codec->dev_audio, voice->number, delta, + dmabuf->hwptr, swptr, distance, dmabuf->count); + } else { + /* + * Normal end of DMA. + */ +// printk("ymfpci%d: %d: done: delta %d" +// " hwptr %d swptr %d distance %d count %d\n", +// codec->dev_audio, voice->number, delta, +// dmabuf->hwptr, swptr, distance, dmabuf->count); + } + played = dmabuf->count; + if (ypcm->running) { + ymf_playback_trigger(codec, ypcm, 0); + } + } else { + /* + * hwptr is chipping away towards a remote swptr. + * Calculate other distance and apply it to count. + */ + if (swptr >= pos) { + distance = swptr - pos; + } else { + distance = dmabuf->dmasize - (pos - swptr); + } + if (distance < dmabuf->count) { + played = dmabuf->count - distance; + } else { + played = 0; + } + } + + dmabuf->total_bytes += played; + dmabuf->count -= played; + if (dmabuf->count < dmabuf->dmasize / 2) { + wake_up(&dmabuf->wait); + } + } + spin_unlock(&codec->reg_lock); +} + +#if HAVE_RECORD +static void ymfpci_pcm_capture_interrupt(snd_pcm_subchn_t *substream) +{ + snd_pcm_runtime_t *runtime = substream->runtime; + ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, ); + ymfpci_t *codec = ypcm->codec; + u32 pos, delta; + + spin_lock(&codec->reg_lock); + if (ypcm->running) { + pos = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset; + if (pos < ypcm->last_pos) // <-- dmabuf->hwptr + delta = pos + (ypcm->buffer_size - ypcm->last_pos); + else + delta = pos - ypcm->last_pos; + ypcm->frag_pos += delta; + ypcm->last_pos = pos; + while (ypcm->frag_pos >= ypcm->frag_size) { + ypcm->frag_pos -= ypcm->frag_size; + // printk("done - active_bank = 0x%x, start = 0x%x\n", codec->active_bank, voice->bank[codec->active_bank].start); + spin_unlock(&codec->reg_lock); + snd_pcm_transfer_done(substream); + spin_lock(&codec->reg_lock); + } + } + spin_unlock(&codec->reg_lock); +} +#endif + +static int ymf_playback_trigger(ymfpci_t *codec, ymfpci_pcm_t *ypcm, int cmd) +{ + + if (ypcm->voices[0] == NULL) { + return -EINVAL; + } + if (cmd != 0) { + codec->ctrl_playback[ypcm->voices[0]->number + 1] = virt_to_bus(ypcm->voices[0]->bank); + if (ypcm->voices[1] != NULL) + codec->ctrl_playback[ypcm->voices[1]->number + 1] = virt_to_bus(ypcm->voices[1]->bank); + ypcm->running = 1; + } else { + codec->ctrl_playback[ypcm->voices[0]->number + 1] = 0; + if (ypcm->voices[1] != NULL) + codec->ctrl_playback[ypcm->voices[1]->number + 1] = 0; + ypcm->running = 0; + } + return 0; +} + +#if HAVE_RECORD +static int ymfpci_capture_trigger(void *private_data, + snd_pcm_subchn_t * substream, + int cmd) +{ + unsigned long flags; + ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO); + ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, substream->runtime->private_data, -ENXIO); + int result = 0; + u32 tmp; + + spin_lock_irqsave(&codec->reg_lock, flags); + if (cmd == SND_PCM_TRIGGER_GO) { + tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) | (1 << ypcm->capture_bank_number); + ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp); + ypcm->running = 1; + } else if (cmd == SND_PCM_TRIGGER_STOP) { + tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) & ~(1 << ypcm->capture_bank_number); + ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp); + ypcm->running = 0; + } else { + result = -EINVAL; + } + spin_unlock_irqrestore(&codec->reg_lock, flags); + return result; +} +#endif + +static int ymfpci_pcm_voice_alloc(ymfpci_pcm_t *ypcm, int voices) +{ + int err; + + if (ypcm->voices[1] != NULL && voices < 2) { + ymfpci_voice_free(ypcm->codec, ypcm->voices[1]); + ypcm->voices[1] = NULL; + } + if (voices == 1 && ypcm->voices[0] != NULL) + return 0; /* already allocated */ + if (voices == 2 && ypcm->voices[0] != NULL && ypcm->voices[1] != NULL) + return 0; /* already allocated */ + if (voices > 1) { + if (ypcm->voices[0] != NULL && ypcm->voices[1] == NULL) { + ymfpci_voice_free(ypcm->codec, ypcm->voices[0]); + ypcm->voices[0] = NULL; + } + } + err = ymfpci_voice_alloc(ypcm->codec, YMFPCI_PCM, voices > 1, &ypcm->voices[0]); + if (err < 0) + return err; + ypcm->voices[0]->ypcm = ypcm; + ypcm->voices[0]->interrupt = ymf_pcm_interrupt; + if (voices > 1) { + ypcm->voices[1] = &ypcm->codec->voices[ypcm->voices[0]->number + 1]; + ypcm->voices[1]->ypcm = ypcm; + } + return 0; +} + +static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo, + int rate, int w_16, unsigned long addr, unsigned int end, int spdif) +{ + u32 format; + u32 delta = ymfpci_calc_delta(rate); + u32 lpfQ = ymfpci_calc_lpfQ(rate); + u32 lpfK = ymfpci_calc_lpfK(rate); + ymfpci_playback_bank_t *bank; + int nbank; + + format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000); + if (stereo) + end >>= 1; + if (w_16) + end >>= 1; +/* P3 */ // printk("ymf_pcm_init_voice: %d: Rate %d Format 0x%08x Delta 0x%x End 0x%x\n", +// voice->number, rate, format, delta, end); + for (nbank = 0; nbank < 2; nbank++) { + bank = &voice->bank[nbank]; + bank->format = format; + bank->loop_default = 0; /* 0-loops forever, otherwise count */ + bank->base = addr; + bank->loop_start = 0; + bank->loop_end = end; + bank->loop_frac = 0; + bank->eg_gain_end = 0x40000000; + bank->lpfQ = lpfQ; + bank->status = 0; + bank->num_of_frames = 0; + bank->loop_count = 0; + bank->start = 0; + bank->start_frac = 0; + bank->delta = + bank->delta_end = delta; + bank->lpfK = + bank->lpfK_end = lpfK; + bank->eg_gain = 0x40000000; + bank->lpfD1 = + bank->lpfD2 = 0; + + bank->left_gain = + bank->right_gain = + bank->left_gain_end = + bank->right_gain_end = + bank->eff1_gain = + bank->eff2_gain = + bank->eff3_gain = + bank->eff1_gain_end = + bank->eff2_gain_end = + bank->eff3_gain_end = 0; + + if (!stereo) { + if (!spdif) { + bank->left_gain = + bank->right_gain = + bank->left_gain_end = + bank->right_gain_end = 0x40000000; + } else { + bank->eff2_gain = + bank->eff2_gain_end = + bank->eff3_gain = + bank->eff3_gain_end = 0x40000000; + } + } else { + if (!spdif) { + if ((voice->number & 1) == 0) { + bank->format |= 1; + bank->left_gain = + bank->left_gain_end = 0x40000000; + } else { + bank->right_gain = + bank->right_gain_end = 0x40000000; + } + } else { + if ((voice->number & 1) == 0) { + bank->format |= 1; + bank->eff2_gain = + bank->eff2_gain_end = 0x40000000; + } else { + bank->eff3_gain = + bank->eff3_gain_end = 0x40000000; + } + } + } + } +} + +/* + * XXX Use new cache coherent PCI DMA routines instead of virt_to_bus. + */ +static int ymf_playback_prepare(ymfpci_t *codec, struct ymf_state *state) +{ + ymfpci_pcm_t *ypcm = &state->ypcm; + int err, nvoice; + + if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) { + /* Cannot be unless we leak voices in ymf_release! */ + printk(KERN_ERR "ymfpci%d: cannot allocate voice!\n", + codec->dev_audio); + return err; + } + + for (nvoice = 0; nvoice < state->format.voices; nvoice++) { + ymf_pcm_init_voice(ypcm->voices[nvoice], + state->format.voices == 2, state->format.rate, + ymf_pcm_format_width(state->format.format) == 16, + virt_to_bus(state->dmabuf.rawbuf), state->dmabuf.dmasize, + ypcm->spdif); + } + return 0; +} + +#if 0 /* old */ +static int ymfpci_capture_prepare(void *private_data, + snd_pcm_subchn_t * substream) +{ + ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO); + snd_pcm_runtime_t *runtime = substream->runtime; + ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO); + ymfpci_capture_bank_t * bank; + int nbank; + u32 rate, format; + + ypcm->frag_size = snd_pcm_lib_transfer_fragment(substream); + ypcm->buffer_size = snd_pcm_lib_transfer_size(substream); + ypcm->frag_pos = 0; + ypcm->last_pos = 0; + ypcm->shift_offset = 0; + rate = ((48000 * 4096) / runtime->format.rate) - 1; + format = 0; + if (runtime->format.voices == 2) + format |= 2; + if (snd_pcm_format_width(runtime->format.format) == 8) + format |= 1; + switch (ypcm->capture_bank_number) { + case 0: + ymfpci_writel(codec, YDSXGR_RECFORMAT, format); + ymfpci_writel(codec, YDSXGR_RECSLOTSR, rate); + break; + case 1: + ymfpci_writel(codec, YDSXGR_ADCFORMAT, format); + ymfpci_writel(codec, YDSXGR_ADCSLOTSR, rate); + break; + } + for (nbank = 0; nbank < 2; nbank++) { + bank = codec->bank_capture[ypcm->capture_bank_number][nbank]; + bank->base = virt_to_bus(runtime->dma_area->buf); + bank->loop_end = ypcm->buffer_size; + bank->start = 0; + bank->num_of_loops = 0; + } + if (runtime->digital.dig_valid) + /*runtime->digital.type == SND_PCM_DIG_AES_IEC958*/ + ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS, runtime->digital.dig_status[0] | + (runtime->digital.dig_status[1] << 8)); + return 0; +} + +static unsigned int ymfpci_playback_pointer(void *private_data, + snd_pcm_subchn_t * substream) +{ + ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO); + snd_pcm_runtime_t *runtime = substream->runtime; + ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO); + ymfpci_voice_t *voice = ypcm->voices[0]; + unsigned long flags; + unsigned int result; + + spin_lock_irqsave(&codec->reg_lock, flags); + if (ypcm->running && voice) + result = voice->bank[codec->active_bank].start << ypcm->shift_offset; + else + result = 0; + spin_unlock_irqrestore(&codec->reg_lock, flags); + return result; +} + +static unsigned int ymfpci_capture_pointer(void *private_data, + snd_pcm_subchn_t * substream) +{ + ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO); + snd_pcm_runtime_t *runtime = substream->runtime; + ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO); + unsigned long flags; + unsigned int result; + + spin_lock_irqsave(&codec->reg_lock, flags); + if (ypcm->running) + result = codec->bank_capture[ypcm->capture_bank_number][codec->active_bank]->start << ypcm->shift_offset; + else + result = 0; + spin_unlock_irqrestore(&codec->reg_lock, flags); + return result; +} +#endif /* old */ + +void ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + ymfpci_t *codec = dev_id; + u32 status, nvoice, mode; + ymfpci_voice_t *voice; + + status = ymfpci_readl(codec, YDSXGR_STATUS); + if (status & 0x80000000) { + spin_lock(&codec->reg_lock); + ymfpci_writel(codec, YDSXGR_STATUS, 0x80000000); + mode = ymfpci_readl(codec, YDSXGR_MODE) | 2; + ymfpci_writel(codec, YDSXGR_MODE, mode); + spin_unlock(&codec->reg_lock); + codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1; + spin_lock(&codec->voice_lock); + for (nvoice = 0; nvoice < 64; nvoice++) { + voice = &codec->voices[nvoice]; + if (voice->interrupt) + voice->interrupt(codec, voice); + } + spin_unlock(&codec->voice_lock); + } + + status = ymfpci_readl(codec, YDSXGR_INTFLAG); + if (status & 1) { + /* timer handler */ + ymfpci_writel(codec, YDSXGR_INTFLAG, ~0); + } +} + +static void ymf_pcm_free_substream(ymfpci_pcm_t *ypcm) +{ + ymfpci_t *codec; + + if (ypcm) { + codec = ypcm->codec; + if (ypcm->voices[1]) + ymfpci_voice_free(codec, ypcm->voices[1]); + if (ypcm->voices[0]) + ymfpci_voice_free(codec, ypcm->voices[0]); + } +} + +static int ymf_state_alloc(ymfpci_t *unit, int nvirt) +{ + ymfpci_pcm_t *ypcm; + struct ymf_state *state; + + if ((state = kmalloc(sizeof(struct ymf_state), GFP_KERNEL)) == NULL) { + goto out0; + } + memset(state, 0, sizeof(struct ymf_state)); + + init_waitqueue_head(&state->dmabuf.wait); + + ypcm = &state->ypcm; + ypcm->state = state; + ypcm->codec = unit; + ypcm->type = PLAYBACK_VOICE; + + state->unit = unit; + state->virt = nvirt; + + state->format.format = AFMT_U8; + state->format.rate = 8000; + state->format.voices = 1; + ymf_pcm_update_shift(&state->format); + + unit->states[nvirt] = state; + return 0; + +out0: + return -ENOMEM; +} + +#if HAVE_RECORD + +static int ymfpci_capture_open(void *private_data, + snd_pcm_subchn_t * substream, + u32 capture_bank_number) +{ + ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO); + snd_pcm_runtime_t *runtime = substream->runtime; + ymfpci_pcm_t *ypcm; + int err; + + if ((err = snd_pcm_dma_alloc(substream, !capture_bank_number ? codec->dma2ptr : codec->dma3ptr, "YMFPCI - ADC")) < 0) + return err; + ypcm = snd_magic_kcalloc(ymfpci_pcm_t, 0, GFP_KERNEL); + if (ypcm == NULL) { + snd_pcm_dma_free(substream); + return -ENOMEM; + } + ypcm->codec = codec; + ypcm->type = capture_bank_number + CAPTURE_REC; + ypcm->substream = substream; + ypcm->capture_bank_number = capture_bank_number; + codec->capture_substream[capture_bank_number] = substream; + runtime->hw = &ymfpci_capture; + snd_pcm_set_mixer(substream, codec->mixer->device, codec->ac97->me_capture); + runtime->private_data = ypcm; + runtime->private_free = ymfpci_pcm_free_substream; + ymfpci_hw_start(codec); + return 0; +} + +#endif /* old */ + +/* AES/IEC958 channel status bits */ +#define SND_PCM_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */ +#define SND_PCM_AES0_NONAUDIO (1<<1) /* 0 = audio, 1 = non-audio */ +#define SND_PCM_AES0_PRO_EMPHASIS (7<<2) /* mask - emphasis */ +#define SND_PCM_AES0_PRO_EMPHASIS_NOTID (0<<2) /* emphasis not indicated */ +#define SND_PCM_AES0_PRO_EMPHASIS_NONE (1<<2) /* none emphasis */ +#define SND_PCM_AES0_PRO_EMPHASIS_5015 (3<<2) /* 50/15us emphasis */ +#define SND_PCM_AES0_PRO_EMPHASIS_CCITT (7<<2) /* CCITT J.17 emphasis */ +#define SND_PCM_AES0_PRO_FREQ_UNLOCKED (1<<5) /* source sample frequency: 0 = locked, 1 = unlocked */ +#define SND_PCM_AES0_PRO_FS (3<<6) /* mask - sample frequency */ +#define SND_PCM_AES0_PRO_FS_NOTID (0<<6) /* fs not indicated */ +#define SND_PCM_AES0_PRO_FS_44100 (1<<6) /* 44.1kHz */ +#define SND_PCM_AES0_PRO_FS_48000 (2<<6) /* 48kHz */ +#define SND_PCM_AES0_PRO_FS_32000 (3<<6) /* 32kHz */ +#define SND_PCM_AES0_CON_NOT_COPYRIGHT (1<<2) /* 0 = copyright, 1 = not copyright */ +#define SND_PCM_AES0_CON_EMPHASIS (7<<3) /* mask - emphasis */ +#define SND_PCM_AES0_CON_EMPHASIS_NONE (0<<3) /* none emphasis */ +#define SND_PCM_AES0_CON_EMPHASIS_5015 (1<<3) /* 50/15us emphasis */ +#define SND_PCM_AES0_CON_MODE (3<<6) /* mask - mode */ +#define SND_PCM_AES1_PRO_MODE (15<<0) /* mask - channel mode */ +#define SND_PCM_AES1_PRO_MODE_NOTID (0<<0) /* not indicated */ +#define SND_PCM_AES1_PRO_MODE_STEREOPHONIC (2<<0) /* stereophonic - ch A is left */ +#define SND_PCM_AES1_PRO_MODE_SINGLE (4<<0) /* single channel */ +#define SND_PCM_AES1_PRO_MODE_TWO (8<<0) /* two channels */ +#define SND_PCM_AES1_PRO_MODE_PRIMARY (12<<0) /* primary/secondary */ +#define SND_PCM_AES1_PRO_MODE_BYTE3 (15<<0) /* vector to byte 3 */ +#define SND_PCM_AES1_PRO_USERBITS (15<<4) /* mask - user bits */ +#define SND_PCM_AES1_PRO_USERBITS_NOTID (0<<4) /* not indicated */ +#define SND_PCM_AES1_PRO_USERBITS_192 (8<<4) /* 192-bit structure */ +#define SND_PCM_AES1_PRO_USERBITS_UDEF (12<<4) /* user defined application */ +#define SND_PCM_AES1_CON_CATEGORY 0x7f +#define SND_PCM_AES1_CON_GENERAL 0x00 +#define SND_PCM_AES1_CON_EXPERIMENTAL 0x40 +#define SND_PCM_AES1_CON_SOLIDMEM_MASK 0x0f +#define SND_PCM_AES1_CON_SOLIDMEM_ID 0x08 +#define SND_PCM_AES1_CON_BROADCAST1_MASK 0x07 +#define SND_PCM_AES1_CON_BROADCAST1_ID 0x04 +#define SND_PCM_AES1_CON_DIGDIGCONV_MASK 0x07 +#define SND_PCM_AES1_CON_DIGDIGCONV_ID 0x02 +#define SND_PCM_AES1_CON_ADC_COPYRIGHT_MASK 0x1f +#define SND_PCM_AES1_CON_ADC_COPYRIGHT_ID 0x06 +#define SND_PCM_AES1_CON_ADC_MASK 0x1f +#define SND_PCM_AES1_CON_ADC_ID 0x16 +#define SND_PCM_AES1_CON_BROADCAST2_MASK 0x0f +#define SND_PCM_AES1_CON_BROADCAST2_ID 0x0e +#define SND_PCM_AES1_CON_LASEROPT_MASK 0x07 +#define SND_PCM_AES1_CON_LASEROPT_ID 0x01 +#define SND_PCM_AES1_CON_MUSICAL_MASK 0x07 +#define SND_PCM_AES1_CON_MUSICAL_ID 0x05 +#define SND_PCM_AES1_CON_MAGNETIC_MASK 0x07 +#define SND_PCM_AES1_CON_MAGNETIC_ID 0x03 +#define SND_PCM_AES1_CON_IEC908_CD (SND_PCM_AES1_CON_LASEROPT_ID|0x00) +#define SND_PCM_AES1_CON_NON_IEC908_CD (SND_PCM_AES1_CON_LASEROPT_ID|0x08) +#define SND_PCM_AES1_CON_PCM_CODER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x00) +#define SND_PCM_AES1_CON_SAMPLER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x20) +#define SND_PCM_AES1_CON_MIXER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x10) +#define SND_PCM_AES1_CON_RATE_CONVERTER (SND_PCM_AES1_CON_DIGDIGCONV_ID|0x18) +#define SND_PCM_AES1_CON_SYNTHESIZER (SND_PCM_AES1_CON_MUSICAL_ID|0x00) +#define SND_PCM_AES1_CON_MICROPHONE (SND_PCM_AES1_CON_MUSICAL_ID|0x08) +#define SND_PCM_AES1_CON_DAT (SND_PCM_AES1_CON_MAGNETIC_ID|0x00) +#define SND_PCM_AES1_CON_VCR (SND_PCM_AES1_CON_MAGNETIC_ID|0x08) +#define SND_PCM_AES1_CON_ORIGINAL (1<<7) /* this bits depends on the category code */ +#define SND_PCM_AES2_PRO_SBITS (7<<0) /* mask - sample bits */ +#define SND_PCM_AES2_PRO_SBITS_20 (2<<0) /* 20-bit - coordination */ +#define SND_PCM_AES2_PRO_SBITS_24 (4<<0) /* 24-bit - main audio */ +#define SND_PCM_AES2_PRO_SBITS_UDEF (6<<0) /* user defined application */ +#define SND_PCM_AES2_PRO_WORDLEN (7<<3) /* mask - source word length */ +#define SND_PCM_AES2_PRO_WORDLEN_NOTID (0<<3) /* not indicated */ +#define SND_PCM_AES2_PRO_WORDLEN_22_18 (2<<3) /* 22-bit or 18-bit */ +#define SND_PCM_AES2_PRO_WORDLEN_23_19 (4<<3) /* 23-bit or 19-bit */ +#define SND_PCM_AES2_PRO_WORDLEN_24_20 (5<<3) /* 24-bit or 20-bit */ +#define SND_PCM_AES2_PRO_WORDLEN_20_16 (6<<3) /* 20-bit or 16-bit */ +#define SND_PCM_AES2_CON_SOURCE (15<<0) /* mask - source number */ +#define SND_PCM_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */ +#define SND_PCM_AES2_CON_CHANNEL (15<<4) /* mask - channel number */ +#define SND_PCM_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */ +#define SND_PCM_AES3_CON_FS (15<<0) /* mask - sample frequency */ +#define SND_PCM_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */ +#define SND_PCM_AES3_CON_FS_48000 (2<<0) /* 48kHz */ +#define SND_PCM_AES3_CON_FS_32000 (3<<0) /* 32kHz */ +#define SND_PCM_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */ +#define SND_PCM_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */ +#define SND_PCM_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */ +#define SND_PCM_AES3_CON_CLOCK_VARIABLE (2<<4) /* variable pitch */ + +#if HAVE_RECORD /* old */ + +static int ymfpci_capture_close(void *private_data, + snd_pcm_subchn_t * substream) +{ + ymfpci_t *codec = snd_magic_cast(ymfpci_t, private_data, -ENXIO); + snd_pcm_runtime_t *runtime = substream->runtime; + ymfpci_pcm_t *ypcm = snd_magic_cast(ymfpci_pcm_t, runtime->private_data, -ENXIO); + + if (ypcm != NULL) { + codec->capture_substream[ypcm->capture_bank_number] = NULL; + ymfpci_hw_stop(codec); + } + snd_pcm_dma_free(substream); + return 0; +} +#endif + +/* + * User interface + */ + +static loff_t ymf_llseek(struct file *file, loff_t offset, int origin) +{ + return -ESPIPE; +} + +/* in this loop, dmabuf.count signifies the amount of data that is waiting to be copied to + the user's buffer. it is filled by the dma machine and drained by this loop. */ +static ssize_t ymf_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ +#if HAVE_RECORD + struct cs_state *state = (struct cs_state *)file->private_data; + struct dmabuf *dmabuf = &state->dmabuf; + ssize_t ret; + unsigned long flags; + unsigned swptr; + int cnt; + +#ifdef DEBUG + printk("cs461x: cs_read called, count = %d\n", count); +#endif + + if (ppos != &file->f_pos) + return -ESPIPE; + if (dmabuf->mapped) + return -ENXIO; + if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) + return ret; + if (!access_ok(VERIFY_WRITE, buffer, count)) + return -EFAULT; + ret = 0; + + while (count > 0) { + spin_lock_irqsave(&state->card->lock, flags); + if (dmabuf->count > (signed) dmabuf->dmasize) { + /* buffer overrun, we are recovering from sleep_on_timeout, + resync hwptr and swptr, make process flush the buffer */ + dmabuf->count = dmabuf->dmasize; + dmabuf->swptr = dmabuf->hwptr; + } + swptr = dmabuf->swptr; + cnt = dmabuf->dmasize - swptr; + if (dmabuf->count < cnt) + cnt = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); + + if (cnt > count) + cnt = count; + if (cnt <= 0) { + unsigned long tmo; + /* buffer is empty, start the dma machine and wait for data to be + recorded */ + start_adc(state); + if (file->f_flags & O_NONBLOCK) { + if (!ret) ret = -EAGAIN; + return ret; + } + /* This isnt strictly right for the 810 but it'll do */ + tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); + tmo >>= sample_shift[dmabuf->fmt]; + /* There are two situations when sleep_on_timeout returns, one is when + the interrupt is serviced correctly and the process is waked up by + ISR ON TIME. Another is when timeout is expired, which means that + either interrupt is NOT serviced correctly (pending interrupt) or it + is TOO LATE for the process to be scheduled to run (scheduler latency) + which results in a (potential) buffer overrun. And worse, there is + NOTHING we can do to prevent it. */ + if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) { +#ifdef DEBUG + printk(KERN_ERR "cs461x: recording schedule timeout, " + "dmasz %u fragsz %u count %i hwptr %u swptr %u\n", + dmabuf->dmasize, dmabuf->fragsize, dmabuf->count, + dmabuf->hwptr, dmabuf->swptr); +#endif + /* a buffer overrun, we delay the recovery untill next time the + while loop begin and we REALLY have space to record */ + } + if (signal_pending(current)) { + ret = ret ? ret : -ERESTARTSYS; + return ret; + } + continue; + } + + if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) { + if (!ret) ret = -EFAULT; + return ret; + } + + swptr = (swptr + cnt) % dmabuf->dmasize; + + spin_lock_irqsave(&state->card->lock, flags); + dmabuf->swptr = swptr; + dmabuf->count -= cnt; + spin_unlock_irqrestore(&state->card->lock, flags); + + count -= cnt; + buffer += cnt; + ret += cnt; + start_adc(state); + } + return ret; +#else + return -EINVAL; +#endif +} + +static ssize_t ymf_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +{ + struct ymf_state *state = (struct ymf_state *)file->private_data; + struct ymf_dmabuf *dmabuf = &state->dmabuf; + DECLARE_WAITQUEUE(waita, current); + ssize_t ret; + unsigned long flags; + unsigned int swptr; + int cnt; /* This many to go in this revolution */ + int redzone; + int delay; + +/* P3 */ /* printk("ymf_write: count %d\n", count); */ + + if (ppos != &file->f_pos) + return -ESPIPE; + if (dmabuf->mapped) + return -ENXIO; + if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) + return ret; + if (!access_ok(VERIFY_READ, buffer, count)) + return -EFAULT; + ret = 0; + + /* + * Alan's cs46xx works without a red zone - marvel of ingenuity. + * We are not so brilliant... Red zone does two things: + * 1. allows for safe start after a pause as we have no way + * to know what the actual, relentlessly advancing, hwptr is. + * 2. makes computations in ymf_pcm_interrupt simpler. + */ + redzone = ymf_calc_lend(state->format.rate) << state->format.shift; + redzone *= 3; /* 2 redzone + 1 possible uncertainty reserve. */ + + add_wait_queue(&dmabuf->wait, &waita); + while (count > 0) { + spin_lock_irqsave(&state->unit->reg_lock, flags); + if (dmabuf->count < 0) { + printk(KERN_ERR + "ymf_write: count %d, was legal in cs46xx\n", + dmabuf->count); + dmabuf->count = 0; + } + if (dmabuf->count == 0) { + swptr = dmabuf->hwptr; + if (state->ypcm.running) { + /* + * Add uncertainty reserve. + */ + cnt = ymf_calc_lend(state->format.rate); + cnt <<= state->format.shift; + if ((swptr += cnt) >= dmabuf->dmasize) { + swptr -= dmabuf->dmasize; + } + } + dmabuf->swptr = swptr; + } else { + /* + * XXX This is not right if dmabuf->count is small - + * about 2*x frame size or less. We cannot count on + * on appending and not causing an artefact. + * Should use a variation of the count==0 case above. + */ + swptr = dmabuf->swptr; + } + cnt = dmabuf->dmasize - swptr; + if (dmabuf->count + cnt > dmabuf->dmasize - redzone) + cnt = (dmabuf->dmasize - redzone) - dmabuf->count; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + + if (cnt > count) + cnt = count; + if (cnt <= 0) { +/* P3 */ /* printk("ymf_write: full, count %d swptr %d\n", + dmabuf->count, dmabuf->swptr); */ + /* + * buffer is full, start the dma machine and + * wait for data to be played + */ + spin_lock_irqsave(&state->unit->reg_lock, flags); + if (!state->ypcm.running) { + ymf_playback_trigger(state->unit, &state->ypcm, 1); + } + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + if (file->f_flags & O_NONBLOCK) { + if (!ret) ret = -EAGAIN; + break; + } + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + if (signal_pending(current)) { + if (!ret) ret = -ERESTARTSYS; + break; + } + continue; + } + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { + if (!ret) ret = -EFAULT; + break; + } + + if ((swptr += cnt) >= dmabuf->dmasize) { + swptr -= dmabuf->dmasize; + } + + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->swptr = swptr; + dmabuf->count += cnt; + + /* + * Start here is a bad idea - may cause startup click + * in /bin/play when dmabuf is not full yet. + * However, some broken applications do not make + * any use of SNDCTL_DSP_SYNC (Doom is the worst). + * One frame is about 5.3ms, Doom write size is 46ms. + */ + delay = state->format.rate / 20; /* 50ms */ + delay <<= state->format.shift; + if (dmabuf->count >= delay && !state->ypcm.running) { + ymf_playback_trigger(state->unit, &state->ypcm, 1); + } + + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + + count -= cnt; + buffer += cnt; + ret += cnt; + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&dmabuf->wait, &waita); + +/* P3 */ /* printk("ymf_write: dmabuf.count %d\n", dmabuf->count); */ + return ret; +} + +static unsigned int ymf_poll(struct file *file, struct poll_table_struct *wait) +{ + struct ymf_state *state = (struct ymf_state *)file->private_data; + struct ymf_dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + unsigned int mask = 0; + + if (file->f_mode & (FMODE_WRITE | FMODE_READ)) + poll_wait(file, &dmabuf->wait, wait); + + spin_lock_irqsave(&state->unit->reg_lock, flags); + if (file->f_mode & FMODE_READ) { + if (dmabuf->count >= (signed)dmabuf->fragsize) + mask |= POLLIN | POLLRDNORM; + } + if (file->f_mode & FMODE_WRITE) { + if (dmabuf->mapped) { + if (dmabuf->count >= (signed)dmabuf->fragsize) + mask |= POLLOUT | POLLWRNORM; + } else { + if ((signed)dmabuf->dmasize >= dmabuf->count + (signed)dmabuf->fragsize) + mask |= POLLOUT | POLLWRNORM; + } + } + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + + return mask; +} + +static int ymf_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct ymf_state *state = (struct ymf_state *)file->private_data; + struct ymf_dmabuf *dmabuf = &state->dmabuf; + int ret; + unsigned long size; + + + if (vma->vm_flags & VM_WRITE) { + if ((ret = prog_dmabuf(state, 0)) != 0) + return ret; + } else if (vma->vm_flags & VM_READ) { + if ((ret = prog_dmabuf(state, 1)) != 0) + return ret; + } else + return -EINVAL; + + if (vma->vm_pgoff != 0) + return -EINVAL; + size = vma->vm_end - vma->vm_start; + if (size > (PAGE_SIZE << dmabuf->buforder)) + return -EINVAL; + if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf), + size, vma->vm_page_prot)) + return -EAGAIN; + dmabuf->mapped = 1; + + return 0; +} + +static int ymf_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct ymf_state *state = (struct ymf_state *)file->private_data; + struct ymf_dmabuf *dmabuf = &state->dmabuf; + unsigned long flags; + audio_buf_info abinfo; + count_info cinfo; + int val; + + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, (int *)arg); + + case SNDCTL_DSP_RESET: + if (file->f_mode & FMODE_WRITE) { + ymf_wait_dac(state); + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } +#if HAVE_RECORD + if (file->f_mode & FMODE_READ) { + stop_adc(state); + synchronize_irq(); + dmabuf->ready = 0; + dmabuf->swptr = dmabuf->hwptr = 0; + dmabuf->count = dmabuf->total_bytes = 0; + } +#endif + return 0; + + case SNDCTL_DSP_SYNC: + if (file->f_mode & FMODE_WRITE) { + if (file->f_flags & O_NONBLOCK) { + spin_lock_irqsave(&state->unit->reg_lock, flags); + if (dmabuf->count != 0 && !state->ypcm.running) { + ymf_start_dac(state); + } + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } else { + ymf_wait_dac(state); + } + } + return 0; + + case SNDCTL_DSP_SPEED: /* set smaple rate */ + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val >= 8000 && val <= 48000) { + if (file->f_mode & FMODE_WRITE) { + ymf_wait_dac(state); + } +#if HAVE_RECORD + if (file->f_mode & FMODE_READ) { + stop_adc(state); + } +#endif + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->ready = 0; + state->format.rate = val; + ymf_pcm_update_shift(&state->format); + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } + return put_user(state->format.rate, (int *)arg); + + /* + * OSS manual does not mention SNDCTL_DSP_STEREO at all. + * All channels are mono and if you want stereo, you + * play into two channels with SNDCTL_DSP_CHANNELS. + * However, mpg123 uses it. I wonder, why Michael Hipp uses it. + */ + case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_WRITE) { + ymf_wait_dac(state); + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->ready = 0; + state->format.voices = val ? 2 : 1; + ymf_pcm_update_shift(&state->format); + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } +#if HAVE_RECORD + if (file->f_mode & FMODE_READ) { + /* stop_adc(state); */ + dmabuf->ready = 0; + if(val) + dmabuf->fmt |= CS_FMT_STEREO; + else + dmabuf->fmt &= ~CS_FMT_STEREO; + } +#endif + return 0; + + case SNDCTL_DSP_GETBLKSIZE: + if (file->f_mode & FMODE_WRITE) { + if ((val = prog_dmabuf(state, 0))) + return val; + return put_user(dmabuf->fragsize, (int *)arg); + } + if (file->f_mode & FMODE_READ) { + if ((val = prog_dmabuf(state, 1))) + return val; + return put_user(dmabuf->fragsize, (int *)arg); + } + return -EINVAL; + + case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/ + return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); + + case SNDCTL_DSP_SETFMT: /* Select sample format */ + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val == AFMT_S16_LE || val == AFMT_U8) { + if (file->f_mode & FMODE_WRITE) { + ymf_wait_dac(state); + } +#if HAVE_RECORD + if (file->f_mode & FMODE_READ) { + stop_adc(state); + } +#endif + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->ready = 0; + state->format.format = val; + ymf_pcm_update_shift(&state->format); + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } + return put_user(state->format.format, (int *)arg); + + case SNDCTL_DSP_CHANNELS: + if (get_user(val, (int *)arg)) + return -EFAULT; + /* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_CHANNELS 0x%x\n", val); */ + if (val != 0) { + if (file->f_mode & FMODE_WRITE) { + ymf_wait_dac(state); + if (val == 1 || val == 2) { + spin_lock_irqsave(&state->unit->reg_lock, flags); + dmabuf->ready = 0; + state->format.voices = val; + ymf_pcm_update_shift(&state->format); + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } + } +#if HAVE_RECORD + if (file->f_mode & FMODE_READ) { + spin_lock_irqsave(&state->unit->reg_lock, flags); + stop_adc(state); + dmabuf->ready = 0; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + } +#endif + } + return put_user(state->format.voices, (int *)arg); + + case SNDCTL_DSP_POST: + /* + * Quoting OSS PG: + * The ioctl SNDCTL_DSP_POST is a lightweight version of + * SNDCTL_DSP_SYNC. It just tells to the driver that there + * is likely to be a pause in the output. This makes it + * possible for the device to handle the pause more + * intelligently. This ioctl doesn't block the application. + * + * The paragraph above is a clumsy way to say "flush ioctl". + * This ioctl is used by mpg123. + */ + /* P3 */ /* printk("ymfpci: ioctl SNDCTL_DSP_POST\n"); */ + spin_lock_irqsave(&state->unit->reg_lock, flags); + if (dmabuf->count != 0 && !state->ypcm.running) { + ymf_start_dac(state); + } + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + return 0; + + case SNDCTL_DSP_SUBDIVIDE: + if (dmabuf->subdivision) + return -EINVAL; + if (get_user(val, (int *)arg)) + return -EFAULT; + if (val != 1 && val != 2) + return -EINVAL; + dmabuf->subdivision = val; + return 0; + + case SNDCTL_DSP_SETFRAGMENT: + if (get_user(val, (int *)arg)) + return -EFAULT; + /* P3: these frags are for Doom. Amasingly, it sets [2,2**11]. */ + /* P3 */ // printk("ymfpci: ioctl SNDCTL_DSP_SETFRAGMENT 0x%x\n", val); + + dmabuf->ossfragshift = val & 0xffff; + dmabuf->ossmaxfrags = (val >> 16) & 0xffff; + switch (dmabuf->ossmaxfrags) { + case 1: + dmabuf->ossfragshift = 12; + return 0; + default: + /* Fragments must be 2K long */ + dmabuf->ossfragshift = 11; + dmabuf->ossmaxfrags = 2; + } + return 0; + + case SNDCTL_DSP_GETOSPACE: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + if (!dmabuf->ready && (val = prog_dmabuf(state, 0)) != 0) + return val; + spin_lock_irqsave(&state->unit->reg_lock, flags); + /* cs_update_ptr(state); */ /* XXX Always up to date? */ + abinfo.fragsize = dmabuf->fragsize; + abinfo.bytes = dmabuf->dmasize - dmabuf->count; + abinfo.fragstotal = dmabuf->numfrag; + abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + +#if HAVE_RECORD + case SNDCTL_DSP_GETISPACE: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + if (!dmabuf->ready && (val = prog_dmabuf(state, 1)) != 0) + return val; + spin_lock_irqsave(&state->card->lock, flags); + cs_update_ptr(state); + abinfo.fragsize = dmabuf->fragsize; + abinfo.bytes = dmabuf->count; + abinfo.fragstotal = dmabuf->numfrag; + abinfo.fragments = abinfo.bytes >> dmabuf->fragshift; + spin_unlock_irqrestore(&state->card->lock, flags); + return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; +#endif + + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; + + case SNDCTL_DSP_GETCAPS: + /* return put_user(DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP, + (int *)arg); */ + return put_user(0, (int *)arg); + +#if 0 /* old */ + case SNDCTL_DSP_GETTRIGGER: + val = 0; + if (file->f_mode & FMODE_READ && dmabuf->enable) + val |= PCM_ENABLE_INPUT; + if (file->f_mode & FMODE_WRITE && dmabuf->enable) + val |= PCM_ENABLE_OUTPUT; + return put_user(val, (int *)arg); + + case SNDCTL_DSP_SETTRIGGER: + if (get_user(val, (int *)arg)) + return -EFAULT; + if (file->f_mode & FMODE_READ) { + if (val & PCM_ENABLE_INPUT) { + if (!dmabuf->ready && (ret = prog_dmabuf(state, 1))) + return ret; + start_adc(state); + } else + stop_adc(state); + } + if (file->f_mode & FMODE_WRITE) { + if (val & PCM_ENABLE_OUTPUT) { + if (!dmabuf->ready && (ret = prog_dmabuf(state, 0))) + return ret; + start_dac(state); // sure? + } else + stop_dac(state); + } + return 0; + +#endif + +#if HAVE_RECORD + case SNDCTL_DSP_GETIPTR: + if (!(file->f_mode & FMODE_READ)) + return -EINVAL; + spin_lock_irqsave(&state->unit->reg_lock, flags); + cs_update_ptr(state); + cinfo.bytes = dmabuf->total_bytes; + cinfo.blocks = dmabuf->count >> dmabuf->fragshift; + cinfo.ptr = dmabuf->hwptr; + if (dmabuf->mapped) + dmabuf->count &= dmabuf->fragsize-1; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); +#endif + + case SNDCTL_DSP_GETOPTR: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&state->unit->reg_lock, flags); + /* cs_update_ptr(state); */ /* Always up to date */ + cinfo.bytes = dmabuf->total_bytes; + cinfo.blocks = dmabuf->count >> dmabuf->fragshift; + cinfo.ptr = dmabuf->hwptr; + if (dmabuf->mapped) + dmabuf->count &= dmabuf->fragsize-1; + spin_unlock_irqrestore(&state->unit->reg_lock, flags); + return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + + case SNDCTL_DSP_SETDUPLEX: /* XXX TODO */ + return -EINVAL; + +#if 0 /* old */ + case SNDCTL_DSP_GETODELAY: + if (!(file->f_mode & FMODE_WRITE)) + return -EINVAL; + spin_lock_irqsave(&state->unit->reg_lock, flags); + cs_update_ptr(state); + val = dmabuf->count; + spin_unlock_irqrestore(&state->card->lock, flags); + return put_user(val, (int *)arg); +#endif + + case SOUND_PCM_READ_RATE: + return put_user(state->format.rate, (int *)arg); + + case SOUND_PCM_READ_CHANNELS: + return put_user(state->format.voices, (int *)arg); + + case SOUND_PCM_READ_BITS: + return put_user(AFMT_S16_LE, (int *)arg); + + case SNDCTL_DSP_MAPINBUF: + case SNDCTL_DSP_MAPOUTBUF: + case SNDCTL_DSP_SETSYNCRO: + case SOUND_PCM_WRITE_FILTER: + case SOUND_PCM_READ_FILTER: + return -ENOTTY; + + default: + /* + * Some programs mix up audio devices and ioctls + * or perhaps they expect "universal" ioctls, + * for instance we get SNDCTL_TMR_CONTINUE here. + * XXX Is there sound_generic_ioctl() around? + */ + } + return -ENOTTY; +} + +static int ymf_open(struct inode *inode, struct file *file) +{ + struct list_head *list; + ymfpci_t *unit; + int minor; + struct ymf_state *state; + int nvirt; + int err; + + /* + * This is how we do it currently: only one channel is used + * in every board, so that we could use several boards in one machine. + * We waste 63 out of 64 playback slots, but so what. + * OSS model is constructed for devices with single playback channel. + */ + minor = MINOR(inode->i_rdev); + if ((minor & 0x0F) == 3) { /* /dev/dspN */ + ; + } else { + return -ENXIO; + } + nvirt = 0; /* Such is the partitioning of minor */ + + for (list = ymf_devs.next; list != &ymf_devs; list = list->next) { + unit = list_entry(list, ymfpci_t, ymf_devs); + if (((unit->dev_audio ^ minor) & ~0x0F) == 0) + break; + } + if (list == &ymf_devs) + return -ENODEV; + + down(&unit->open_sem); + if (unit->states[nvirt] != NULL) { + up(&unit->open_sem); + return -EBUSY; + } + + if ((err = ymf_state_alloc(unit, nvirt)) != 0) { + up(&unit->open_sem); + return err; + } + state = unit->states[nvirt]; + + file->private_data = state; + + /* + * XXX This ymf_playback_prepare is totally unneeded here. + * The question is if we want to allow write to fail if + * prog_dmabuf fails... Say, no memory in DMA zone? + */ + if ((err = ymf_playback_prepare(unit, state)) != 0) { + /* XXX This recovery is ugly as hell. */ + + ymf_pcm_free_substream(&state->ypcm); + + unit->states[state->virt] = NULL; + kfree(state); + + up(&unit->open_sem); + return err; + } + +#if 0 /* test if interrupts work */ + ymfpci_writew(codec, YDSXGR_TIMERCOUNT, 0xfffe); /* ~ 680ms */ + ymfpci_writeb(codec, YDSXGR_TIMERCTRL, + (YDSXGR_TIMERCTRL_TEN|YDSXGR_TIMERCTRL_TIEN)); +#endif + up(&unit->open_sem); + /* XXX Is it correct to have MOD_INC_USE_COUNT outside of sem.? */ + + MOD_INC_USE_COUNT; + return 0; +} + +static int ymf_release(struct inode *inode, struct file *file) +{ + struct ymf_state *state = (struct ymf_state *)file->private_data; + ymfpci_t *codec = state->unit; + +#if 0 /* test if interrupts work */ + ymfpci_writeb(codec, YDSXGR_TIMERCTRL, 0); +#endif + + if (state != codec->states[state->virt]) { + printk(KERN_ERR "ymfpci%d.%d: state mismatch\n", + state->unit->dev_audio, state->virt); + return -EIO; + } + + down(&codec->open_sem); + + /* + * XXX Solve the case of O_NONBLOCK close - don't deallocate here. + * Deallocate when unloading the driver and we can wait. + */ + ymf_wait_dac(state); + dealloc_dmabuf(state); + ymf_pcm_free_substream(&state->ypcm); + + codec->states[state->virt] = NULL; + kfree(state); + + up(&codec->open_sem); + + MOD_DEC_USE_COUNT; + return 0; +} + +/* + * Mixer operations are based on cs46xx. + */ +static int ymf_open_mixdev(struct inode *inode, struct file *file) +{ + int i; + int minor = MINOR(inode->i_rdev); + struct list_head *list; + ymfpci_t *unit; + + for (list = ymf_devs.next; list != &ymf_devs; list = list->next) { + unit = list_entry(list, ymfpci_t, ymf_devs); + for (i = 0; i < NR_AC97; i++) { + if (unit->ac97_codec[i] != NULL && + unit->ac97_codec[i]->dev_mixer == minor) { + goto match; + } + } + } + return -ENODEV; + + match: + file->private_data = unit->ac97_codec[i]; + + MOD_INC_USE_COUNT; + return 0; +} + +static int ymf_ioctl_mixdev(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct ac97_codec *codec = (struct ac97_codec *)file->private_data; + + return codec->mixer_ioctl(codec, cmd, arg); +} + +static int ymf_release_mixdev(struct inode *inode, struct file *file) +{ + MOD_DEC_USE_COUNT; + return 0; +} + +static /*const*/ struct file_operations ymf_fops = { + llseek: ymf_llseek, + read: ymf_read, + write: ymf_write, + poll: ymf_poll, + ioctl: ymf_ioctl, + mmap: ymf_mmap, + open: ymf_open, + release: ymf_release, +}; + +static /*const*/ struct file_operations ymf_mixer_fops = { + llseek: ymf_llseek, + ioctl: ymf_ioctl_mixdev, + open: ymf_open_mixdev, + release: ymf_release_mixdev, +}; + +/* + * initialization routines + */ + +static void ymfpci_aclink_reset(struct pci_dev * pci) +{ + u8 cmd; + + pci_read_config_byte(pci, PCIR_DSXGCTRL, &cmd); + if (cmd & 0x03) { + pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc); + pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd | 0x03); + pci_write_config_byte(pci, PCIR_DSXGCTRL, cmd & 0xfc); + } +} + +static void ymfpci_enable_dsp(ymfpci_t *codec) +{ + ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000001); +} + +static void ymfpci_disable_dsp(ymfpci_t *codec) +{ + u32 val; + int timeout = 1000; + + val = ymfpci_readl(codec, YDSXGR_CONFIG); + if (val) + ymfpci_writel(codec, YDSXGR_CONFIG, 0x00000000); + while (timeout-- > 0) { + val = ymfpci_readl(codec, YDSXGR_STATUS); + if ((val & 0x00000002) == 0) + break; + } +} + +#include "ymfpci_image.h" + +static void ymfpci_download_image(ymfpci_t *codec) +{ + int i, ver_1e; + u16 ctrl; + + ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x00000000); + ymfpci_disable_dsp(codec); + ymfpci_writel(codec, YDSXGR_MODE, 0x00010000); + ymfpci_writel(codec, YDSXGR_MODE, 0x00000000); + ymfpci_writel(codec, YDSXGR_MAPOFREC, 0x00000000); + ymfpci_writel(codec, YDSXGR_MAPOFEFFECT, 0x00000000); + ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, 0x00000000); + ymfpci_writel(codec, YDSXGR_RECCTRLBASE, 0x00000000); + ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0x00000000); + ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL); + ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); + + /* setup DSP instruction code */ + for (i = 0; i < YDSXG_DSPLENGTH; i++) + ymfpci_writel(codec, YDSXGR_DSPINSTRAM + i, DspInst[i >> 2]); + + switch (codec->pci->device) { + case PCI_DEVICE_ID_YAMAHA_724F: + case PCI_DEVICE_ID_YAMAHA_740C: + case PCI_DEVICE_ID_YAMAHA_744: + case PCI_DEVICE_ID_YAMAHA_754: + ver_1e = 1; + break; + default: + ver_1e = 0; + } + + if (ver_1e) { + /* setup control instruction code */ + for (i = 0; i < YDSXG_CTRLLENGTH; i++) + ymfpci_writel(codec, YDSXGR_CTRLINSTRAM + i, CntrlInst1E[i >> 2]); + } else { + for (i = 0; i < YDSXG_CTRLLENGTH; i++) + ymfpci_writel(codec, YDSXGR_CTRLINSTRAM + i, CntrlInst[i >> 2]); + } + + ymfpci_enable_dsp(codec); +} + +static int ymfpci_memalloc(ymfpci_t *codec) +{ + long size, playback_ctrl_size; + int voice, bank; + u8 *ptr; + + playback_ctrl_size = 4 + 4 * YDSXG_PLAYBACK_VOICES; + codec->bank_size_playback = ymfpci_readl(codec, YDSXGR_PLAYCTRLSIZE) << 2; + codec->bank_size_capture = ymfpci_readl(codec, YDSXGR_RECCTRLSIZE) << 2; + codec->bank_size_effect = ymfpci_readl(codec, YDSXGR_EFFCTRLSIZE) << 2; + codec->work_size = YDSXG_DEFAULT_WORK_SIZE; + + size = ((playback_ctrl_size + 0x00ff) & ~0x00ff) + + ((codec->bank_size_playback * 2 * YDSXG_PLAYBACK_VOICES + 0xff) & ~0xff) + + ((codec->bank_size_capture * 2 * YDSXG_CAPTURE_VOICES + 0xff) & ~0xff) + + ((codec->bank_size_effect * 2 * YDSXG_EFFECT_VOICES + 0xff) & ~0xff) + + codec->work_size; + + ptr = (u8 *)kmalloc(size + 0x00ff, GFP_KERNEL); + if (ptr == NULL) + return -ENOMEM; + + codec->work_ptr = ptr; + ptr += 0x00ff; + (long)ptr &= ~0x00ff; + + codec->bank_base_playback = ptr; + codec->ctrl_playback = (u32 *)ptr; + codec->ctrl_playback[0] = YDSXG_PLAYBACK_VOICES; + ptr += (playback_ctrl_size + 0x00ff) & ~0x00ff; + for (voice = 0; voice < YDSXG_PLAYBACK_VOICES; voice++) { + for (bank = 0; bank < 2; bank++) { + codec->bank_playback[voice][bank] = (ymfpci_playback_bank_t *)ptr; + ptr += codec->bank_size_playback; + } + codec->voices[voice].number = voice; + codec->voices[voice].bank = codec->bank_playback[voice][0]; + } + ptr += (codec->bank_size_playback + 0x00ff) & ~0x00ff; + codec->bank_base_capture = ptr; + for (voice = 0; voice < YDSXG_CAPTURE_VOICES; voice++) + for (bank = 0; bank < 2; bank++) { + codec->bank_capture[voice][bank] = (ymfpci_capture_bank_t *)ptr; + ptr += codec->bank_size_capture; + } + ptr += (codec->bank_size_capture + 0x00ff) & ~0x00ff; + codec->bank_base_effect = ptr; + for (voice = 0; voice < YDSXG_EFFECT_VOICES; voice++) + for (bank = 0; bank < 2; bank++) { + codec->bank_effect[voice][bank] = (ymfpci_effect_bank_t *)ptr; + ptr += codec->bank_size_effect; + } + ptr += (codec->bank_size_effect + 0x00ff) & ~0x00ff; + codec->work_base = ptr; + + ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, virt_to_bus(codec->bank_base_playback)); + ymfpci_writel(codec, YDSXGR_RECCTRLBASE, virt_to_bus(codec->bank_base_capture)); + ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, virt_to_bus(codec->bank_base_effect)); + ymfpci_writel(codec, YDSXGR_WORKBASE, virt_to_bus(codec->work_base)); + ymfpci_writel(codec, YDSXGR_WORKSIZE, codec->work_size >> 2); + + /* S/PDIF output initialization */ + ymfpci_writew(codec, YDSXGR_SPDIFOUTCTRL, 0); + ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS, + SND_PCM_AES0_CON_EMPHASIS_NONE | + (SND_PCM_AES1_CON_ORIGINAL << 8) | + (SND_PCM_AES1_CON_PCM_CODER << 8)); + + /* S/PDIF input initialization */ + ymfpci_writew(codec, YDSXGR_SPDIFINCTRL, 0); + + /* move this volume setup to mixer */ + ymfpci_writel(codec, YDSXGR_NATIVEDACOUTVOL, 0x3fff3fff); + ymfpci_writel(codec, YDSXGR_BUF441OUTVOL, 0x3fff3fff); + ymfpci_writel(codec, YDSXGR_NATIVEADCINVOL, 0x3fff3fff); + ymfpci_writel(codec, YDSXGR_NATIVEDACINVOL, 0x3fff3fff); + + return 0; +} + +static void ymfpci_memfree(ymfpci_t *codec) +{ + ymfpci_writel(codec, YDSXGR_PLAYCTRLBASE, 0); + ymfpci_writel(codec, YDSXGR_RECCTRLBASE, 0); + ymfpci_writel(codec, YDSXGR_EFFCTRLBASE, 0); + ymfpci_writel(codec, YDSXGR_WORKBASE, 0); + ymfpci_writel(codec, YDSXGR_WORKSIZE, 0); + kfree(codec->work_ptr); +} + +static int ymf_ac97_init(ymfpci_t *card, int num_ac97) +{ + struct ac97_codec *codec; + u16 eid; + + if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) + return -ENOMEM; + memset(codec, 0, sizeof(struct ac97_codec)); + + /* initialize some basic codec information, other fields will be filled + in ac97_probe_codec */ + codec->private_data = card; + codec->id = num_ac97; + + codec->codec_read = ymfpci_codec_read; + codec->codec_write = ymfpci_codec_write; + + if (ac97_probe_codec(codec) == 0) { + printk("ymfpci: ac97_probe_codec failed\n"); + goto out_kfree; + } + + eid = ymfpci_codec_read(codec, AC97_EXTENDED_ID); + if (eid==0xFFFFFF) { + printk(KERN_WARNING "ymfpci: no codec attached ?\n"); + goto out_kfree; + } + + card->ac97_features = eid; + + if ((codec->dev_mixer = register_sound_mixer(&ymf_mixer_fops, -1)) < 0) { + printk(KERN_ERR "ymfpci: couldn't register mixer!\n"); + goto out_kfree; + } + + card->ac97_codec[num_ac97] = codec; + + return 0; + out_kfree: + kfree(codec); + return -ENODEV; +} + +static int __devinit ymf_probe_one(struct pci_dev *pcidev, const struct pci_device_id *ent) +{ + u16 ctrl; + ymfpci_t *codec; + + int err; + + if (pci_enable_device(pcidev) < 0) { + printk(KERN_ERR "ymfpci: pci_enable_device failed\n"); + return -ENODEV; + } + + if ((codec = kmalloc(sizeof(ymfpci_t), GFP_KERNEL)) == NULL) { + printk(KERN_ERR "ymfpci: no core\n"); + return -ENOMEM; + } + memset(codec, 0, sizeof(*codec)); + + spin_lock_init(&codec->reg_lock); + spin_lock_init(&codec->voice_lock); + init_MUTEX(&codec->open_sem); + codec->pci = pcidev; + + pci_read_config_byte(pcidev, PCI_REVISION_ID, &codec->rev); + codec->reg_area_virt = ioremap(pci_resource_start(pcidev, 0), 0x8000); + + printk(KERN_INFO "ymfpci: %s at 0x%lx IRQ %d\n", + (char *)ent->driver_data, pci_resource_start(pcidev, 0), pcidev->irq); + + ymfpci_aclink_reset(pcidev); + if (ymfpci_codec_ready(codec, 0, 1) < 0) + goto out_unmap; + + ymfpci_download_image(codec); + + udelay(100); /* seems we need some delay after downloading image.. */ + + if (ymfpci_memalloc(codec) < 0) + goto out_disable_dsp; + + /* ymfpci_proc_init(card, codec); */ + + if (request_irq(pcidev->irq, ymf_interrupt, SA_SHIRQ, "ymfpci", codec) != 0) { + printk(KERN_ERR "ymfpci%d: unable to request IRQ %d\n", + codec->dev_audio, pcidev->irq); + goto out_memfree; + } + + /* register /dev/dsp */ + if ((codec->dev_audio = register_sound_dsp(&ymf_fops, -1)) < 0) { + printk(KERN_ERR "ymfpci%d: unable to register dsp\n", + codec->dev_audio); + goto out_free_irq; + } + + /* + * Poke just the primary for the moment. + */ + if ((err = ymf_ac97_init(codec, 0)) != 0) + goto out_unregister_sound_dsp; + + /* put it into driver list */ + list_add_tail(&codec->ymf_devs, &ymf_devs); + pci_set_drvdata(pcidev, codec); + + return 0; + + out_unregister_sound_dsp: + unregister_sound_dsp(codec->dev_audio); + out_free_irq: + free_irq(pcidev->irq, codec); + out_memfree: + ymfpci_memfree(codec); + out_disable_dsp: + ymfpci_disable_dsp(codec); + ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL); + ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); + ymfpci_writel(codec, YDSXGR_STATUS, ~0); + out_unmap: + iounmap(codec->reg_area_virt); + kfree(codec); + return -ENODEV; +} + +static void __devexit ymf_remove_one(struct pci_dev *pcidev) +{ + __u16 ctrl; + ymfpci_t *codec = pci_get_drvdata(pcidev); + + /* remove from list of devices */ + list_del(&codec->ymf_devs); + + unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer); + kfree(codec->ac97_codec[0]); + unregister_sound_dsp(codec->dev_audio); + free_irq(pcidev->irq, codec); + ymfpci_memfree(codec); + ymfpci_writel(codec, YDSXGR_STATUS, ~0); + ymfpci_disable_dsp(codec); + ctrl = ymfpci_readw(codec, YDSXGR_GLOBALCTRL); + ymfpci_writew(codec, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); + iounmap(codec->reg_area_virt); + kfree(codec); +} + +MODULE_AUTHOR("Jaroslav Kysela"); +MODULE_DESCRIPTION("Yamaha YMF7xx PCI Audio"); + +static struct pci_driver ymfpci_driver = { + name: "ymfpci", + id_table: ymf_id_tbl, + probe: ymf_probe_one, + remove: ymf_remove_one, +}; + +static int __init ymf_init_module(void) +{ + return pci_module_init(&ymfpci_driver); +} + +static void __exit ymf_cleanup_module (void) +{ + pci_unregister_driver(&ymfpci_driver); +} + +module_init(ymf_init_module); +module_exit(ymf_cleanup_module); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/ymfpci.h linux/drivers/sound/ymfpci.h --- v2.4.0-test11/linux/drivers/sound/ymfpci.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/ymfpci.h Mon Dec 11 13:32:24 2000 @@ -0,0 +1,343 @@ +#ifndef __YMFPCI_H +#define __YMFPCI_H + +/* + * Copyright (c) by Jaroslav Kysela + * Definitions for Yahama YMF724/740/744/754 chips + * + * + * 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. + * + */ + +/* + * Direct registers + */ + +/* #define YMFREG(codec, reg) (codec->port + YDSXGR_##reg) */ + +#define YDSXGR_INTFLAG 0x0004 +#define YDSXGR_ACTIVITY 0x0006 +#define YDSXGR_GLOBALCTRL 0x0008 +#define YDSXGR_ZVCTRL 0x000A +#define YDSXGR_TIMERCTRL 0x0010 +#define YDSXGR_TIMERCTRL_TEN 0x0001 +#define YDSXGR_TIMERCTRL_TIEN 0x0002 +#define YDSXGR_TIMERCOUNT 0x0012 +#define YDSXGR_SPDIFOUTCTRL 0x0018 +#define YDSXGR_SPDIFOUTSTATUS 0x001C +#define YDSXGR_EEPROMCTRL 0x0020 +#define YDSXGR_SPDIFINCTRL 0x0034 +#define YDSXGR_SPDIFINSTATUS 0x0038 +#define YDSXGR_DSPPROGRAMDL 0x0048 +#define YDSXGR_DLCNTRL 0x004C +#define YDSXGR_GPIOININTFLAG 0x0050 +#define YDSXGR_GPIOININTENABLE 0x0052 +#define YDSXGR_GPIOINSTATUS 0x0054 +#define YDSXGR_GPIOOUTCTRL 0x0056 +#define YDSXGR_GPIOFUNCENABLE 0x0058 +#define YDSXGR_GPIOTYPECONFIG 0x005A +#define YDSXGR_AC97CMDDATA 0x0060 +#define YDSXGR_AC97CMDADR 0x0062 +#define YDSXGR_PRISTATUSDATA 0x0064 +#define YDSXGR_PRISTATUSADR 0x0066 +#define YDSXGR_SECSTATUSDATA 0x0068 +#define YDSXGR_SECSTATUSADR 0x006A +#define YDSXGR_SECCONFIG 0x0070 +#define YDSXGR_LEGACYOUTVOL 0x0080 +#define YDSXGR_LEGACYOUTVOLL 0x0080 +#define YDSXGR_LEGACYOUTVOLR 0x0082 +#define YDSXGR_NATIVEDACOUTVOL 0x0084 +#define YDSXGR_NATIVEDACOUTVOLL 0x0084 +#define YDSXGR_NATIVEDACOUTVOLR 0x0086 +#define YDSXGR_SPDIFOUTVOL 0x0088 +#define YDSXGR_SPDIFOUTVOLL 0x0088 +#define YDSXGR_SPDIFOUTVOLR 0x008A +#define YDSXGR_AC3OUTVOL 0x008C +#define YDSXGR_AC3OUTVOLL 0x008C +#define YDSXGR_AC3OUTVOLR 0x008E +#define YDSXGR_PRIADCOUTVOL 0x0090 +#define YDSXGR_PRIADCOUTVOLL 0x0090 +#define YDSXGR_PRIADCOUTVOLR 0x0092 +#define YDSXGR_LEGACYLOOPVOL 0x0094 +#define YDSXGR_LEGACYLOOPVOLL 0x0094 +#define YDSXGR_LEGACYLOOPVOLR 0x0096 +#define YDSXGR_NATIVEDACLOOPVOL 0x0098 +#define YDSXGR_NATIVEDACLOOPVOLL 0x0098 +#define YDSXGR_NATIVEDACLOOPVOLR 0x009A +#define YDSXGR_SPDIFLOOPVOL 0x009C +#define YDSXGR_SPDIFLOOPVOLL 0x009E +#define YDSXGR_SPDIFLOOPVOLR 0x009E +#define YDSXGR_AC3LOOPVOL 0x00A0 +#define YDSXGR_AC3LOOPVOLL 0x00A0 +#define YDSXGR_AC3LOOPVOLR 0x00A2 +#define YDSXGR_PRIADCLOOPVOL 0x00A4 +#define YDSXGR_PRIADCLOOPVOLL 0x00A4 +#define YDSXGR_PRIADCLOOPVOLR 0x00A6 +#define YDSXGR_NATIVEADCINVOL 0x00A8 +#define YDSXGR_NATIVEADCINVOLL 0x00A8 +#define YDSXGR_NATIVEADCINVOLR 0x00AA +#define YDSXGR_NATIVEDACINVOL 0x00AC +#define YDSXGR_NATIVEDACINVOLL 0x00AC +#define YDSXGR_NATIVEDACINVOLR 0x00AE +#define YDSXGR_BUF441OUTVOL 0x00B0 +#define YDSXGR_BUF441OUTVOLL 0x00B0 +#define YDSXGR_BUF441OUTVOLR 0x00B2 +#define YDSXGR_BUF441LOOPVOL 0x00B4 +#define YDSXGR_BUF441LOOPVOLL 0x00B4 +#define YDSXGR_BUF441LOOPVOLR 0x00B6 +#define YDSXGR_SPDIFOUTVOL2 0x00B8 +#define YDSXGR_SPDIFOUTVOL2L 0x00B8 +#define YDSXGR_SPDIFOUTVOL2R 0x00BA +#define YDSXGR_SPDIFLOOPVOL2 0x00BC +#define YDSXGR_SPDIFLOOPVOL2L 0x00BC +#define YDSXGR_SPDIFLOOPVOL2R 0x00BE +#define YDSXGR_ADCSLOTSR 0x00C0 +#define YDSXGR_RECSLOTSR 0x00C4 +#define YDSXGR_ADCFORMAT 0x00C8 +#define YDSXGR_RECFORMAT 0x00CC +#define YDSXGR_P44SLOTSR 0x00D0 +#define YDSXGR_STATUS 0x0100 +#define YDSXGR_CTRLSELECT 0x0104 +#define YDSXGR_MODE 0x0108 +#define YDSXGR_SAMPLECOUNT 0x010C +#define YDSXGR_NUMOFSAMPLES 0x0110 +#define YDSXGR_CONFIG 0x0114 +#define YDSXGR_PLAYCTRLSIZE 0x0140 +#define YDSXGR_RECCTRLSIZE 0x0144 +#define YDSXGR_EFFCTRLSIZE 0x0148 +#define YDSXGR_WORKSIZE 0x014C +#define YDSXGR_MAPOFREC 0x0150 +#define YDSXGR_MAPOFEFFECT 0x0154 +#define YDSXGR_PLAYCTRLBASE 0x0158 +#define YDSXGR_RECCTRLBASE 0x015C +#define YDSXGR_EFFCTRLBASE 0x0160 +#define YDSXGR_WORKBASE 0x0164 +#define YDSXGR_DSPINSTRAM 0x1000 +#define YDSXGR_CTRLINSTRAM 0x4000 + +#define YDSXG_AC97READCMD 0x8000 +#define YDSXG_AC97WRITECMD 0x0000 + +#define PCIR_DSXGCTRL 0x48 + +#define YDSXG_DSPLENGTH 0x0080 +#define YDSXG_CTRLLENGTH 0x3000 + +#define YDSXG_DEFAULT_WORK_SIZE 0x0400 + +#define YDSXG_PLAYBACK_VOICES 64 +#define YDSXG_CAPTURE_VOICES 2 +#define YDSXG_EFFECT_VOICES 5 + +/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ +#define NR_AC97 2 + +#define YMF_SAMPF 256 /* Samples per frame @48000 */ + +/* + * The slot/voice control bank (2 of these per voice) + */ + +typedef struct stru_ymfpci_playback_bank { + u32 format; + u32 loop_default; + u32 base; /* 32-bit address */ + u32 loop_start; /* 32-bit offset */ + u32 loop_end; /* 32-bit offset */ + u32 loop_frac; /* 8-bit fraction - loop_start */ + u32 delta_end; /* pitch delta end */ + u32 lpfK_end; + u32 eg_gain_end; + u32 left_gain_end; + u32 right_gain_end; + u32 eff1_gain_end; + u32 eff2_gain_end; + u32 eff3_gain_end; + u32 lpfQ; + u32 status; /* P3: Always 0 for some reason. */ + u32 num_of_frames; + u32 loop_count; + u32 start; /* P3: J. reads this to know where chip is. */ + u32 start_frac; + u32 delta; + u32 lpfK; + u32 eg_gain; + u32 left_gain; + u32 right_gain; + u32 eff1_gain; + u32 eff2_gain; + u32 eff3_gain; + u32 lpfD1; + u32 lpfD2; +} ymfpci_playback_bank_t; + +typedef struct stru_ymfpci_capture_bank { + u32 base; /* 32-bit address */ + u32 loop_end; /* 32-bit offset */ + u32 start; /* 32-bit offset */ + u32 num_of_loops; /* counter */ +} ymfpci_capture_bank_t; + +typedef struct stru_ymfpci_effect_bank { + u32 base; /* 32-bit address */ + u32 loop_end; /* 32-bit offset */ + u32 start; /* 32-bit offset */ + u32 temp; +} ymfpci_effect_bank_t; + +typedef struct stru_ymfpci_voice ymfpci_voice_t; +typedef struct ymf_pcm ymfpci_pcm_t; +/* + * Throughout the code Yaroslav names YMF unit pointer "codec" + * even though it does not correspond to any codec. Must be historic. + * We replace it with "unit" over time. + * AC97 parts use "codec" to denote a codec, naturally. + */ +typedef struct ymf_unit ymfpci_t; + +typedef enum { + YMFPCI_PCM, + YMFPCI_SYNTH, + YMFPCI_MIDI +} ymfpci_voice_type_t; + +struct stru_ymfpci_voice { + ymfpci_t *codec; + int number; + int use: 1, + pcm: 1, + synth: 1, + midi: 1; + ymfpci_playback_bank_t *bank; + void (*interrupt)(ymfpci_t *codec, ymfpci_voice_t *voice); + ymfpci_pcm_t *ypcm; +}; + +typedef enum { + PLAYBACK_VOICE, + CAPTURE_REC, + CAPTURE_AC97, + EFFECT_DRY_LEFT, + EFFECT_DRY_RIGHT, + EFFECT_EFF1, + EFFECT_EFF2, + EFFECT_EFF3 +} ymfpci_pcm_type_t; + +struct ymf_pcm { + ymfpci_t *codec; + ymfpci_pcm_type_t type; + struct ymf_state *state; + ymfpci_voice_t *voices[2]; /* playback only */ + int running; // + + int spdif; +}; + +struct ymf_unit { + u8 rev; /* PCI revision */ + void *reg_area_virt; + void *work_ptr; // + + + unsigned int bank_size_playback; + unsigned int bank_size_capture; + unsigned int bank_size_effect; + unsigned int work_size; + + void *bank_base_playback; // + + void *bank_base_capture; // + + void *bank_base_effect; // + + void *work_base; // + + + u32 *ctrl_playback; + ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2]; + ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2]; + ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2]; + + int start_count; + + u32 active_bank; + ymfpci_voice_t voices[64]; + + struct ac97_codec *ac97_codec[NR_AC97]; + u16 ac97_features; + + struct pci_dev *pci; + + spinlock_t reg_lock; + spinlock_t voice_lock; + + /* soundcore stuff */ + int dev_audio; + struct semaphore open_sem; + + struct list_head ymf_devs; + struct ymf_state *states[1]; // * + /* ypcm may be the same thing as state, but not for record, effects. */ +}; + +/* + * "Software" or virtual channel, an instance of opened /dev/dsp. + */ + +struct ymf_dmabuf { + + /* OSS buffer management stuff */ + void *rawbuf; + unsigned buforder; + unsigned numfrag; + unsigned fragshift; + + /* our buffer acts like a circular ring */ + unsigned hwptr; /* where dma last started */ + unsigned swptr; /* where driver last clear/filled */ + int count; /* fill count */ + unsigned total_bytes; /* total bytes dmaed by hardware */ + + unsigned error; /* number of over/underruns */ + wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */ + + /* redundant, but makes calculations easier */ + unsigned fragsize; + unsigned dmasize; /* Total rawbuf[] size */ + unsigned fragsamples; + + /* OSS stuff */ + unsigned mapped:1; + unsigned ready:1; + unsigned ossfragshift; + int ossmaxfrags; + unsigned subdivision; +}; + +struct ymf_pcm_format { + int format; /* OSS format */ + int rate; /* rate in Hz */ + int voices; /* number of voices */ + int shift; /* redundant, computed from the above */ +}; + +struct ymf_state { + struct ymf_unit *unit; /* backpointer */ + + /* virtual channel number */ + int virt; // * unused a.t.m. + + struct ymf_pcm ypcm; // * + struct ymf_dmabuf dmabuf; // * + struct ymf_pcm_format format; // * +}; + +#endif /* __YMFPCI_H */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/sound/ymfpci_image.h linux/drivers/sound/ymfpci_image.h --- v2.4.0-test11/linux/drivers/sound/ymfpci_image.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/sound/ymfpci_image.h Sun Dec 3 23:58:10 2000 @@ -0,0 +1,1565 @@ +#ifndef _HWMCODE_ +#define _HWMCODE_ + +static unsigned long int DspInst[] = { + 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, + 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, + 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, + 0x0000c07b, 0x00050c3f, 0x0121503c, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000 +}; + +static unsigned long int CntrlInst[] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x001A82, 0x032D0D, 0x000810, 0x10043A, + 0x02D38D, 0x000810, 0x18043A, 0x00010D, + 0x020015, 0x0000FD, 0x000020, 0x038860, + 0x039060, 0x038060, 0x038040, 0x038040, + 0x038040, 0x018040, 0x000A7D, 0x038040, + 0x038040, 0x018040, 0x200402, 0x000882, + 0x08001A, 0x000904, 0x015986, 0x000007, + 0x260007, 0x000007, 0x000007, 0x018A06, + 0x000007, 0x030C8D, 0x000810, 0x18043A, + 0x260007, 0x00087D, 0x018042, 0x00160A, + 0x04A206, 0x000007, 0x00218D, 0x000810, + 0x08043A, 0x21C206, 0x000007, 0x0007FD, + 0x018042, 0x08000A, 0x000904, 0x029386, + 0x000195, 0x090D04, 0x000007, 0x000820, + 0x0000F5, 0x000B7D, 0x01F060, 0x0000FD, + 0x032206, 0x018040, 0x000A7D, 0x038042, + 0x13804A, 0x18000A, 0x001820, 0x059060, + 0x058860, 0x018040, 0x0000FD, 0x018042, + 0x70000A, 0x000115, 0x071144, 0x032386, + 0x030000, 0x007020, 0x034A06, 0x018040, + 0x00348D, 0x000810, 0x08043A, 0x21EA06, + 0x000007, 0x02D38D, 0x000810, 0x18043A, + 0x018206, 0x000007, 0x240007, 0x000F8D, + 0x000810, 0x00163A, 0x002402, 0x005C02, + 0x0028FD, 0x000020, 0x018040, 0x08000D, + 0x000815, 0x510984, 0x000007, 0x00004D, + 0x000E5D, 0x000E02, 0x00418D, 0x000810, + 0x08043A, 0x2C8A06, 0x000007, 0x00008D, + 0x000924, 0x000F02, 0x00458D, 0x000810, + 0x08043A, 0x2C8A06, 0x000007, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x018386, 0x000007, 0x01AA06, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x218086, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x055A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x034986, 0x000007, 0x002104, 0x034986, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x06C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00688D, 0x000810, 0x08043A, 0x288A06, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x060206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x215886, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x212086, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x07DA86, 0x00057D, 0x002820, + 0x03B060, 0x07F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x07FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x008D8D, 0x000810, + 0x08043A, 0x288A06, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x095186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x007FBD, 0x383DC4, + 0x000007, 0x001A7D, 0x001375, 0x018042, + 0x09004A, 0x10000A, 0x0B8D04, 0x139504, + 0x000007, 0x000820, 0x019060, 0x001104, + 0x212086, 0x010040, 0x0017FD, 0x018042, + 0x08000A, 0x000904, 0x212286, 0x000007, + 0x00197D, 0x038042, 0x09804A, 0x10000A, + 0x000924, 0x001664, 0x0011FD, 0x038042, + 0x2B804A, 0x19804A, 0x00008D, 0x218944, + 0x000007, 0x002244, 0x0AE186, 0x000007, + 0x001A64, 0x002A24, 0x00197D, 0x080102, + 0x100122, 0x000820, 0x039060, 0x018040, + 0x003DFD, 0x00008D, 0x000820, 0x018040, + 0x001375, 0x001A7D, 0x010042, 0x09804A, + 0x10000A, 0x00021D, 0x0189E4, 0x2992E4, + 0x309144, 0x000007, 0x00060D, 0x000A15, + 0x000C1D, 0x001025, 0x00A9E4, 0x012BE4, + 0x000464, 0x01B3E4, 0x0232E4, 0x000464, + 0x000464, 0x000464, 0x000464, 0x00040D, + 0x08B1C4, 0x000007, 0x000820, 0x000BF5, + 0x030040, 0x00197D, 0x038042, 0x09804A, + 0x000A24, 0x08000A, 0x080E64, 0x000007, + 0x100122, 0x000820, 0x031060, 0x010040, + 0x0064AC, 0x00027D, 0x000020, 0x018040, + 0x00107D, 0x018042, 0x0011FD, 0x3B804A, + 0x09804A, 0x20000A, 0x000095, 0x1A1144, + 0x00A144, 0x0D2086, 0x00040D, 0x00B984, + 0x0D2186, 0x0018FD, 0x018042, 0x0010FD, + 0x09804A, 0x28000A, 0x000095, 0x010924, + 0x002A64, 0x0D1186, 0x000007, 0x002904, + 0x0D2286, 0x000007, 0x0D2A06, 0x080002, + 0x00008D, 0x00387D, 0x000820, 0x018040, + 0x00127D, 0x018042, 0x10000A, 0x003904, + 0x0DD186, 0x00080D, 0x7FFFB5, 0x00B984, + 0x0DA186, 0x000025, 0x0E7A06, 0x00002D, + 0x000015, 0x00082D, 0x02C78D, 0x000820, + 0x0EC206, 0x00000D, 0x7F8035, 0x00B984, + 0x0E7186, 0x400025, 0x00008D, 0x110944, + 0x000007, 0x00018D, 0x109504, 0x000007, + 0x009164, 0x000424, 0x000424, 0x000424, + 0x100102, 0x280002, 0x02C68D, 0x000820, + 0x0EC206, 0x00018D, 0x00042D, 0x00008D, + 0x109504, 0x000007, 0x00020D, 0x109184, + 0x000007, 0x02C70D, 0x000820, 0x00008D, + 0x0038FD, 0x018040, 0x003BFD, 0x001020, + 0x03A860, 0x000815, 0x313184, 0x212184, + 0x000007, 0x03B060, 0x03A060, 0x018040, + 0x0022FD, 0x000095, 0x010924, 0x000424, + 0x000424, 0x001264, 0x100102, 0x000820, + 0x039060, 0x018040, 0x001924, 0x00FB8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x000424, + 0x000424, 0x00117D, 0x018042, 0x08000A, + 0x000A24, 0x280502, 0x280C02, 0x09800D, + 0x000820, 0x0002FD, 0x018040, 0x200007, + 0x0022FD, 0x018042, 0x08000A, 0x000095, + 0x280DC4, 0x011924, 0x00197D, 0x018042, + 0x0011FD, 0x09804A, 0x10000A, 0x0000B5, + 0x113144, 0x0A8D04, 0x000007, 0x080A44, + 0x129504, 0x000007, 0x0023FD, 0x001020, + 0x038040, 0x101244, 0x000007, 0x000820, + 0x039060, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x10FA86, 0x000007, + 0x003BFD, 0x000100, 0x000A10, 0x0B807A, + 0x13804A, 0x090984, 0x000007, 0x000095, + 0x013D04, 0x118086, 0x10000A, 0x100002, + 0x090984, 0x000007, 0x038042, 0x11804A, + 0x090D04, 0x000007, 0x10000A, 0x090D84, + 0x000007, 0x00257D, 0x000820, 0x018040, + 0x00010D, 0x000810, 0x28143A, 0x00127D, + 0x018042, 0x20000A, 0x00197D, 0x018042, + 0x00117D, 0x31804A, 0x10000A, 0x003124, + 0x01280D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x300102, 0x003124, 0x000424, 0x000424, + 0x001224, 0x280502, 0x001A4C, 0x130186, + 0x700002, 0x00002D, 0x030000, 0x00387D, + 0x018042, 0x10000A, 0x132A06, 0x002124, + 0x0000AD, 0x100002, 0x00010D, 0x000924, + 0x006B24, 0x01368D, 0x00397D, 0x000820, + 0x058040, 0x038042, 0x09844A, 0x000606, + 0x08040A, 0x003264, 0x00008D, 0x000A24, + 0x001020, 0x00227D, 0x018040, 0x013C0D, + 0x000810, 0x08043A, 0x29D206, 0x000007, + 0x002820, 0x00207D, 0x018040, 0x00117D, + 0x038042, 0x13804A, 0x33800A, 0x00387D, + 0x018042, 0x08000A, 0x000904, 0x163A86, + 0x000007, 0x00008D, 0x030964, 0x01478D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x380102, + 0x000424, 0x000424, 0x001224, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x14A286, + 0x000007, 0x280502, 0x001A4C, 0x163986, + 0x000007, 0x032164, 0x00632C, 0x003DFD, + 0x018042, 0x08000A, 0x000095, 0x090904, + 0x000007, 0x000820, 0x001A4C, 0x156186, + 0x018040, 0x030000, 0x157A06, 0x002124, + 0x00010D, 0x000924, 0x006B24, 0x015B8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x003A64, + 0x000095, 0x001224, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x15DA86, 0x000007, + 0x01628D, 0x000810, 0x08043A, 0x29D206, + 0x000007, 0x14D206, 0x000007, 0x007020, + 0x08010A, 0x10012A, 0x0020FD, 0x038860, + 0x039060, 0x018040, 0x00227D, 0x018042, + 0x003DFD, 0x08000A, 0x31844A, 0x000904, + 0x16D886, 0x18008B, 0x00008D, 0x189904, + 0x00312C, 0x17AA06, 0x000007, 0x00324C, + 0x173386, 0x000007, 0x001904, 0x173086, + 0x000007, 0x000095, 0x199144, 0x00222C, + 0x003124, 0x00636C, 0x000E3D, 0x001375, + 0x000BFD, 0x010042, 0x09804A, 0x10000A, + 0x038AEC, 0x0393EC, 0x00224C, 0x17A986, + 0x000007, 0x00008D, 0x189904, 0x00226C, + 0x00322C, 0x30050A, 0x301DAB, 0x002083, + 0x0018FD, 0x018042, 0x08000A, 0x018924, + 0x300502, 0x001083, 0x001875, 0x010042, + 0x10000A, 0x00008D, 0x010924, 0x001375, + 0x330542, 0x330CCB, 0x332CCB, 0x3334CB, + 0x333CCB, 0x3344CB, 0x334CCB, 0x3354CB, + 0x305C8B, 0x006083, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x187A86, 0x000007, + 0x001E2D, 0x0005FD, 0x018042, 0x08000A, + 0x028924, 0x280502, 0x00060D, 0x000810, + 0x280C3A, 0x00008D, 0x000810, 0x28143A, + 0x0A808D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x001275, 0x030042, 0x21004A, + 0x00008D, 0x1A0944, 0x000007, 0x01980D, + 0x000810, 0x08043A, 0x2B2206, 0x000007, + 0x0001F5, 0x030042, 0x0D004A, 0x10000A, + 0x089144, 0x000007, 0x000820, 0x010040, + 0x0025F5, 0x0A3144, 0x000007, 0x000820, + 0x032860, 0x030040, 0x00217D, 0x038042, + 0x0B804A, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x00008D, 0x000124, 0x00012C, + 0x000E64, 0x001A64, 0x00636C, 0x08010A, + 0x10012A, 0x000820, 0x031060, 0x030040, + 0x0020FD, 0x018042, 0x08000A, 0x00227D, + 0x018042, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x00197D, 0x018042, 0x08000A, + 0x0022FD, 0x038042, 0x10000A, 0x000820, + 0x031060, 0x030040, 0x090D04, 0x000007, + 0x000820, 0x030040, 0x038042, 0x0B804A, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x038042, 0x13804A, 0x19804A, 0x110D04, + 0x198D04, 0x000007, 0x08000A, 0x001020, + 0x031860, 0x030860, 0x030040, 0x00008D, + 0x0B0944, 0x000007, 0x000820, 0x010040, + 0x0005F5, 0x030042, 0x08000A, 0x000820, + 0x010040, 0x0000F5, 0x010042, 0x08000A, + 0x000904, 0x1C6086, 0x001E75, 0x030042, + 0x01044A, 0x000C0A, 0x1C7206, 0x000007, + 0x000402, 0x000C02, 0x00177D, 0x001AF5, + 0x018042, 0x03144A, 0x031C4A, 0x03244A, + 0x032C4A, 0x03344A, 0x033C4A, 0x03444A, + 0x004C0A, 0x00043D, 0x0013F5, 0x001AFD, + 0x030042, 0x0B004A, 0x1B804A, 0x13804A, + 0x20000A, 0x089144, 0x19A144, 0x0389E4, + 0x0399EC, 0x005502, 0x005D0A, 0x030042, + 0x0B004A, 0x1B804A, 0x13804A, 0x20000A, + 0x089144, 0x19A144, 0x0389E4, 0x0399EC, + 0x006502, 0x006D0A, 0x030042, 0x0B004A, + 0x19004A, 0x2B804A, 0x13804A, 0x21804A, + 0x30000A, 0x089144, 0x19A144, 0x2AB144, + 0x0389E4, 0x0399EC, 0x007502, 0x007D0A, + 0x03A9E4, 0x000702, 0x00107D, 0x000415, + 0x018042, 0x08000A, 0x0109E4, 0x000F02, + 0x002AF5, 0x0019FD, 0x010042, 0x09804A, + 0x10000A, 0x000934, 0x001674, 0x0029F5, + 0x010042, 0x10000A, 0x00917C, 0x002075, + 0x010042, 0x08000A, 0x000904, 0x1ED286, + 0x0026F5, 0x0027F5, 0x030042, 0x09004A, + 0x10000A, 0x000A3C, 0x00167C, 0x001A75, + 0x000BFD, 0x010042, 0x51804A, 0x48000A, + 0x160007, 0x001075, 0x010042, 0x282C0A, + 0x281D12, 0x282512, 0x001F32, 0x1E0007, + 0x0E0007, 0x001975, 0x010042, 0x002DF5, + 0x0D004A, 0x10000A, 0x009144, 0x1FB286, + 0x010042, 0x28340A, 0x000E5D, 0x00008D, + 0x000375, 0x000820, 0x010040, 0x05D2F4, + 0x54D104, 0x00735C, 0x205386, 0x000007, + 0x0C0007, 0x080007, 0x0A0007, 0x02040D, + 0x000810, 0x08043A, 0x332206, 0x000007, + 0x205A06, 0x000007, 0x080007, 0x002275, + 0x010042, 0x20000A, 0x002104, 0x212086, + 0x001E2D, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x209286, 0x000007, 0x002010, + 0x30043A, 0x00057D, 0x0180C3, 0x08000A, + 0x028924, 0x280502, 0x280C02, 0x0A810D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x0004FD, 0x018042, 0x70000A, 0x030000, + 0x007020, 0x06FA06, 0x018040, 0x02180D, + 0x000810, 0x08043A, 0x2B2206, 0x000007, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x218A86, 0x000007, 0x01F206, 0x000007, + 0x000875, 0x0009FD, 0x00010D, 0x220A06, + 0x000295, 0x000B75, 0x00097D, 0x00000D, + 0x000515, 0x010042, 0x18000A, 0x001904, + 0x287886, 0x0006F5, 0x001020, 0x010040, + 0x0004F5, 0x000820, 0x010040, 0x000775, + 0x010042, 0x09804A, 0x10000A, 0x001124, + 0x000904, 0x22BA86, 0x000815, 0x080102, + 0x101204, 0x22DA06, 0x000575, 0x081204, + 0x000007, 0x100102, 0x000575, 0x000425, + 0x021124, 0x100102, 0x000820, 0x031060, + 0x010040, 0x001924, 0x287886, 0x00008D, + 0x000464, 0x009D04, 0x278886, 0x180102, + 0x000575, 0x010042, 0x28040A, 0x00018D, + 0x000924, 0x280D02, 0x00000D, 0x000924, + 0x281502, 0x10000D, 0x000820, 0x0002F5, + 0x010040, 0x200007, 0x001175, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x23C286, + 0x000007, 0x000100, 0x080B20, 0x130B60, + 0x1B0B60, 0x030A60, 0x010040, 0x050042, + 0x3D004A, 0x35004A, 0x2D004A, 0x20000A, + 0x0006F5, 0x010042, 0x28140A, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x24CA86, 0x004015, 0x000095, 0x010D04, + 0x24B886, 0x100022, 0x10002A, 0x24E206, + 0x000007, 0x333104, 0x2AA904, 0x000007, + 0x032124, 0x280502, 0x001124, 0x000424, + 0x000424, 0x003224, 0x00292C, 0x00636C, + 0x25F386, 0x000007, 0x02B164, 0x000464, + 0x000464, 0x00008D, 0x000A64, 0x280D02, + 0x10008D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x00008D, 0x38B904, 0x000007, + 0x03296C, 0x30010A, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x25BA86, 0x000007, + 0x02312C, 0x28050A, 0x00008D, 0x01096C, + 0x280D0A, 0x10010D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x001124, 0x000424, + 0x000424, 0x003224, 0x300102, 0x032944, + 0x267A86, 0x000007, 0x300002, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x26C086, 0x003124, 0x000464, 0x300102, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x26CA86, 0x000007, 0x003124, 0x300502, + 0x003924, 0x300583, 0x000883, 0x0005F5, + 0x010042, 0x28040A, 0x00008D, 0x008124, + 0x280D02, 0x00008D, 0x008124, 0x281502, + 0x10018D, 0x000820, 0x0002F5, 0x010040, + 0x220007, 0x001025, 0x000575, 0x030042, + 0x09004A, 0x10000A, 0x0A0904, 0x121104, + 0x000007, 0x001020, 0x050860, 0x050040, + 0x0006FD, 0x018042, 0x09004A, 0x10000A, + 0x0000A5, 0x0A0904, 0x121104, 0x000007, + 0x000820, 0x019060, 0x010040, 0x0002F5, + 0x010042, 0x08000A, 0x000904, 0x284286, + 0x000007, 0x230A06, 0x000007, 0x000606, + 0x000007, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x289286, 0x000007, 0x000100, + 0x080B20, 0x138B60, 0x1B8B60, 0x238B60, + 0x2B8B60, 0x338B60, 0x3B8B60, 0x438B60, + 0x4B8B60, 0x538B60, 0x5B8B60, 0x638B60, + 0x6B8B60, 0x738B60, 0x7B8B60, 0x038F60, + 0x0B8F60, 0x138F60, 0x1B8F60, 0x238F60, + 0x2B8F60, 0x338F60, 0x3B8F60, 0x438F60, + 0x4B8F60, 0x538F60, 0x5B8F60, 0x638F60, + 0x6B8F60, 0x738F60, 0x7B8F60, 0x038A60, + 0x000606, 0x018040, 0x00008D, 0x000A64, + 0x280D02, 0x000A24, 0x00027D, 0x018042, + 0x10000A, 0x001224, 0x0003FD, 0x018042, + 0x08000A, 0x000904, 0x2A8286, 0x000007, + 0x00018D, 0x000A24, 0x000464, 0x000464, + 0x080102, 0x000924, 0x000424, 0x000424, + 0x100102, 0x02000D, 0x009144, 0x2AD986, + 0x000007, 0x0001FD, 0x018042, 0x08000A, + 0x000A44, 0x2ABB86, 0x018042, 0x0A000D, + 0x000820, 0x0002FD, 0x018040, 0x200007, + 0x00027D, 0x001020, 0x000606, 0x018040, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x2B2A86, 0x000007, 0x00037D, 0x018042, + 0x08000A, 0x000904, 0x2B5A86, 0x000007, + 0x000075, 0x002E7D, 0x010042, 0x0B804A, + 0x000020, 0x000904, 0x000686, 0x010040, + 0x31844A, 0x30048B, 0x000883, 0x00008D, + 0x000810, 0x28143A, 0x00008D, 0x000810, + 0x280C3A, 0x000675, 0x010042, 0x08000A, + 0x003815, 0x010924, 0x280502, 0x0B000D, + 0x000820, 0x0002F5, 0x010040, 0x000606, + 0x220007, 0x000464, 0x000464, 0x000606, + 0x000007, 0x000134, 0x007F8D, 0x00093C, + 0x281D12, 0x282512, 0x001F32, 0x0E0007, + 0x00010D, 0x00037D, 0x000820, 0x018040, + 0x05D2F4, 0x000007, 0x080007, 0x00037D, + 0x018042, 0x08000A, 0x000904, 0x2D0286, + 0x000007, 0x000606, 0x000007, 0x000007, + 0x000012, 0x100007, 0x320007, 0x600007, + 0x100080, 0x48001A, 0x004904, 0x2D6186, + 0x000007, 0x001210, 0x58003A, 0x000145, + 0x5C5D04, 0x000007, 0x000080, 0x48001A, + 0x004904, 0x2DB186, 0x000007, 0x001210, + 0x50003A, 0x005904, 0x2E0886, 0x000045, + 0x0000C5, 0x7FFFF5, 0x7FFF7D, 0x07D524, + 0x004224, 0x500102, 0x200502, 0x000082, + 0x40001A, 0x004104, 0x2E3986, 0x000007, + 0x003865, 0x40001A, 0x004020, 0x00104D, + 0x04C184, 0x301B86, 0x000040, 0x040007, + 0x000165, 0x000145, 0x004020, 0x000040, + 0x000765, 0x080080, 0x40001A, 0x004104, + 0x2EC986, 0x000007, 0x001210, 0x40003A, + 0x004104, 0x2F2286, 0x00004D, 0x0000CD, + 0x004810, 0x20043A, 0x000882, 0x40001A, + 0x004104, 0x2F3186, 0x000007, 0x004820, + 0x005904, 0x300886, 0x000040, 0x0007E5, + 0x200480, 0x2816A0, 0x3216E0, 0x3A16E0, + 0x4216E0, 0x021260, 0x000040, 0x000032, + 0x400075, 0x00007D, 0x07D574, 0x200512, + 0x000082, 0x40001A, 0x004104, 0x2FE186, + 0x000007, 0x037206, 0x640007, 0x060007, + 0x0000E5, 0x000020, 0x000040, 0x000A65, + 0x000020, 0x020040, 0x020040, 0x000040, + 0x000165, 0x000042, 0x70000A, 0x007104, + 0x30A286, 0x000007, 0x018206, 0x640007, + 0x050000, 0x007020, 0x000040, 0x037206, + 0x640007, 0x000007, 0x00306D, 0x028860, + 0x029060, 0x08000A, 0x028860, 0x008040, + 0x100012, 0x00100D, 0x009184, 0x314186, + 0x000E0D, 0x009184, 0x325186, 0x000007, + 0x300007, 0x001020, 0x003B6D, 0x008040, + 0x000080, 0x08001A, 0x000904, 0x316186, + 0x000007, 0x001220, 0x000DED, 0x008040, + 0x008042, 0x10000A, 0x40000D, 0x109544, + 0x000007, 0x001020, 0x000DED, 0x008040, + 0x008042, 0x20040A, 0x000082, 0x08001A, + 0x000904, 0x31F186, 0x000007, 0x003B6D, + 0x008042, 0x08000A, 0x000E15, 0x010984, + 0x329B86, 0x600007, 0x08001A, 0x000C15, + 0x010984, 0x328386, 0x000020, 0x1A0007, + 0x0002ED, 0x008040, 0x620007, 0x00306D, + 0x028042, 0x0A804A, 0x000820, 0x0A804A, + 0x000606, 0x10804A, 0x000007, 0x282512, + 0x001F32, 0x05D2F4, 0x54D104, 0x00735C, + 0x000786, 0x000007, 0x0C0007, 0x0A0007, + 0x1C0007, 0x003465, 0x020040, 0x004820, + 0x025060, 0x40000A, 0x024060, 0x000040, + 0x454944, 0x000007, 0x004020, 0x003AE5, + 0x000040, 0x0028E5, 0x000042, 0x48000A, + 0x004904, 0x386886, 0x002C65, 0x000042, + 0x40000A, 0x0000D5, 0x454104, 0x000007, + 0x000655, 0x054504, 0x34F286, 0x0001D5, + 0x054504, 0x34F086, 0x002B65, 0x000042, + 0x003AE5, 0x50004A, 0x40000A, 0x45C3D4, + 0x000007, 0x454504, 0x000007, 0x0000CD, + 0x444944, 0x000007, 0x454504, 0x000007, + 0x00014D, 0x554944, 0x000007, 0x045144, + 0x34E986, 0x002C65, 0x000042, 0x48000A, + 0x4CD104, 0x000007, 0x04C144, 0x34F386, + 0x000007, 0x160007, 0x002CE5, 0x040042, + 0x40000A, 0x004020, 0x000040, 0x002965, + 0x000042, 0x40000A, 0x004104, 0x356086, + 0x000007, 0x002402, 0x36A206, 0x005C02, + 0x0025E5, 0x000042, 0x40000A, 0x004274, + 0x002AE5, 0x000042, 0x40000A, 0x004274, + 0x500112, 0x0029E5, 0x000042, 0x40000A, + 0x004234, 0x454104, 0x000007, 0x004020, + 0x000040, 0x003EE5, 0x000020, 0x000040, + 0x002DE5, 0x400152, 0x50000A, 0x045144, + 0x364A86, 0x0000C5, 0x003EE5, 0x004020, + 0x000040, 0x002BE5, 0x000042, 0x40000A, + 0x404254, 0x000007, 0x002AE5, 0x004020, + 0x000040, 0x500132, 0x040134, 0x005674, + 0x0029E5, 0x020042, 0x42000A, 0x000042, + 0x50000A, 0x05417C, 0x0028E5, 0x000042, + 0x48000A, 0x0000C5, 0x4CC144, 0x371086, + 0x0026E5, 0x0027E5, 0x020042, 0x40004A, + 0x50000A, 0x00423C, 0x00567C, 0x0028E5, + 0x004820, 0x000040, 0x281D12, 0x282512, + 0x001F72, 0x002965, 0x000042, 0x40000A, + 0x004104, 0x37AA86, 0x0E0007, 0x160007, + 0x1E0007, 0x003EE5, 0x000042, 0x40000A, + 0x004104, 0x37E886, 0x002D65, 0x000042, + 0x28340A, 0x003465, 0x020042, 0x42004A, + 0x004020, 0x4A004A, 0x50004A, 0x05D2F4, + 0x54D104, 0x00735C, 0x385186, 0x000007, + 0x000606, 0x080007, 0x0C0007, 0x080007, + 0x0A0007, 0x0001E5, 0x020045, 0x004020, + 0x000060, 0x000365, 0x000040, 0x002E65, + 0x001A20, 0x0A1A60, 0x000040, 0x003465, + 0x020042, 0x42004A, 0x004020, 0x4A004A, + 0x000606, 0x50004A, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; + +// -------------------------------------------- +// DS-1E Controller InstructionRAM Code +// 1999/06/21 +// Buf441 slot is Enabled. +// -------------------------------------------- +// 04/09 creat +// 04/12 stop nise fix +// 06/21 WorkingOff timming +static unsigned long int CntrlInst1E[] = { + 0x000007, 0x240007, 0x0C0007, 0x1C0007, + 0x060007, 0x700002, 0x000020, 0x030040, + 0x007104, 0x004286, 0x030040, 0x000F0D, + 0x000810, 0x20043A, 0x000282, 0x00020D, + 0x000810, 0x20043A, 0x001282, 0x200E82, + 0x00800D, 0x000810, 0x20043A, 0x001A82, + 0x03460D, 0x000810, 0x10043A, 0x02EC0D, + 0x000810, 0x18043A, 0x00010D, 0x020015, + 0x0000FD, 0x000020, 0x038860, 0x039060, + 0x038060, 0x038040, 0x038040, 0x038040, + 0x018040, 0x000A7D, 0x038040, 0x038040, + 0x018040, 0x200402, 0x000882, 0x08001A, + 0x000904, 0x017186, 0x000007, 0x260007, + 0x400007, 0x000007, 0x03258D, 0x000810, + 0x18043A, 0x260007, 0x284402, 0x00087D, + 0x018042, 0x00160A, 0x05A206, 0x000007, + 0x440007, 0x00230D, 0x000810, 0x08043A, + 0x22FA06, 0x000007, 0x0007FD, 0x018042, + 0x08000A, 0x000904, 0x02AB86, 0x000195, + 0x090D04, 0x000007, 0x000820, 0x0000F5, + 0x000B7D, 0x01F060, 0x0000FD, 0x033A06, + 0x018040, 0x000A7D, 0x038042, 0x13804A, + 0x18000A, 0x001820, 0x059060, 0x058860, + 0x018040, 0x0000FD, 0x018042, 0x70000A, + 0x000115, 0x071144, 0x033B86, 0x030000, + 0x007020, 0x036206, 0x018040, 0x00360D, + 0x000810, 0x08043A, 0x232206, 0x000007, + 0x02EC0D, 0x000810, 0x18043A, 0x019A06, + 0x000007, 0x240007, 0x000F8D, 0x000810, + 0x00163A, 0x002402, 0x005C02, 0x0028FD, + 0x000020, 0x018040, 0x08000D, 0x000815, + 0x510984, 0x000007, 0x00004D, 0x000E5D, + 0x000E02, 0x00430D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x00008D, 0x000924, + 0x000F02, 0x00470D, 0x000810, 0x08043A, + 0x2E1206, 0x000007, 0x480480, 0x001210, + 0x28043A, 0x00778D, 0x000810, 0x280C3A, + 0x00068D, 0x000810, 0x28143A, 0x284402, + 0x03258D, 0x000810, 0x18043A, 0x07FF8D, + 0x000820, 0x0002FD, 0x018040, 0x260007, + 0x200007, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x051286, 0x000007, 0x240007, + 0x02EC0D, 0x000810, 0x18043A, 0x00387D, + 0x018042, 0x08000A, 0x001015, 0x010984, + 0x019B86, 0x000007, 0x01B206, 0x000007, + 0x0008FD, 0x018042, 0x18000A, 0x001904, + 0x22B886, 0x280007, 0x001810, 0x28043A, + 0x280C02, 0x00000D, 0x000810, 0x28143A, + 0x08808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00020D, 0x189904, 0x000007, + 0x00402D, 0x0000BD, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x065A86, 0x000007, + 0x000100, 0x000A20, 0x00047D, 0x018040, + 0x018042, 0x20000A, 0x003015, 0x012144, + 0x036186, 0x000007, 0x002104, 0x036186, + 0x000007, 0x000F8D, 0x000810, 0x280C3A, + 0x023944, 0x07C986, 0x000007, 0x001810, + 0x28043A, 0x08810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x002810, 0x78003A, + 0x00788D, 0x000810, 0x08043A, 0x2A1206, + 0x000007, 0x00400D, 0x001015, 0x189904, + 0x292904, 0x393904, 0x000007, 0x070206, + 0x000007, 0x0004F5, 0x00007D, 0x000020, + 0x00008D, 0x010860, 0x018040, 0x00047D, + 0x038042, 0x21804A, 0x18000A, 0x021944, + 0x229086, 0x000007, 0x004075, 0x71F104, + 0x000007, 0x010042, 0x28000A, 0x002904, + 0x225886, 0x000007, 0x003C0D, 0x30A904, + 0x000007, 0x00077D, 0x018042, 0x08000A, + 0x000904, 0x08DA86, 0x00057D, 0x002820, + 0x03B060, 0x08F206, 0x018040, 0x003020, + 0x03A860, 0x018040, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x08FA86, 0x000007, + 0x00057D, 0x018042, 0x28040A, 0x000E8D, + 0x000810, 0x280C3A, 0x00000D, 0x000810, + 0x28143A, 0x09000D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x003DFD, 0x000020, + 0x018040, 0x00107D, 0x009D8D, 0x000810, + 0x08043A, 0x2A1206, 0x000007, 0x000815, + 0x08001A, 0x010984, 0x0A5186, 0x00137D, + 0x200500, 0x280F20, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x038A60, 0x018040, 0x00107D, 0x018042, + 0x08000A, 0x000215, 0x010984, 0x3A8186, + 0x000007, 0x007FBD, 0x383DC4, 0x000007, + 0x001A7D, 0x001375, 0x018042, 0x09004A, + 0x10000A, 0x0B8D04, 0x139504, 0x000007, + 0x000820, 0x019060, 0x001104, 0x225886, + 0x010040, 0x0017FD, 0x018042, 0x08000A, + 0x000904, 0x225A86, 0x000007, 0x00197D, + 0x038042, 0x09804A, 0x10000A, 0x000924, + 0x001664, 0x0011FD, 0x038042, 0x2B804A, + 0x19804A, 0x00008D, 0x218944, 0x000007, + 0x002244, 0x0C1986, 0x000007, 0x001A64, + 0x002A24, 0x00197D, 0x080102, 0x100122, + 0x000820, 0x039060, 0x018040, 0x003DFD, + 0x00008D, 0x000820, 0x018040, 0x001375, + 0x001A7D, 0x010042, 0x09804A, 0x10000A, + 0x00021D, 0x0189E4, 0x2992E4, 0x309144, + 0x000007, 0x00060D, 0x000A15, 0x000C1D, + 0x001025, 0x00A9E4, 0x012BE4, 0x000464, + 0x01B3E4, 0x0232E4, 0x000464, 0x000464, + 0x000464, 0x000464, 0x00040D, 0x08B1C4, + 0x000007, 0x000820, 0x000BF5, 0x030040, + 0x00197D, 0x038042, 0x09804A, 0x000A24, + 0x08000A, 0x080E64, 0x000007, 0x100122, + 0x000820, 0x031060, 0x010040, 0x0064AC, + 0x00027D, 0x000020, 0x018040, 0x00107D, + 0x018042, 0x0011FD, 0x3B804A, 0x09804A, + 0x20000A, 0x000095, 0x1A1144, 0x00A144, + 0x0E5886, 0x00040D, 0x00B984, 0x0E5986, + 0x0018FD, 0x018042, 0x0010FD, 0x09804A, + 0x28000A, 0x000095, 0x010924, 0x002A64, + 0x0E4986, 0x000007, 0x002904, 0x0E5A86, + 0x000007, 0x0E6206, 0x080002, 0x00008D, + 0x00387D, 0x000820, 0x018040, 0x00127D, + 0x018042, 0x10000A, 0x003904, 0x0F0986, + 0x00080D, 0x7FFFB5, 0x00B984, 0x0ED986, + 0x000025, 0x0FB206, 0x00002D, 0x000015, + 0x00082D, 0x02E00D, 0x000820, 0x0FFA06, + 0x00000D, 0x7F8035, 0x00B984, 0x0FA986, + 0x400025, 0x00008D, 0x110944, 0x000007, + 0x00018D, 0x109504, 0x000007, 0x009164, + 0x000424, 0x000424, 0x000424, 0x100102, + 0x280002, 0x02DF0D, 0x000820, 0x0FFA06, + 0x00018D, 0x00042D, 0x00008D, 0x109504, + 0x000007, 0x00020D, 0x109184, 0x000007, + 0x02DF8D, 0x000820, 0x00008D, 0x0038FD, + 0x018040, 0x003BFD, 0x001020, 0x03A860, + 0x000815, 0x313184, 0x212184, 0x000007, + 0x03B060, 0x03A060, 0x018040, 0x0022FD, + 0x000095, 0x010924, 0x000424, 0x000424, + 0x001264, 0x100102, 0x000820, 0x039060, + 0x018040, 0x001924, 0x010F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x000424, 0x000424, + 0x00117D, 0x018042, 0x08000A, 0x000A24, + 0x280502, 0x280C02, 0x09800D, 0x000820, + 0x0002FD, 0x018040, 0x200007, 0x0022FD, + 0x018042, 0x08000A, 0x000095, 0x280DC4, + 0x011924, 0x00197D, 0x018042, 0x0011FD, + 0x09804A, 0x10000A, 0x0000B5, 0x113144, + 0x0A8D04, 0x000007, 0x080A44, 0x129504, + 0x000007, 0x0023FD, 0x001020, 0x038040, + 0x101244, 0x000007, 0x000820, 0x039060, + 0x018040, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x123286, 0x000007, 0x003BFD, + 0x000100, 0x000A10, 0x0B807A, 0x13804A, + 0x090984, 0x000007, 0x000095, 0x013D04, + 0x12B886, 0x10000A, 0x100002, 0x090984, + 0x000007, 0x038042, 0x11804A, 0x090D04, + 0x000007, 0x10000A, 0x090D84, 0x000007, + 0x00257D, 0x000820, 0x018040, 0x00010D, + 0x000810, 0x28143A, 0x00127D, 0x018042, + 0x20000A, 0x00197D, 0x018042, 0x00117D, + 0x31804A, 0x10000A, 0x003124, 0x013B8D, + 0x00397D, 0x000820, 0x058040, 0x038042, + 0x09844A, 0x000606, 0x08040A, 0x300102, + 0x003124, 0x000424, 0x000424, 0x001224, + 0x280502, 0x001A4C, 0x143986, 0x700002, + 0x00002D, 0x030000, 0x00387D, 0x018042, + 0x10000A, 0x146206, 0x002124, 0x0000AD, + 0x100002, 0x00010D, 0x000924, 0x006B24, + 0x014A0D, 0x00397D, 0x000820, 0x058040, + 0x038042, 0x09844A, 0x000606, 0x08040A, + 0x003264, 0x00008D, 0x000A24, 0x001020, + 0x00227D, 0x018040, 0x014F8D, 0x000810, + 0x08043A, 0x2B5A06, 0x000007, 0x002820, + 0x00207D, 0x018040, 0x00117D, 0x038042, + 0x13804A, 0x33800A, 0x00387D, 0x018042, + 0x08000A, 0x000904, 0x177286, 0x000007, + 0x00008D, 0x030964, 0x015B0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x380102, 0x000424, + 0x000424, 0x001224, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x15DA86, 0x000007, + 0x280502, 0x001A4C, 0x177186, 0x000007, + 0x032164, 0x00632C, 0x003DFD, 0x018042, + 0x08000A, 0x000095, 0x090904, 0x000007, + 0x000820, 0x001A4C, 0x169986, 0x018040, + 0x030000, 0x16B206, 0x002124, 0x00010D, + 0x000924, 0x006B24, 0x016F0D, 0x00397D, + 0x000820, 0x058040, 0x038042, 0x09844A, + 0x000606, 0x08040A, 0x003A64, 0x000095, + 0x001224, 0x0002FD, 0x018042, 0x08000A, + 0x000904, 0x171286, 0x000007, 0x01760D, + 0x000810, 0x08043A, 0x2B5A06, 0x000007, + 0x160A06, 0x000007, 0x007020, 0x08010A, + 0x10012A, 0x0020FD, 0x038860, 0x039060, + 0x018040, 0x00227D, 0x018042, 0x003DFD, + 0x08000A, 0x31844A, 0x000904, 0x181086, + 0x18008B, 0x00008D, 0x189904, 0x00312C, + 0x18E206, 0x000007, 0x00324C, 0x186B86, + 0x000007, 0x001904, 0x186886, 0x000007, + 0x000095, 0x199144, 0x00222C, 0x003124, + 0x00636C, 0x000E3D, 0x001375, 0x000BFD, + 0x010042, 0x09804A, 0x10000A, 0x038AEC, + 0x0393EC, 0x00224C, 0x18E186, 0x000007, + 0x00008D, 0x189904, 0x00226C, 0x00322C, + 0x30050A, 0x301DAB, 0x002083, 0x0018FD, + 0x018042, 0x08000A, 0x018924, 0x300502, + 0x001083, 0x001875, 0x010042, 0x10000A, + 0x00008D, 0x010924, 0x001375, 0x330542, + 0x330CCB, 0x332CCB, 0x3334CB, 0x333CCB, + 0x3344CB, 0x334CCB, 0x3354CB, 0x305C8B, + 0x006083, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x19B286, 0x000007, 0x001E2D, + 0x0005FD, 0x018042, 0x08000A, 0x028924, + 0x280502, 0x00060D, 0x000810, 0x280C3A, + 0x00008D, 0x000810, 0x28143A, 0x0A808D, + 0x000820, 0x0002F5, 0x010040, 0x220007, + 0x001275, 0x030042, 0x21004A, 0x00008D, + 0x1A0944, 0x000007, 0x01AB8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0001F5, + 0x030042, 0x0D004A, 0x10000A, 0x089144, + 0x000007, 0x000820, 0x010040, 0x0025F5, + 0x0A3144, 0x000007, 0x000820, 0x032860, + 0x030040, 0x00217D, 0x038042, 0x0B804A, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00008D, 0x000124, 0x00012C, 0x000E64, + 0x001A64, 0x00636C, 0x08010A, 0x10012A, + 0x000820, 0x031060, 0x030040, 0x0020FD, + 0x018042, 0x08000A, 0x00227D, 0x018042, + 0x10000A, 0x000820, 0x031060, 0x030040, + 0x00197D, 0x018042, 0x08000A, 0x0022FD, + 0x038042, 0x10000A, 0x000820, 0x031060, + 0x030040, 0x090D04, 0x000007, 0x000820, + 0x030040, 0x038042, 0x0B804A, 0x10000A, + 0x000820, 0x031060, 0x030040, 0x038042, + 0x13804A, 0x19804A, 0x110D04, 0x198D04, + 0x000007, 0x08000A, 0x001020, 0x031860, + 0x030860, 0x030040, 0x00008D, 0x0B0944, + 0x000007, 0x000820, 0x010040, 0x0005F5, + 0x030042, 0x08000A, 0x000820, 0x010040, + 0x0000F5, 0x010042, 0x08000A, 0x000904, + 0x1D9886, 0x001E75, 0x030042, 0x01044A, + 0x000C0A, 0x1DAA06, 0x000007, 0x000402, + 0x000C02, 0x00177D, 0x001AF5, 0x018042, + 0x03144A, 0x031C4A, 0x03244A, 0x032C4A, + 0x03344A, 0x033C4A, 0x03444A, 0x004C0A, + 0x00043D, 0x0013F5, 0x001AFD, 0x030042, + 0x0B004A, 0x1B804A, 0x13804A, 0x20000A, + 0x089144, 0x19A144, 0x0389E4, 0x0399EC, + 0x005502, 0x005D0A, 0x030042, 0x0B004A, + 0x1B804A, 0x13804A, 0x20000A, 0x089144, + 0x19A144, 0x0389E4, 0x0399EC, 0x006502, + 0x006D0A, 0x030042, 0x0B004A, 0x19004A, + 0x2B804A, 0x13804A, 0x21804A, 0x30000A, + 0x089144, 0x19A144, 0x2AB144, 0x0389E4, + 0x0399EC, 0x007502, 0x007D0A, 0x03A9E4, + 0x000702, 0x00107D, 0x000415, 0x018042, + 0x08000A, 0x0109E4, 0x000F02, 0x002AF5, + 0x0019FD, 0x010042, 0x09804A, 0x10000A, + 0x000934, 0x001674, 0x0029F5, 0x010042, + 0x10000A, 0x00917C, 0x002075, 0x010042, + 0x08000A, 0x000904, 0x200A86, 0x0026F5, + 0x0027F5, 0x030042, 0x09004A, 0x10000A, + 0x000A3C, 0x00167C, 0x001A75, 0x000BFD, + 0x010042, 0x51804A, 0x48000A, 0x160007, + 0x001075, 0x010042, 0x282C0A, 0x281D12, + 0x282512, 0x001F32, 0x1E0007, 0x0E0007, + 0x001975, 0x010042, 0x002DF5, 0x0D004A, + 0x10000A, 0x009144, 0x20EA86, 0x010042, + 0x28340A, 0x000E5D, 0x00008D, 0x000375, + 0x000820, 0x010040, 0x05D2F4, 0x54D104, + 0x00735C, 0x218B86, 0x000007, 0x0C0007, + 0x080007, 0x0A0007, 0x02178D, 0x000810, + 0x08043A, 0x34B206, 0x000007, 0x219206, + 0x000007, 0x080007, 0x002275, 0x010042, + 0x20000A, 0x002104, 0x225886, 0x001E2D, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x21CA86, 0x000007, 0x002010, 0x30043A, + 0x00057D, 0x0180C3, 0x08000A, 0x028924, + 0x280502, 0x280C02, 0x0A810D, 0x000820, + 0x0002F5, 0x010040, 0x220007, 0x0004FD, + 0x018042, 0x70000A, 0x030000, 0x007020, + 0x07FA06, 0x018040, 0x022B8D, 0x000810, + 0x08043A, 0x2CAA06, 0x000007, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x22C286, + 0x000007, 0x020206, 0x000007, 0x000875, + 0x0009FD, 0x00010D, 0x234206, 0x000295, + 0x000B75, 0x00097D, 0x00000D, 0x000515, + 0x010042, 0x18000A, 0x001904, 0x2A0086, + 0x0006F5, 0x001020, 0x010040, 0x0004F5, + 0x000820, 0x010040, 0x000775, 0x010042, + 0x09804A, 0x10000A, 0x001124, 0x000904, + 0x23F286, 0x000815, 0x080102, 0x101204, + 0x241206, 0x000575, 0x081204, 0x000007, + 0x100102, 0x000575, 0x000425, 0x021124, + 0x100102, 0x000820, 0x031060, 0x010040, + 0x001924, 0x2A0086, 0x00008D, 0x000464, + 0x009D04, 0x291086, 0x180102, 0x000575, + 0x010042, 0x28040A, 0x00018D, 0x000924, + 0x280D02, 0x00000D, 0x000924, 0x281502, + 0x10000D, 0x000820, 0x0002F5, 0x010040, + 0x200007, 0x001175, 0x0002FD, 0x018042, + 0x08000A, 0x000904, 0x24FA86, 0x000007, + 0x000100, 0x080B20, 0x130B60, 0x1B0B60, + 0x030A60, 0x010040, 0x050042, 0x3D004A, + 0x35004A, 0x2D004A, 0x20000A, 0x0006F5, + 0x010042, 0x28140A, 0x0004F5, 0x010042, + 0x08000A, 0x000315, 0x010D04, 0x260286, + 0x004015, 0x000095, 0x010D04, 0x25F086, + 0x100022, 0x10002A, 0x261A06, 0x000007, + 0x333104, 0x2AA904, 0x000007, 0x032124, + 0x280502, 0x284402, 0x001124, 0x400102, + 0x000424, 0x000424, 0x003224, 0x00292C, + 0x00636C, 0x277386, 0x000007, 0x02B164, + 0x000464, 0x000464, 0x00008D, 0x000A64, + 0x280D02, 0x10008D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x00008D, 0x38B904, + 0x000007, 0x03296C, 0x30010A, 0x0002F5, + 0x010042, 0x08000A, 0x000904, 0x270286, + 0x000007, 0x00212C, 0x28050A, 0x00316C, + 0x00046C, 0x00046C, 0x28450A, 0x001124, + 0x006B64, 0x100102, 0x00008D, 0x01096C, + 0x280D0A, 0x10010D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x004124, 0x000424, + 0x000424, 0x003224, 0x300102, 0x032944, + 0x27FA86, 0x000007, 0x300002, 0x0004F5, + 0x010042, 0x08000A, 0x000315, 0x010D04, + 0x284086, 0x003124, 0x000464, 0x300102, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x284A86, 0x000007, 0x284402, 0x003124, + 0x300502, 0x003924, 0x300583, 0x000883, + 0x0005F5, 0x010042, 0x28040A, 0x00008D, + 0x008124, 0x280D02, 0x00008D, 0x008124, + 0x281502, 0x10018D, 0x000820, 0x0002F5, + 0x010040, 0x220007, 0x001025, 0x000575, + 0x030042, 0x09004A, 0x10000A, 0x0A0904, + 0x121104, 0x000007, 0x001020, 0x050860, + 0x050040, 0x0006FD, 0x018042, 0x09004A, + 0x10000A, 0x0000A5, 0x0A0904, 0x121104, + 0x000007, 0x000820, 0x019060, 0x010040, + 0x0002F5, 0x010042, 0x08000A, 0x000904, + 0x29CA86, 0x000007, 0x244206, 0x000007, + 0x000606, 0x000007, 0x0002F5, 0x010042, + 0x08000A, 0x000904, 0x2A1A86, 0x000007, + 0x000100, 0x080B20, 0x138B60, 0x1B8B60, + 0x238B60, 0x2B8B60, 0x338B60, 0x3B8B60, + 0x438B60, 0x4B8B60, 0x538B60, 0x5B8B60, + 0x638B60, 0x6B8B60, 0x738B60, 0x7B8B60, + 0x038F60, 0x0B8F60, 0x138F60, 0x1B8F60, + 0x238F60, 0x2B8F60, 0x338F60, 0x3B8F60, + 0x438F60, 0x4B8F60, 0x538F60, 0x5B8F60, + 0x638F60, 0x6B8F60, 0x738F60, 0x7B8F60, + 0x038A60, 0x000606, 0x018040, 0x00008D, + 0x000A64, 0x280D02, 0x000A24, 0x00027D, + 0x018042, 0x10000A, 0x001224, 0x0003FD, + 0x018042, 0x08000A, 0x000904, 0x2C0A86, + 0x000007, 0x00018D, 0x000A24, 0x000464, + 0x000464, 0x080102, 0x000924, 0x000424, + 0x000424, 0x100102, 0x02000D, 0x009144, + 0x2C6186, 0x000007, 0x0001FD, 0x018042, + 0x08000A, 0x000A44, 0x2C4386, 0x018042, + 0x0A000D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00027D, 0x001020, 0x000606, + 0x018040, 0x0002F5, 0x010042, 0x08000A, + 0x000904, 0x2CB286, 0x000007, 0x00037D, + 0x018042, 0x08000A, 0x000904, 0x2CE286, + 0x000007, 0x000075, 0x002E7D, 0x010042, + 0x0B804A, 0x000020, 0x000904, 0x000686, + 0x010040, 0x31844A, 0x30048B, 0x000883, + 0x00008D, 0x000810, 0x28143A, 0x00008D, + 0x000810, 0x280C3A, 0x000675, 0x010042, + 0x08000A, 0x003815, 0x010924, 0x280502, + 0x0B000D, 0x000820, 0x0002F5, 0x010040, + 0x000606, 0x220007, 0x000464, 0x000464, + 0x000606, 0x000007, 0x000134, 0x007F8D, + 0x00093C, 0x281D12, 0x282512, 0x001F32, + 0x0E0007, 0x00010D, 0x00037D, 0x000820, + 0x018040, 0x05D2F4, 0x000007, 0x080007, + 0x00037D, 0x018042, 0x08000A, 0x000904, + 0x2E8A86, 0x000007, 0x000606, 0x000007, + 0x000007, 0x000012, 0x100007, 0x320007, + 0x600007, 0x460007, 0x100080, 0x48001A, + 0x004904, 0x2EF186, 0x000007, 0x001210, + 0x58003A, 0x000145, 0x5C5D04, 0x000007, + 0x000080, 0x48001A, 0x004904, 0x2F4186, + 0x000007, 0x001210, 0x50003A, 0x005904, + 0x2F9886, 0x000045, 0x0000C5, 0x7FFFF5, + 0x7FFF7D, 0x07D524, 0x004224, 0x500102, + 0x200502, 0x000082, 0x40001A, 0x004104, + 0x2FC986, 0x000007, 0x003865, 0x40001A, + 0x004020, 0x00104D, 0x04C184, 0x31AB86, + 0x000040, 0x040007, 0x000165, 0x000145, + 0x004020, 0x000040, 0x000765, 0x080080, + 0x40001A, 0x004104, 0x305986, 0x000007, + 0x001210, 0x40003A, 0x004104, 0x30B286, + 0x00004D, 0x0000CD, 0x004810, 0x20043A, + 0x000882, 0x40001A, 0x004104, 0x30C186, + 0x000007, 0x004820, 0x005904, 0x319886, + 0x000040, 0x0007E5, 0x200480, 0x2816A0, + 0x3216E0, 0x3A16E0, 0x4216E0, 0x021260, + 0x000040, 0x000032, 0x400075, 0x00007D, + 0x07D574, 0x200512, 0x000082, 0x40001A, + 0x004104, 0x317186, 0x000007, 0x038A06, + 0x640007, 0x0000E5, 0x000020, 0x000040, + 0x000A65, 0x000020, 0x020040, 0x020040, + 0x000040, 0x000165, 0x000042, 0x70000A, + 0x007104, 0x323286, 0x000007, 0x060007, + 0x019A06, 0x640007, 0x050000, 0x007020, + 0x000040, 0x038A06, 0x640007, 0x000007, + 0x00306D, 0x028860, 0x029060, 0x08000A, + 0x028860, 0x008040, 0x100012, 0x00100D, + 0x009184, 0x32D186, 0x000E0D, 0x009184, + 0x33E186, 0x000007, 0x300007, 0x001020, + 0x003B6D, 0x008040, 0x000080, 0x08001A, + 0x000904, 0x32F186, 0x000007, 0x001220, + 0x000DED, 0x008040, 0x008042, 0x10000A, + 0x40000D, 0x109544, 0x000007, 0x001020, + 0x000DED, 0x008040, 0x008042, 0x20040A, + 0x000082, 0x08001A, 0x000904, 0x338186, + 0x000007, 0x003B6D, 0x008042, 0x08000A, + 0x000E15, 0x010984, 0x342B86, 0x600007, + 0x08001A, 0x000C15, 0x010984, 0x341386, + 0x000020, 0x1A0007, 0x0002ED, 0x008040, + 0x620007, 0x00306D, 0x028042, 0x0A804A, + 0x000820, 0x0A804A, 0x000606, 0x10804A, + 0x000007, 0x282512, 0x001F32, 0x05D2F4, + 0x54D104, 0x00735C, 0x000786, 0x000007, + 0x0C0007, 0x0A0007, 0x1C0007, 0x003465, + 0x020040, 0x004820, 0x025060, 0x40000A, + 0x024060, 0x000040, 0x454944, 0x000007, + 0x004020, 0x003AE5, 0x000040, 0x0028E5, + 0x000042, 0x48000A, 0x004904, 0x39F886, + 0x002C65, 0x000042, 0x40000A, 0x0000D5, + 0x454104, 0x000007, 0x000655, 0x054504, + 0x368286, 0x0001D5, 0x054504, 0x368086, + 0x002B65, 0x000042, 0x003AE5, 0x50004A, + 0x40000A, 0x45C3D4, 0x000007, 0x454504, + 0x000007, 0x0000CD, 0x444944, 0x000007, + 0x454504, 0x000007, 0x00014D, 0x554944, + 0x000007, 0x045144, 0x367986, 0x002C65, + 0x000042, 0x48000A, 0x4CD104, 0x000007, + 0x04C144, 0x368386, 0x000007, 0x160007, + 0x002CE5, 0x040042, 0x40000A, 0x004020, + 0x000040, 0x002965, 0x000042, 0x40000A, + 0x004104, 0x36F086, 0x000007, 0x002402, + 0x383206, 0x005C02, 0x0025E5, 0x000042, + 0x40000A, 0x004274, 0x002AE5, 0x000042, + 0x40000A, 0x004274, 0x500112, 0x0029E5, + 0x000042, 0x40000A, 0x004234, 0x454104, + 0x000007, 0x004020, 0x000040, 0x003EE5, + 0x000020, 0x000040, 0x002DE5, 0x400152, + 0x50000A, 0x045144, 0x37DA86, 0x0000C5, + 0x003EE5, 0x004020, 0x000040, 0x002BE5, + 0x000042, 0x40000A, 0x404254, 0x000007, + 0x002AE5, 0x004020, 0x000040, 0x500132, + 0x040134, 0x005674, 0x0029E5, 0x020042, + 0x42000A, 0x000042, 0x50000A, 0x05417C, + 0x0028E5, 0x000042, 0x48000A, 0x0000C5, + 0x4CC144, 0x38A086, 0x0026E5, 0x0027E5, + 0x020042, 0x40004A, 0x50000A, 0x00423C, + 0x00567C, 0x0028E5, 0x004820, 0x000040, + 0x281D12, 0x282512, 0x001F72, 0x002965, + 0x000042, 0x40000A, 0x004104, 0x393A86, + 0x0E0007, 0x160007, 0x1E0007, 0x003EE5, + 0x000042, 0x40000A, 0x004104, 0x397886, + 0x002D65, 0x000042, 0x28340A, 0x003465, + 0x020042, 0x42004A, 0x004020, 0x4A004A, + 0x50004A, 0x05D2F4, 0x54D104, 0x00735C, + 0x39E186, 0x000007, 0x000606, 0x080007, + 0x0C0007, 0x080007, 0x0A0007, 0x0001E5, + 0x020045, 0x004020, 0x000060, 0x000365, + 0x000040, 0x002E65, 0x001A20, 0x0A1A60, + 0x000040, 0x003465, 0x020042, 0x42004A, + 0x004020, 0x4A004A, 0x000606, 0x50004A, + 0x0017FD, 0x018042, 0x08000A, 0x000904, + 0x225A86, 0x000007, 0x00107D, 0x018042, + 0x0011FD, 0x33804A, 0x19804A, 0x20000A, + 0x000095, 0x2A1144, 0x01A144, 0x3B9086, + 0x00040D, 0x00B184, 0x3B9186, 0x0018FD, + 0x018042, 0x0010FD, 0x09804A, 0x38000A, + 0x000095, 0x010924, 0x003A64, 0x3B8186, + 0x000007, 0x003904, 0x3B9286, 0x000007, + 0x3B9A06, 0x00000D, 0x00008D, 0x000820, + 0x00387D, 0x018040, 0x700002, 0x00117D, + 0x018042, 0x00197D, 0x29804A, 0x30000A, + 0x380002, 0x003124, 0x000424, 0x000424, + 0x002A24, 0x280502, 0x00068D, 0x000810, + 0x28143A, 0x00750D, 0x00B124, 0x002264, + 0x3D0386, 0x284402, 0x000810, 0x280C3A, + 0x0B800D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00758D, 0x00B124, 0x100102, + 0x012144, 0x3E4986, 0x001810, 0x10003A, + 0x00387D, 0x018042, 0x08000A, 0x000904, + 0x3E4886, 0x030000, 0x3E4A06, 0x0000BD, + 0x00008D, 0x023164, 0x000A64, 0x280D02, + 0x0B808D, 0x000820, 0x0002FD, 0x018040, + 0x200007, 0x00387D, 0x018042, 0x08000A, + 0x000904, 0x3E3286, 0x030000, 0x0002FD, + 0x018042, 0x08000A, 0x000904, 0x3D8286, + 0x000007, 0x002810, 0x28043A, 0x00750D, + 0x030924, 0x002264, 0x280D02, 0x02316C, + 0x28450A, 0x0B810D, 0x000820, 0x0002FD, + 0x018040, 0x200007, 0x00008D, 0x000A24, + 0x3E4A06, 0x100102, 0x001810, 0x10003A, + 0x0000BD, 0x003810, 0x30043A, 0x00187D, + 0x018042, 0x0018FD, 0x09804A, 0x20000A, + 0x0000AD, 0x028924, 0x07212C, 0x001010, + 0x300583, 0x300D8B, 0x3014BB, 0x301C83, + 0x002083, 0x00137D, 0x038042, 0x33844A, + 0x33ACCB, 0x33B4CB, 0x33BCCB, 0x33C4CB, + 0x33CCCB, 0x33D4CB, 0x305C8B, 0x006083, + 0x001E0D, 0x0005FD, 0x018042, 0x20000A, + 0x020924, 0x00068D, 0x00A96C, 0x00009D, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x3F6A86, 0x000007, 0x280502, 0x280D0A, + 0x284402, 0x001810, 0x28143A, 0x0C008D, + 0x000820, 0x0002FD, 0x018040, 0x220007, + 0x003904, 0x225886, 0x001E0D, 0x00057D, + 0x018042, 0x20000A, 0x020924, 0x0000A5, + 0x0002FD, 0x018042, 0x08000A, 0x000904, + 0x402A86, 0x000007, 0x280502, 0x280C02, + 0x002010, 0x28143A, 0x0C010D, 0x000820, + 0x0002FD, 0x018040, 0x225A06, 0x220007, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000 +}; + +#endif //_HWMCODE_ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.4.0-test11/linux/drivers/usb/Config.in Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/Config.in Mon Nov 27 18:10:35 2000 @@ -25,56 +25,16 @@ fi dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB -comment 'USB Devices' - dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB - dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI - fi + comment 'USB Device Class drivers' dep_tristate ' USB Audio support' CONFIG_USB_AUDIO $CONFIG_USB $CONFIG_SOUND - dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB - dep_tristate ' USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB - if [ "$CONFIG_USB_SERIAL" != "n" ]; then - bool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC - dep_tristate ' USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL - dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL - dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL - dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL - dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL - if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then - bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 - bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X - bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 - bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X - bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W - fi - dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL - dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL - fi - bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG - fi - dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV - dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV - dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB - fi + dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB $CONFIG_EXPERIMENTAL dep_tristate ' USB Mass Storage support' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI if [ "$CONFIG_USB_STORAGE" != "n" ]; then bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG + bool ' Freecom USB/ATAPI Bridge support' CONFIG_USB_STORAGE_FREECOM fi - dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT - dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET - dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET - dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB - dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV - dep_tristate ' USB Bluetooth support (EXPERIMENTAL)' CONFIG_USB_BLUETOOTH $CONFIG_USB - dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET - fi + dep_tristate ' USB Modem (CDC ACM) support' CONFIG_USB_ACM $CONFIG_USB + dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB comment 'USB Human Interface Devices (HID)' if [ "$CONFIG_INPUT" = "n" ]; then @@ -87,6 +47,30 @@ fi dep_tristate ' Wacom Intuos/Graphire tablet support' CONFIG_USB_WACOM $CONFIG_USB $CONFIG_INPUT fi + + comment 'USB Imaging devices' + dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB + dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB $CONFIG_EXPERIMENTAL + dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB + dep_tristate ' Microtek X6USB scanner support (EXPERIMENTAL)' CONFIG_USB_MICROTEK $CONFIG_USB $CONFIG_SCSI $CONFIG_EXPERIMENTAL + + comment 'USB Multimedia devices' + dep_tristate ' USB IBM (Xirlink) C-it Camera support' CONFIG_USB_IBMCAM $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' USB OV511 Camera support' CONFIG_USB_OV511 $CONFIG_USB $CONFIG_VIDEO_DEV + dep_tristate ' D-Link USB FM radio support (EXPERIMENTAL)' CONFIG_USB_DSBR $CONFIG_USB $CONFIG_VIDEO_DEV $CONFIG_EXPERIMENTAL + dep_tristate ' DABUSB driver' CONFIG_USB_DABUSB $CONFIG_USB + + comment 'USB Network adaptors' + dep_tristate ' PLUSB Prolific USB-Network driver (EXPERIMENTAL)' CONFIG_USB_PLUSB $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' USB ADMtek Pegasus-based ethernet device support (EXPERIMENTAL)' CONFIG_USB_PEGASUS $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + dep_tristate ' NetChip 1080-based USB Host-to-Host Link (EXPERIMENTAL)' CONFIG_USB_NET1080 $CONFIG_USB $CONFIG_NET $CONFIG_EXPERIMENTAL + + comment 'USB port drivers' + dep_tristate ' USS720 parport driver' CONFIG_USB_USS720 $CONFIG_USB $CONFIG_PARPORT + source drivers/usb/serial/Config.in + + comment 'USB misc drivers' + dep_tristate ' USB Diamond Rio500 support (EXPERIMENTAL)' CONFIG_USB_RIO500 $CONFIG_USB $CONFIG_EXPERIMENTAL fi endmenu diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.4.0-test11/linux/drivers/usb/acm.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/acm.c Tue Dec 5 23:15:12 2000 @@ -1,5 +1,5 @@ /* - * acm.c Version 0.16 + * acm.c Version 0.18 * * Copyright (c) 1999 Armin Fuerst * Copyright (c) 1999 Pavel Machek @@ -19,6 +19,8 @@ * v0.14 - sized down struct acm * v0.15 - fixed flow control again - characters could be lost * v0.16 - added code for modems with swapped data and control interfaces + * v0.17 - added new style probing + * v0.18 - fixed new style probing for devices with more configurations */ /* @@ -144,7 +146,7 @@ static struct usb_driver acm_driver; static struct tty_driver acm_tty_driver; -static struct acm *acm_table[ACM_TTY_MINORS] = { NULL, /* .... */ }; +static struct acm *acm_table[ACM_TTY_MINORS]; #define ACM_READY(acm) (acm && acm->dev && acm->used) @@ -185,7 +187,7 @@ switch (dr->request) { case ACM_IRQ_NETWORK: - + dbg("%s network", data[0] ? "connected to" : "disconnected from"); return; @@ -267,7 +269,7 @@ struct acm *acm = private; struct tty_struct *tty = acm->tty; - if (!ACM_READY(acm)) return; + if (!ACM_READY(acm)) return; if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) (tty->ldisc.write_wakeup)(tty); @@ -420,15 +422,15 @@ case TIOCMBIS: newctrl |= mask; break; case TIOCMBIC: newctrl &= ~mask; break; } - - if (acm->ctrlout == newctrl) return 0; + + if (acm->ctrlout == newctrl) return 0; return acm_set_control(acm, acm->ctrlout = newctrl); } return -ENOIOCTLCMD; } -static __u32 acm_tty_speed[] = { +static __u32 acm_tty_speed[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, @@ -457,7 +459,7 @@ newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; acm->clocal = termios->c_cflag & CLOCAL; - + if (!newline.speed) { newline.speed = acm->line.speed; newctrl &= ~ACM_CTRL_DTR; @@ -484,106 +486,114 @@ struct usb_config_descriptor *cfacm; struct usb_interface_descriptor *ifcom, *ifdata; struct usb_endpoint_descriptor *epctrl, *epread, *epwrite; - int readsize, ctrlsize, minor; + int readsize, ctrlsize, minor, i; unsigned char *buf; - /* Since 0 is treated as a wildcard by the USB pattern matching, - we explicitly check bDeviceSubClass and bDeviceProtocol - here. */ - if (dev->descriptor.bDeviceSubClass != 0 - || dev->descriptor.bDeviceProtocol != 0) return NULL; - - cfacm = dev->actconfig; - - dbg("probing config %d", cfacm->bConfigurationValue); - - if (cfacm->bNumInterfaces != 2 || - usb_interface_claimed(cfacm->interface + 0) || - usb_interface_claimed(cfacm->interface + 1)) +/* + * Since 0 is treated as a wildcard by the USB pattern matching, + * we explicitly check bDeviceSubClass and bDeviceProtocol here. + */ + + if (dev->descriptor.bDeviceSubClass != 0 || + dev->descriptor.bDeviceProtocol != 0) return NULL; - ifcom = cfacm->interface[0].altsetting + 0; - ifdata = cfacm->interface[1].altsetting + 0; + for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { - if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints != 2) { - ifcom = cfacm->interface[1].altsetting + 0; - ifdata = cfacm->interface[0].altsetting + 0; - if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints !=2) - return NULL; - } + cfacm = dev->config + i; - if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || - ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1) - return NULL; + dbg("probing config %d", cfacm->bConfigurationValue); - epctrl = ifcom->endpoint + 0; - epread = ifdata->endpoint + 0; - epwrite = ifdata->endpoint + 1; - - if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 || - (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 || - ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) - return NULL; + if (cfacm->bNumInterfaces != 2 || + usb_interface_claimed(cfacm->interface + 0) || + usb_interface_claimed(cfacm->interface + 1)) + continue; - if ((epread->bEndpointAddress & 0x80) != 0x80) { - epread = ifdata->endpoint + 1; - epwrite = ifdata->endpoint + 0; - } + ifcom = cfacm->interface[0].altsetting + 0; + ifdata = cfacm->interface[1].altsetting + 0; - usb_set_configuration(dev, cfacm->bConfigurationValue); + if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) { + ifcom = cfacm->interface[1].altsetting + 0; + ifdata = cfacm->interface[0].altsetting + 0; + if (ifdata->bInterfaceClass != 10 || ifdata->bNumEndpoints < 2) + continue; + } - for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); - if (acm_table[minor]) { - err("no more free acm devices"); - return NULL; - } + if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || + ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints < 1) + continue; + + epctrl = ifcom->endpoint + 0; + epread = ifdata->endpoint + 0; + epwrite = ifdata->endpoint + 1; + + if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 || + (epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 || + ((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80) + continue; + + if ((epread->bEndpointAddress & 0x80) != 0x80) { + epread = ifdata->endpoint + 1; + epwrite = ifdata->endpoint + 0; + } - if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { - err("out of memory"); - return NULL; - } - memset(acm, 0, sizeof(struct acm)); + usb_set_configuration(dev, cfacm->bConfigurationValue); - ctrlsize = epctrl->wMaxPacketSize; - readsize = epread->wMaxPacketSize; - acm->writesize = epwrite->wMaxPacketSize; - acm->iface = cfacm->interface; - acm->minor = minor; - acm->dev = dev; + for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); + if (acm_table[minor]) { + err("no more free acm devices"); + return NULL; + } - acm->tqueue.routine = acm_softint; - acm->tqueue.data = acm; + if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { + err("out of memory"); + return NULL; + } + memset(acm, 0, sizeof(struct acm)); - if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { - err("out of memory"); - kfree(acm); - return NULL; - } + ctrlsize = epctrl->wMaxPacketSize; + readsize = epread->wMaxPacketSize; + acm->writesize = epwrite->wMaxPacketSize; + acm->iface = cfacm->interface; + acm->minor = minor; + acm->dev = dev; - FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), - buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); + acm->tqueue.routine = acm_softint; + acm->tqueue.data = acm; - FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), - buf += ctrlsize, readsize, acm_read_bulk, acm); - acm->readurb.transfer_flags |= USB_NO_FSBR; + if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { + err("out of memory"); + kfree(acm); + return NULL; + } + + FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), + buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); - FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), - buf += readsize, acm->writesize, acm_write_bulk, acm); - acm->writeurb.transfer_flags |= USB_NO_FSBR; + FILL_BULK_URB(&acm->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), + buf += ctrlsize, readsize, acm_read_bulk, acm); + acm->readurb.transfer_flags |= USB_NO_FSBR; - printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); + FILL_BULK_URB(&acm->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress), + buf += readsize, acm->writesize, acm_write_bulk, acm); + acm->writeurb.transfer_flags |= USB_NO_FSBR; - acm_set_control(acm, acm->ctrlout); + printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); - acm->line.speed = cpu_to_le32(9600); - acm->line.databits = 8; - acm_set_line(acm, &acm->line); + acm_set_control(acm, acm->ctrlout); - usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); - usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + acm->line.speed = cpu_to_le32(9600); + acm->line.databits = 8; + acm_set_line(acm, &acm->line); + + usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); + usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + + tty_register_devfs(&acm_tty_driver, 0, minor); + return acm_table[minor] = acm; + } - tty_register_devfs(&acm_tty_driver, 0, minor); - return acm_table[minor] = acm; + return NULL; } static void acm_disconnect(struct usb_device *dev, void *ptr) @@ -621,10 +631,9 @@ * USB driver structure. */ -static struct usb_device_id acm_ids [] = { - { bDeviceClass: 2}, - { bInterfaceClass: 2, bInterfaceSubClass: 2, bInterfaceProtocol: 1}, - { } /* Terminating entry */ +static struct usb_device_id acm_ids[] = { + { bDeviceClass: 2, bDeviceSubClass: 0, bDeviceProtocol: 0}, + { } }; MODULE_DEVICE_TABLE (usb, acm_ids); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.4.0-test11/linux/drivers/usb/audio.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/audio.c Tue Nov 28 21:50:07 2000 @@ -89,6 +89,9 @@ * Somewhat peculiar due to OSS interface limitations. Only works * for channels where a "slider" is already in front of it (i.e. * a MIXER unit or a FEATURE unit with volume capability). + * 2000-11-26: Thomas Sailer + * Workaround for Dallas DS4201. The DS4201 uses PCM8 as format tag for + * its 8 bit modes, but expects signed data (and should therefore have used PCM). * */ @@ -191,6 +194,7 @@ #define SND_DEV_DSP16 5 +#define dprintk(x) /* --------------------------------------------------------------------- */ @@ -472,10 +476,10 @@ } db->bufsize = nr << PAGE_SHIFT; db->ready = 1; - printk(KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d " - "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n", - bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize, - db->numfrag, db->dmasize, db->bufsize, db->format); + dprintk((KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d " + "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n", + bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize, + db->numfrag, db->dmasize, db->bufsize, db->format)); return 0; } @@ -829,7 +833,7 @@ for (i = 0; i < DESCFRAMES; i++) { cp = ((unsigned char *)urb->transfer_buffer) + urb->iso_frame_desc[i].offset; if (urb->iso_frame_desc[i].status) { - printk(KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status); + dprintk((KERN_DEBUG "usbin_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); continue; } scnt = urb->iso_frame_desc[i].actual_length >> ufmtsh; @@ -921,7 +925,7 @@ for (i = 0; i < SYNCFRAMES; i++) if (urb->iso_frame_desc[0].status) - printk(KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status); + dprintk((KERN_DEBUG "usbin_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); return 0; } @@ -954,7 +958,7 @@ } else { u->flags &= ~(mask | FLG_RUNNING); wake_up(&u->dma.wait); - printk(KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret); + dprintk((KERN_DEBUG "usbin_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); } spin_unlock_irqrestore(&as->lock, flags); } @@ -1211,7 +1215,7 @@ for (i = 0; i < DESCFRAMES; i++) { if (urb->iso_frame_desc[i].status) { - printk(KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status); + dprintk((KERN_DEBUG "usbout_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); continue; } } @@ -1247,7 +1251,7 @@ } else { u->flags &= ~(mask | FLG_RUNNING); wake_up(&u->dma.wait); - printk(KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret); + dprintk((KERN_DEBUG "usbout_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); } spin_unlock_irqrestore(&as->lock, flags); } @@ -1273,11 +1277,11 @@ for (i = 0; i < SYNCFRAMES; i++, cp += 3) { if (urb->iso_frame_desc[i].status) { - printk(KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status); + dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u status %d\n", i, urb->iso_frame_desc[i].status)); continue; } if (urb->iso_frame_desc[i].actual_length < 3) { - printk(KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length); + dprintk((KERN_DEBUG "usbout_sync_retire_desc: frame %u length %d\n", i, urb->iso_frame_desc[i].actual_length)); continue; } f = cp[0] | (cp[1] << 8) | (cp[2] << 16); @@ -1319,7 +1323,7 @@ } else { u->flags &= ~(mask | FLG_RUNNING); wake_up(&u->dma.wait); - printk(KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret); + dprintk((KERN_DEBUG "usbout_sync_completed: descriptor not restarted (usb_submit_urb: %d)\n", suret)); } spin_unlock_irqrestore(&as->lock, flags); } @@ -1520,9 +1524,7 @@ d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi; -#if 1 - printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); -#endif + dprintk((KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting)); if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); @@ -1558,10 +1560,11 @@ ret, dev->devnum, u->interface, ep); return -1; } - printk(KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n", - dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)); + dprintk((KERN_DEBUG "usbaudio: set_format_in: device %d interface %d altsetting %d srate req: %u real %u\n", + dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16))); d->srate = data[0] | (data[1] << 8) | (data[2] << 16); } + dprintk((KERN_DEBUG "usbaudio: set_format_in: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate)); return 0; } @@ -1616,9 +1619,7 @@ d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi; -#if 1 - printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting); -#endif + dprintk((KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting)); if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); @@ -1654,10 +1655,11 @@ ret, dev->devnum, u->interface, ep); return -1; } - printk(KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n", - dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16)); + dprintk((KERN_DEBUG "usbaudio: set_format_out: device %d interface %d altsetting %d srate req: %u real %u\n", + dev->devnum, u->interface, fmt->altsetting, d->srate, data[0] | (data[1] << 8) | (data[2] << 16))); d->srate = data[0] | (data[1] << 8) | (data[2] << 16); } + dprintk((KERN_DEBUG "usbaudio: set_format_out: USB format 0x%x, DMA format 0x%x srate %u\n", u->format, d->format, d->srate)); return 0; } @@ -2902,6 +2904,9 @@ continue; } format = (fmt[5] == 2) ? (AFMT_U16_LE | AFMT_U8) : (AFMT_S16_LE | AFMT_S8); + /* Dallas DS4201 workaround */ + if (dev->descriptor.idVendor == 0x04fa && dev->descriptor.idProduct == 0x4201) + format = (AFMT_S16_LE | AFMT_S8); fmt = find_csinterface_descriptor(buffer, buflen, NULL, FORMAT_TYPE, asifout, i); if (!fmt) { printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u FORMAT_TYPE descriptor not found\n", @@ -3705,11 +3710,11 @@ /* 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"); + dprintk((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); + dprintk((KERN_DEBUG "usb_audio_disconnect: already called for %p!\n", s)); return; } down(&open_sem); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.0-test11/linux/drivers/usb/bluetooth.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/bluetooth.c Fri Dec 1 12:17:24 2000 @@ -1,11 +1,15 @@ /* - * bluetooth.c Version 0.6 + * bluetooth.c Version 0.7 * * Copyright (c) 2000 Greg Kroah-Hartman * Copyright (c) 2000 Mark Douglas Corner * * USB Bluetooth driver, based on the Bluetooth Spec version 1.0B * + * (11/29/2000) Version 0.7 gkh + * Fixed problem with overrunning the tty flip buffer. + * Removed unneeded NULL pointer initialization. + * * (10/05/2000) Version 0.6 gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -211,8 +215,7 @@ static struct tty_struct * bluetooth_tty[BLUETOOTH_TTY_MINORS]; static struct termios * bluetooth_termios[BLUETOOTH_TTY_MINORS]; static struct termios * bluetooth_termios_locked[BLUETOOTH_TTY_MINORS]; -static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS] = {NULL, }; - +static struct usb_bluetooth *bluetooth_table[BLUETOOTH_TTY_MINORS]; static inline int bluetooth_paranoia_check (struct usb_bluetooth *bluetooth, const char *function) @@ -327,6 +330,11 @@ tty->driver_data = bluetooth; bluetooth->tty = tty; + /* force low_latency on so that our tty_push actually forces the data through, + * otherwise it is scheduled, and with high data rates (like with OHCI) data + * can get lost. */ + bluetooth->tty->low_latency = 1; + bluetooth->active = 1; /* Reset the packet position counters */ @@ -786,9 +794,14 @@ return; } - if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos){ - for (i = 0; i < bluetooth->int_packet_pos; ++i) + if (packet_size + EVENT_HDR_SIZE == bluetooth->int_packet_pos) { + for (i = 0; i < bluetooth->int_packet_pos; ++i) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them */ + if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(bluetooth->tty); + } tty_insert_flip_char(bluetooth->tty, bluetooth->int_buffer[i], 0); + } tty_flip_buffer_push(bluetooth->tty); bluetooth->int_packet_pos = 0; @@ -900,8 +913,13 @@ } if (packet_size + ACL_HDR_SIZE == bluetooth->bulk_packet_pos) { - for (i = 0; i < bluetooth->bulk_packet_pos; ++i) + for (i = 0; i < bluetooth->bulk_packet_pos; ++i) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ + if (bluetooth->tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(bluetooth->tty); + } tty_insert_flip_char(bluetooth->tty, bluetooth->bulk_buffer[i], 0); + } tty_flip_buffer_push(bluetooth->tty); bluetooth->bulk_packet_pos = 0; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.4.0-test11/linux/drivers/usb/hid.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/hid.c Tue Nov 28 21:50:07 2000 @@ -856,7 +856,7 @@ case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */ switch (usage->hid & HID_USAGE) { - + case 0x000: usage->code = 0; break; case 0x034: usage->code = KEY_SLEEP; break; case 0x036: usage->code = BTN_MISC; break; case 0x08a: usage->code = KEY_WWW; break; @@ -980,6 +980,9 @@ int b = field->logical_maximum; input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3)); } + + if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */ + return; input_event(input, usage->type, usage->code, value); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/hub.h linux/drivers/usb/hub.h --- v2.4.0-test11/linux/drivers/usb/hub.h Sun Oct 8 10:50:30 2000 +++ linux/drivers/usb/hub.h Thu Dec 7 16:13:38 2000 @@ -95,8 +95,8 @@ struct urb *urb; /* Interrupt polling pipe */ - char buffer[USB_MAXCHILDREN / 8]; - + char buffer[(USB_MAXCHILDREN + 1 + 7) / 8]; /* add 1 bit for hub status change */ + /* and add 7 bits to round up to byte boundary */ int error; int nerrors; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/plusb.c linux/drivers/usb/plusb.c --- v2.4.0-test11/linux/drivers/usb/plusb.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/plusb.c Tue Nov 28 21:50:07 2000 @@ -28,7 +28,7 @@ * * Expect speeds of around 330Kbytes/second over a UHCI host controller. * OHCI should be faster. Increase the MTU for faster transfers of large - * files. (16384 is a good size) + * files (up-to 800Kbytes/second). (16384 is a good size) * * $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $ * @@ -136,6 +136,10 @@ //#define DEBUG 1 #include +#if (LINUX_VERSION_CODE < 0x020300) +#define dev_kfree_skb_any dev_kfree_skb +#endif + /* Definitions formerly in plusb.h relocated. No need to export them -EZA */ #define _PLUSB_INTPIPE 0x1 @@ -401,11 +405,9 @@ skb_list->state=0; - if( purb->status == -EPIPE ) { - + if( purb->status == -EPIPE ) printk(KERN_CRIT "%s: plusb_write_bulk_complete: got -EPIPE and don't know what to do!\n", s->net_dev.name); - } if(!purb->status) { s->net_stats.tx_packets++; @@ -421,15 +423,10 @@ dbg("plusb_bh: dev_kfree_skb"); - -#if (LINUX_VERSION_CODE < 0x020300) - dev_kfree_skb(skb_list->skb); -#else /* NOTE: In 2.4 it's a problem to call dev_kfree_skb() in a hard IRQ: Oct 28 23:42:14 bug kernel: Warning: kfree_skb on hard IRQ c023329a */ dev_kfree_skb_any(skb_list->skb); -#endif skb_list->skb = NULL; if (plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list)) { @@ -463,12 +460,10 @@ if(!s->connected) return; - if( purb->status == -EPIPE ) { - + if( purb->status == -EPIPE ) printk(KERN_CRIT "%s: plusb_read_bulk_complete: got -EPIPE and I don't know what to do!\n", s->net_dev.name); - - } else if (!purb->status) { + else if (!purb->status) { struct sk_buff *skb; unsigned char *dst; int len=purb->transfer_buffer_length; @@ -651,11 +646,7 @@ skb_list = list_entry (skb, skb_list_t, skb_list); if (skb_list->skb) { dbg ("Freeing SKB in queue"); -#if (LINUX_VERSION_CODE < 0x020300) - dev_kfree_skb(skb_list->skb); -#else dev_kfree_skb_any(skb_list->skb); -#endif skb_list->skb = NULL; } kfree(skb_list); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.0-test11/linux/drivers/usb/printer.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/printer.c Fri Dec 1 12:17:24 2000 @@ -82,6 +82,7 @@ int readcount; /* Counter for reads */ int ifnum; /* Interface number */ int minor; /* minor number of device */ + unsigned int quirks; /* quirks flags */ unsigned char used; /* True if open */ unsigned char bidir; /* interface is bidirectional */ unsigned char *device_id_string; /* IEEE 1284 DEVICE ID string (ptr) */ @@ -90,6 +91,26 @@ static struct usblp *usblp_table[USBLP_MINORS]; +/* Quirks: various printer quirks are handled by this table & its flags. */ + +struct quirk_printer_struct { + __u16 vendorId; + __u16 productId; + unsigned int quirks; +}; + +#define USBLP_QUIRK_BIDIR 0x1 /* reports bidir but requires unidirectional mode (no INs/reads) */ +#define USBLP_QUIRK_USB_INIT 0x2 /* needs vendor USB init string */ + +static struct quirk_printer_struct quirk_printers[] = { + { 0x03f0, 0x0004, USBLP_QUIRK_BIDIR }, /* HP DeskJet 895C */ + { 0x03f0, 0x0104, USBLP_QUIRK_BIDIR }, /* HP DeskJet 880C */ + { 0x03f0, 0x0204, USBLP_QUIRK_BIDIR }, /* HP DeskJet 815C */ + { 0x03f0, 0x0304, USBLP_QUIRK_BIDIR }, /* HP DeskJet 810C/812C */ + { 0x03f0, 0x0404, USBLP_QUIRK_BIDIR }, /* HP DeskJet 830C */ + { 0, 0 } +}; + /* * Functions for usblp control messages. */ @@ -325,8 +346,17 @@ return -ENODEV; if (usblp->writeurb.status) { - err = usblp_check_status(usblp, err); - continue; + if (usblp->quirks & USBLP_QUIRK_BIDIR) { + if (usblp->writeurb.status != -EINPROGRESS) + err("usblp%d: error %d writing to printer", + usblp->minor, usblp->writeurb.status); + err = usblp->writeurb.status; + continue; + } + else { + err = usblp_check_status(usblp, err); + continue; + } } writecount += usblp->writeurb.transfer_buffer_length; @@ -393,13 +423,42 @@ return count; } +/* + * Checks for printers that have quirks, such as requiring unidirectional + * communication but reporting bidirectional; currently some HP printers + * have this flaw (HP 810, 880, 895, etc.), or needing an init string + * sent at each open (like some Epsons). + * Returns 1 if found, 0 if not found. + * + * HP recommended that we use the bidirectional interface but + * don't attempt any bulk IN transfers from the IN endpoint. + * Here's some more detail on the problem: + * The problem is not that it isn't bidirectional though. The problem + * is that if you request a device ID, or status information, while + * the buffers are full, the return data will end up in the print data + * buffer. For example if you make sure you never request the device ID + * while you are sending print data, and you don't try to query the + * printer status every couple of milliseconds, you will probably be OK. + */ +static unsigned int usblp_quirks (__u16 vendor, __u16 product) +{ + int i; + + for (i = 0; quirk_printers[i].vendorId; i++) { + if (vendor == quirk_printers[i].vendorId && + product == quirk_printers[i].productId) + return quirk_printers[i].quirks; + } + return 0; +} + static void *usblp_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *epread, *epwrite; struct usblp *usblp; - int minor, i, bidir = 0; + int minor, i, bidir = 0, quirks; int alts = dev->actconfig->interface[ifnum].act_altsetting; int length, err; char *buf; @@ -453,10 +512,21 @@ } memset(usblp, 0, sizeof(struct usblp)); + /* lookup quirks for this printer */ + quirks = usblp_quirks(dev->descriptor.idVendor, dev->descriptor.idProduct); + + if (bidir && (quirks & USBLP_QUIRK_BIDIR)) { + bidir = 0; + epread = NULL; + info ("Disabling reads from problem bidirectional printer on usblp%d", + minor); + } + usblp->dev = dev; usblp->ifnum = ifnum; usblp->minor = minor; usblp->bidir = bidir; + usblp->quirks = quirks; init_waitqueue_head(&usblp->wait); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- v2.4.0-test11/linux/drivers/usb/scanner.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/scanner.c Thu Dec 7 17:05:42 2000 @@ -252,6 +252,7 @@ { idVendor: 0x04a5, idProduct: 0x2022 },/* Vuego Scan Brisa 340U */ /* Agfa */ { idVendor: 0x06bd, idProduct: 0x0001 }, /* SnapScan 1212U */ + { idVendor: 0x06bd, idProduct: 0x0002 }, /* SnapScan 1236U */ { idVendor: 0x06bd, idProduct: 0x2061 }, /* Another SnapScan 1212U (?)*/ { idVendor: 0x06bd, idProduct: 0x0100 }, /* SnapScan Touch */ /* Colorado -- See Primax/Colorado below */ @@ -300,10 +301,10 @@ { idVendor: 0x04b8, idProduct: 0x0101 },/* Perfection 636U and 636Photo */ { idVendor: 0x04b8, idProduct: 0x0103 },/* Perfection 610 */ { idVendor: 0x04b8, idProduct: 0x0104 },/* Perfection 1200U and 1200Photo*/ + { idVendor: 0x04b8, idProduct: 0x0106 },/* Stylus Scan 2500 */ { idVendor: 0x04b8, idProduct: 0x0107 },/* Expression 1600 */ /* Umax */ { idVendor: 0x1606, idProduct: 0x0010 }, /* Astra 1220U */ - { idVendor: 0x1606, idProduct: 0x0002 }, /* Astra 1236U */ { idVendor: 0x1606, idProduct: 0x0030 }, /* Astra 2000U */ { idVendor: 0x1606, idProduct: 0x0230 }, /* Astra 2200U */ /* Visioneer */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/Config.in linux/drivers/usb/serial/Config.in --- v2.4.0-test11/linux/drivers/usb/serial/Config.in Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/Config.in Thu Dec 7 16:13:38 2000 @@ -0,0 +1,30 @@ +# +# USB Serial device configuration +# +mainmenu_option next_comment +comment 'USB Serial Converter support' + +tristate 'USB Serial Converter support' CONFIG_USB_SERIAL $CONFIG_USB +if [ "$CONFIG_USB_SERIAL" != "n" ]; then + bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG + bool ' USB Generic Serial Driver' CONFIG_USB_SERIAL_GENERIC + dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB ConnectTech WhiteHEAT Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_WHITEHEAT $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB Digi International AccelePort USB Serial Driver' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL + dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB FTDI Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_FTDI_SIO $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB Handspring Visor Driver' CONFIG_USB_SERIAL_VISOR $CONFIG_USB_SERIAL + dep_tristate ' USB Keyspan PDA Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN_PDA $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB Keyspan USA-xxx Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_KEYSPAN $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + if [ "$CONFIG_USB_SERIAL_KEYSPAN" != "n" ]; then + bool ' USB Keyspan USA-28 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28 + bool ' USB Keyspan USA-28X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA28X + bool ' USB Keyspan USA-19 Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19 + bool ' USB Keyspan USA-18X Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA18X + bool ' USB Keyspan USA-19W Firmware' CONFIG_USB_SERIAL_KEYSPAN_USA19W + fi + dep_tristate ' USB MCT Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_MCT_U232 $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL + dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL $CONFIG_EXPERIMENTAL +fi + +endmenu diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.4.0-test11/linux/drivers/usb/serial/Makefile Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/Makefile Thu Dec 7 16:13:38 2000 @@ -22,6 +22,8 @@ obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o +obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o +obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o # Objects that export symbols. export-objs := usbserial.o diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.0-test11/linux/drivers/usb/serial/digi_acceleport.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/digi_acceleport.c Mon Dec 11 12:39:45 2000 @@ -601,7 +601,7 @@ spin_lock_irqsave( &priv->dp_port_lock, flags ); digi_wakeup_write( port ); spin_unlock_irqrestore( &priv->dp_port_lock, flags ); - + MOD_DEC_USE_COUNT; } static void digi_wakeup_write( struct usb_serial_port *port ) @@ -1409,7 +1409,9 @@ /* also queue up a wakeup at scheduler time, in case we */ /* lost the race in write_chan(). */ - queue_task( &priv->dp_wakeup_task, &tq_scheduler ); + MOD_INC_USE_COUNT; + if (schedule_task(&priv->dp_wakeup_task) == 0) + MOD_DEC_USE_COUNT; spin_unlock( &priv->dp_port_lock ); @@ -1736,7 +1738,7 @@ init_waitqueue_head( &priv->dp_flush_wait ); priv->dp_in_close = 0; init_waitqueue_head( &priv->dp_close_wait ); - priv->dp_wakeup_task.next = NULL; + INIT_LIST_HEAD(&priv->dp_wakeup_task.list); priv->dp_wakeup_task.sync = 0; priv->dp_wakeup_task.routine = (void *)digi_wakeup_write_lock; priv->dp_wakeup_task.data = (void *)(&serial->port[i]); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c --- v2.4.0-test11/linux/drivers/usb/serial/empeg.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/empeg.c Tue Dec 5 23:15:12 2000 @@ -0,0 +1,648 @@ +/* + * USB Empeg empeg-car player driver + * + * Copyright (C) 2000 + * Gary Brubaker (xavyer@ix.netcom.com) + * + * Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, as published by + * the Free Software Foundation, version 2. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (12/03/2000) gb + * Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open() + * This notifies the tty driver that the termios have changed. + * + * (11/13/2000) gb + * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open() + * (It only needs to be set once - Doh!) + * + * (11/11/2000) gb + * Updated to work with id_table structure. + * + * (11/04/2000) gb + * Forked this from visor.c, and hacked it up to work with an + * Empeg ltd. empeg-car player. Constructive criticism welcomed. + * I would like to say, 'Thank You' to Greg Kroah-Hartman for the + * use of his code, and for his guidance, advice and patience. :) + * A 'Thank You' is in order for John Ripley of Empeg ltd for his + * advice, and patience too. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" + +#define EMPEG_VENDOR_ID 0x084f +#define EMPEG_PRODUCT_ID 0x0001 + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +/* function prototypes for an empeg-car player */ +static int empeg_open (struct usb_serial_port *port, struct file *filp); +static void empeg_close (struct usb_serial_port *port, struct file *filp); +static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static void empeg_throttle (struct usb_serial_port *port); +static void empeg_unthrottle (struct usb_serial_port *port); +static int empeg_startup (struct usb_serial *serial); +static void empeg_shutdown (struct usb_serial *serial); +static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); +static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void empeg_write_bulk_callback (struct urb *urb); +static void empeg_read_bulk_callback (struct urb *urb); + +static __devinitdata struct usb_device_id id_table [] = { + { idVendor: EMPEG_VENDOR_ID, idProduct: EMPEG_PRODUCT_ID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table); + +struct usb_serial_device_type empeg_device = { + name: "Empeg", + id_table: id_table, + needs_interrupt_in: MUST_HAVE_NOT, /* must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: empeg_open, + close: empeg_close, + throttle: empeg_throttle, + unthrottle: empeg_unthrottle, + startup: empeg_startup, + shutdown: empeg_shutdown, + ioctl: empeg_ioctl, + set_termios: empeg_set_termios, + write: empeg_write, + write_bulk_callback: empeg_write_bulk_callback, + read_bulk_callback: empeg_read_bulk_callback, +}; + +#define NUM_URBS 16 +#define URB_TRANSFER_BUFFER_SIZE 4096 + +static struct urb *write_urb_pool[NUM_URBS]; +static spinlock_t write_urb_pool_lock; +static int bytes_in; +static int bytes_out; + +/****************************************************************************** + * Empeg specific driver functions + ******************************************************************************/ +static int empeg_open (struct usb_serial_port *port, struct file *filp) +{ + struct usb_serial *serial = port->serial; + unsigned long flags; + int result; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + dbg(__FUNCTION__ " - port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + ++port->open_count; + MOD_INC_USE_COUNT; + + /* gb - 2000/11/05 + * + * personally, I think these termios should be set in + * empeg_startup(), but it appears doing so leads to one + * of those chicken/egg problems. :) + * + */ + port->tty->termios->c_iflag + &= ~(IGNBRK + | BRKINT + | PARMRK + | ISTRIP + | INLCR + | IGNCR + | ICRNL + | IXON); + + port->tty->termios->c_oflag + &= ~OPOST; + + port->tty->termios->c_lflag + &= ~(ECHO + | ECHONL + | ICANON + | ISIG + | IEXTEN); + + port->tty->termios->c_cflag + &= ~(CSIZE + | PARENB); + + port->tty->termios->c_cflag + |= CS8; + + /* gb - 2000/12/03 + * + * Contributed by Borislav Deianov + * + * Notify the tty driver that the termios have changed!! + * + */ + port->tty->ldisc.set_termios(port->tty, NULL); + + /* gb - 2000/11/05 + * + * force low_latency on + * + * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually + * force the data through if low_latency is set. Otherwise the pushes are + * scheduled; this is bad as it opens up the possibility of dropping bytes + * on the floor. We are trying to sustain high data transfer rates; and + * don't want to drop bytes on the floor. + * Moral: use low_latency - drop no bytes - life is good. :) + * + */ + port->tty->low_latency = 1; + + if (!port->active) { + port->active = 1; + bytes_in = 0; + bytes_out = 0; + + /* Start reading from the device */ + FILL_BULK_URB( + port->read_urb, + serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + empeg_read_bulk_callback, + port); + + port->read_urb->transfer_flags |= USB_QUEUE_BULK; + + result = usb_submit_urb(port->read_urb); + + if (result) + err(__FUNCTION__ " - failed submitting read urb, error %d", result); + + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + return 0; +} + + +static void empeg_close (struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial; + unsigned char *transfer_buffer; + unsigned long flags; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + serial = get_usb_serial (port, __FUNCTION__); + if (!serial) + return; + + spin_lock_irqsave (&port->port_lock, flags); + + --port->open_count; + MOD_DEC_USE_COUNT; + + if (port->open_count <= 0) { + transfer_buffer = kmalloc (0x12, GFP_KERNEL); + + if (!transfer_buffer) { + err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12); + } else { + kfree (transfer_buffer); + } + + /* shutdown our bulk read */ + usb_unlink_urb (port->read_urb); + port->active = 0; + port->open_count = 0; + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + /* Uncomment the following line if you want to see some statistics in your syslog */ + /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ + +} + + +static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + struct urb *urb; + const unsigned char *current_position = buf; + unsigned long flags; + int status; + int i; + int bytes_sent = 0; + int transfer_size; + + dbg(__FUNCTION__ " - port %d", port->number); + + usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf); + + while (count > 0) { + + /* try to find a free urb in our list of them */ + urb = NULL; + + spin_lock_irqsave (&write_urb_pool_lock, flags); + + for (i = 0; i < NUM_URBS; ++i) { + if (write_urb_pool[i]->status != -EINPROGRESS) { + urb = write_urb_pool[i]; + break; + } + } + + spin_unlock_irqrestore (&write_urb_pool_lock, flags); + + if (urb == NULL) { + dbg (__FUNCTION__ " - no more free urbs"); + goto exit; + } + + if (urb->transfer_buffer == NULL) { + urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err(__FUNCTION__" no more kernel memory..."); + goto exit; + } + } + + transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE); + + if (from_user) { + copy_from_user (urb->transfer_buffer, current_position, transfer_size); + } else { + memcpy (urb->transfer_buffer, current_position, transfer_size); + } + + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + + /* build up our urb */ + FILL_BULK_URB ( + urb, + serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + urb->transfer_buffer, + transfer_size, + empeg_write_bulk_callback, + port); + + urb->transfer_flags |= USB_QUEUE_BULK; + + /* send it down the pipe */ + status = usb_submit_urb(urb); + if (status) + dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + + current_position += transfer_size; + bytes_sent += transfer_size; + count -= transfer_size; + bytes_out += transfer_size; + + } + +exit: + return bytes_sent; + +} + + +static void empeg_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); + return; + } + + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + + return; + +} + + +static void empeg_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + int result; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + return; + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + tty = port->tty; + + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + /* gb - 2000/11/13 + * If we insert too many characters we'll overflow the buffer. + * This means we'll lose bytes - Decidedly bad. + */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* gb - 2000/11/13 + * This doesn't push the data through unless tty->low_latency is set. + */ + tty_insert_flip_char(tty, data[i], 0); + } + /* gb - 2000/11/13 + * Goes straight through instead of scheduling - if tty->low_latency is set. + */ + tty_flip_buffer_push(tty); + bytes_in += urb->actual_length; + } + + /* Continue trying to always read */ + FILL_BULK_URB( + port->read_urb, + serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + empeg_read_bulk_callback, + port); + + port->read_urb->transfer_flags |= USB_QUEUE_BULK; + + result = usb_submit_urb(port->read_urb); + + if (result) + err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); + + return; + +} + + +static void empeg_throttle (struct usb_serial_port *port) +{ + unsigned long flags; + + dbg(__FUNCTION__ " - port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + usb_unlink_urb (port->read_urb); + + spin_unlock_irqrestore (&port->port_lock, flags); + + return; + +} + + +static void empeg_unthrottle (struct usb_serial_port *port) +{ + unsigned long flags; + int result; + + dbg(__FUNCTION__ " - port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + port->read_urb->dev = port->serial->dev; + + result = usb_submit_urb(port->read_urb); + + if (result) + err(__FUNCTION__ " - failed submitting read urb, error %d", result); + + spin_unlock_irqrestore (&port->port_lock, flags); + + return; + +} + + +static int empeg_startup (struct usb_serial *serial) +{ + + dbg(__FUNCTION__); + + dbg(__FUNCTION__ " - Set config to 1"); + usb_set_configuration (serial->dev, 1); + + /* continue on with initialization */ + return 0; + +} + + +static void empeg_shutdown (struct usb_serial *serial) +{ + int i; + + dbg (__FUNCTION__); + + /* stop reads and writes on all ports */ + for (i=0; i < serial->num_ports; ++i) { + while (serial->port[i].open_count > 0) { + empeg_close (&serial->port[i], NULL); + } + } + +} + + +static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +{ + dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd); + + return -ENOIOCTLCMD; +} + + +/* This function is all nice and good, but we don't change anything based on it :) */ +static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ + unsigned int cflag = port->tty->termios->c_cflag; + + dbg(__FUNCTION__ " - port %d", port->number); + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg(__FUNCTION__ " - nothing to change..."); + return; + } + } + + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + return; + } + + /* get the byte size */ + switch (cflag & CSIZE) { + case CS5: dbg(__FUNCTION__ " - data bits = 5"); break; + case CS6: dbg(__FUNCTION__ " - data bits = 6"); break; + case CS7: dbg(__FUNCTION__ " - data bits = 7"); break; + default: + case CS8: dbg(__FUNCTION__ " - data bits = 8"); break; + } + + /* determine the parity */ + if (cflag & PARENB) + if (cflag & PARODD) + dbg(__FUNCTION__ " - parity = odd"); + else + dbg(__FUNCTION__ " - parity = even"); + else + dbg(__FUNCTION__ " - parity = none"); + + /* figure out the stop bits requested */ + if (cflag & CSTOPB) + dbg(__FUNCTION__ " - stop bits = 2"); + else + dbg(__FUNCTION__ " - stop bits = 1"); + + /* figure out the flow control settings */ + if (cflag & CRTSCTS) + dbg(__FUNCTION__ " - RTS/CTS is enabled"); + else + dbg(__FUNCTION__ " - RTS/CTS is disabled"); + + /* determine software flow control */ + if (I_IXOFF(port->tty)) + dbg(__FUNCTION__ " - XON/XOFF is enabled, XON = %2x, XOFF = %2x", START_CHAR(port->tty), STOP_CHAR(port->tty)); + else + dbg(__FUNCTION__ " - XON/XOFF is disabled"); + + /* get the baud rate wanted */ + dbg(__FUNCTION__ " - baud rate = %d", tty_get_baud_rate(port->tty)); + + return; + +} + + +static int __init empeg_init (void) +{ + struct urb *urb; + int i; + + usb_serial_register (&empeg_device); + + /* create our write urb pool and transfer buffers */ + spin_lock_init (&write_urb_pool_lock); + for (i = 0; i < NUM_URBS; ++i) { + urb = usb_alloc_urb(0); + write_urb_pool[i] = urb; + if (urb == NULL) { + err("No more urbs???"); + continue; + } + + urb->transfer_buffer = NULL; + urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (!urb->transfer_buffer) { + err (__FUNCTION__ " - out of memory for urb buffers."); + continue; + } + } + + return 0; + +} + + +static void __exit empeg_exit (void) +{ + int i; + unsigned long flags; + + usb_serial_deregister (&empeg_device); + + spin_lock_irqsave (&write_urb_pool_lock, flags); + + for (i = 0; i < NUM_URBS; ++i) { + if (write_urb_pool[i]) { + /* FIXME - uncomment the following usb_unlink_urb call when + * the host controllers get fixed to set urb->dev = NULL after + * the urb is finished. Otherwise this call oopses. */ + /* usb_unlink_urb(write_urb_pool[i]); */ + if (write_urb_pool[i]->transfer_buffer) + kfree(write_urb_pool[i]->transfer_buffer); + usb_free_urb (write_urb_pool[i]); + } + } + + spin_unlock_irqrestore (&write_urb_pool_lock, flags); + +} + + +module_init(empeg_init); +module_exit(empeg_exit); + +MODULE_AUTHOR("Gary Brubaker "); +MODULE_DESCRIPTION("USB Empeg Mark I/II Driver"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.4.0-test11/linux/drivers/usb/serial/ftdi_sio.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/ftdi_sio.c Tue Dec 5 23:15:12 2000 @@ -12,9 +12,20 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * See http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date testing info + * and extra documentation + * + * (12/3/2000) Bill Ryder + * Added support for 8U232AM device. + * Moved PID and VIDs into header file only. + * Turned on low-latency for the tty (device will do high baudrates) + * Added shutdown routine to close files when device removed. + * More debug and error message cleanups. + * + * * (11/13/2000) Bill Ryder * Added spinlock protected open code and close code. - * Multiple opens work (sort of - see webpage). + * Multiple opens work (sort of - see webpage mentioned above). * Cleaned up comments. Removed multiple PID/VID definitions. * Factorised cts/dtr code * Made use of __FUNCTION__ in dbg's @@ -34,11 +45,11 @@ * driver is a loadable module now. * * (04/04/2000) Bill Ryder - * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are - * handled elsewhere in the serial driver chain). + * Fixed bugs in TCGET/TCSET ioctls (by removing them - they are + * handled elsewhere in the tty io driver chain). * * (03/30/2000) Bill Ryder - * Implemented lots of ioctls + * Implemented lots of ioctls * Fixed a race condition in write * Changed some dbg's to errs * @@ -50,6 +61,7 @@ /* Bill Ryder - bryder@sgi.com - wrote the FTDI_SIO implementation */ /* Thanx to FTDI for so kindly providing details of the protocol required */ /* to talk to the device */ +/* Thanx to gkh and the rest of the usb dev group for all code I have assimilated :-) */ #include @@ -78,20 +90,42 @@ #include "ftdi_sio.h" -#define FTDI_VENDOR_ID FTDI_VID -#define FTDI_SIO_SERIAL_CONVERTER_ID FTDI_SIO_PID -#define FTDI_8U232AM_PID 0x6001 static __devinitdata struct usb_device_id id_table_sio [] = { { idVendor: FTDI_VID, idProduct: FTDI_SIO_PID }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table_sio); +/* THe 8U232AM has the same API as the sio - but it can support MUCH + higher baudrates (921600 at 48MHz/230400 at 12MHz + so .. it's baudrate setting codes are different */ + + +static __devinitdata struct usb_device_id id_table_8U232AM [] = { + { idVendor: FTDI_VID, idProduct: FTDI_8U232AM_PID }, + { } /* Terminating entry */ +}; + + +static __devinitdata struct usb_device_id id_table_combined [] = { + { idVendor: FTDI_VID, idProduct: FTDI_SIO_PID }, + { idVendor: FTDI_VID, idProduct: FTDI_8U232AM_PID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table_combined); +struct ftdi_private { + ftdi_type_t ftdi_type; + char last_status_byte; /* device sends this every 40ms when open */ + + +}; /* function prototypes for a FTDI serial converter */ static int ftdi_sio_startup (struct usb_serial *serial); +static int ftdi_8U232AM_startup (struct usb_serial *serial); +static void ftdi_sio_shutdown (struct usb_serial *serial); static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp); static void ftdi_sio_close (struct usb_serial_port *port, struct file *filp); static int ftdi_sio_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); @@ -100,13 +134,15 @@ static void ftdi_sio_set_termios (struct usb_serial_port *port, struct termios * old); static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); -/* All of the device info needed for the FTDI SIO serial converter */ +/* Should rename most ftdi_sio's to ftdi_ now since there are two devices + which share common code */ + struct usb_serial_device_type ftdi_sio_device = { name: "FTDI SIO", id_table: id_table_sio, - needs_interrupt_in: MUST_HAVE_NOT, /* this device must not have an interrupt in endpoint */ - needs_bulk_in: MUST_HAVE, /* this device must have a bulk in endpoint */ - needs_bulk_out: MUST_HAVE, /* this device must have a bulk out endpoint */ + needs_interrupt_in: MUST_HAVE_NOT, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, num_interrupt_in: 0, num_bulk_in: 1, num_bulk_out: 1, @@ -119,17 +155,35 @@ ioctl: ftdi_sio_ioctl, set_termios: ftdi_sio_set_termios, startup: ftdi_sio_startup, + shutdown: ftdi_sio_shutdown, +}; + +struct usb_serial_device_type ftdi_8U232AM_device = { + name: "FTDI 8U232AM", + id_table: id_table_8U232AM, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, + num_interrupt_in: 0, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: ftdi_sio_open, + close: ftdi_sio_close, + write: ftdi_sio_write, + read_bulk_callback: ftdi_sio_read_bulk_callback, + write_bulk_callback: ftdi_sio_write_bulk_callback, + ioctl: ftdi_sio_ioctl, + set_termios: ftdi_sio_set_termios, + startup: ftdi_8U232AM_startup, + shutdown: ftdi_sio_shutdown, }; + /* * *************************************************************************** * FTDI SIO Serial Converter specific driver functions * *************************************************************************** - * - * See the webpage http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date - * testing information - * - * */ #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ @@ -165,15 +219,59 @@ } -/* do some startup allocations not currently performed by usb_serial_probe() */ + static int ftdi_sio_startup (struct usb_serial *serial) { + struct ftdi_private *priv; + init_waitqueue_head(&serial->port[0].write_wait); + + priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); + if (!priv){ + err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private)); + return -ENOMEM; + } + priv->ftdi_type = sio; return (0); } + +static int ftdi_8U232AM_startup (struct usb_serial *serial) +{ + struct ftdi_private *priv; + + init_waitqueue_head(&serial->port[0].write_wait); + + priv = serial->port->private = kmalloc(sizeof(struct ftdi_private), GFP_KERNEL); + if (!priv){ + err(__FUNCTION__"- kmalloc(%d) failed.", sizeof(struct ftdi_private)); + return -ENOMEM; + } + + priv->ftdi_type = F8U232AM; + + return (0); +} + +static void ftdi_sio_shutdown (struct usb_serial *serial) +{ + + dbg (__FUNCTION__); + + /* Close ports if they are open */ + while (serial->port[0].open_count > 0) { + ftdi_sio_close (&serial->port[0], NULL); + } + if (serial->port->private){ + kfree(serial->port->private); + serial->port->private = NULL; + } +} + + + static int ftdi_sio_open (struct usb_serial_port *port, struct file *filp) { /* ftdi_sio_open */ struct termios tmp_termios; @@ -182,7 +280,7 @@ int result; char buf[1]; /* Needed for the usb_control_msg I think */ - dbg(__FUNCTION__ " port %d", port->number); + dbg(__FUNCTION__); spin_lock_irqsave (&port->port_lock, flags); @@ -191,29 +289,33 @@ if (!port->active){ port->active = 1; + spin_unlock_irqrestore (&port->port_lock, flags); + /* do not allow a task to be queued to deliver received data */ + port->tty->low_latency = 1; + + /* No error checking for this (will get errors later anyway) */ /* See ftdi_sio.h for description of what is reset */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_RESET_REQUEST, FTDI_SIO_RESET_REQUEST_TYPE, FTDI_SIO_RESET_SIO, 0, buf, 0, WDR_TIMEOUT); - /* Setup termios */ + /* Setup termios defaults. According to tty_io.c the + settings are driver specific */ port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; /* ftdi_sio_set_termios will send usb control messages */ - /* ftdi_sio_set_termios will set up port according to above list */ - ftdi_sio_set_termios(port, &tmp_termios); - /* Turn on RTS and DTR since we are not flow controlling*/ + /* Turn on RTS and DTR since we are not flow controlling by default */ if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) { - err("Error from DTR HIGH urb"); + err(__FUNCTION__ " Error from DTR HIGH urb"); } if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){ - err("Error from RTS HIGH urb"); + err(__FUNCTION__ " Error from RTS HIGH urb"); } /* Start reading from the device */ @@ -224,7 +326,7 @@ result = usb_submit_urb(port->read_urb); if (result) err(__FUNCTION__ " - failed submitting read urb, error %d", result); - } else { /* the port was already active - so no initialisation was done */ + } else { /* the port was already active - so no initialisation is done */ spin_unlock_irqrestore (&port->port_lock, flags); } @@ -239,7 +341,7 @@ char buf[1]; unsigned long flags; - dbg( __FUNCTION__ " port %d", port->number); + dbg( __FUNCTION__); spin_lock_irqsave (&port->port_lock, flags); --port->open_count; @@ -271,14 +373,18 @@ usb_unlink_urb (port->read_urb); port->active = 0; port->open_count = 0; - } else { + } else { spin_unlock_irqrestore (&port->port_lock, flags); + + /* Send a HUP if necessary */ + if (!(port->tty->termios->c_cflag & CLOCAL)){ + tty_hangup(port->tty); + } + } MOD_DEC_USE_COUNT; - - } /* ftdi_sio_close */ @@ -292,7 +398,8 @@ const unsigned char *buf, int count) { /* ftdi_sio_write */ struct usb_serial *serial = port->serial; - const int data_offset = 1; + struct ftdi_private *priv = (struct ftdi_private *)port->private; + int data_offset ; int rc; int result; DECLARE_WAITQUEUE(wait, current); @@ -303,24 +410,25 @@ err("write request of 0 bytes"); return 0; } + + if (priv->ftdi_type == sio){ + data_offset = 1; + } else { + data_offset = 0; + } + dbg("data_offset set to %d",data_offset); /* only do something if we have a bulk out endpoint */ if (serial->num_bulk_out) { unsigned char *first_byte = port->write_urb->transfer_buffer; /* Was seeing a race here, got a read callback, then write callback before - hitting interuptible_sleep_on - so wrapping in add_wait_queue stuff */ + hitting interuptible_sleep_on - so wrapping in a wait_queue */ add_wait_queue(&port->write_wait, &wait); set_current_state (TASK_INTERRUPTIBLE); while (port->write_urb->status == -EINPROGRESS) { dbg(__FUNCTION__ " write in progress - retrying"); - if (0 /* file->f_flags & O_NONBLOCK */) { - remove_wait_queue(&port->write_wait, &wait); - set_current_state(TASK_RUNNING); - rc = -EAGAIN; - goto err; - } if (signal_pending(current)) { current->state = TASK_RUNNING; remove_wait_queue(&port->write_wait, &wait); @@ -328,7 +436,6 @@ goto err; } schedule(); - set_current_state (TASK_INTERRUPTIBLE); } remove_wait_queue(&port->write_wait, &wait); set_current_state(TASK_RUNNING); @@ -349,11 +456,13 @@ buf, count - data_offset ); } - /* Write the control byte at the front of the packet*/ first_byte = port->write_urb->transfer_buffer; - *first_byte = 1 | ((count-data_offset) << 2) ; + if (data_offset > 0){ + /* Write the control byte at the front of the packet*/ + *first_byte = 1 | ((count-data_offset) << 2) ; + } - dbg(__FUNCTION__ "Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]); + dbg(__FUNCTION__ " Bytes: %d, First Byte: 0o%03o",count, first_byte[0]); usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte); /* send the data out the bulk port */ @@ -412,6 +521,7 @@ static void ftdi_sio_read_bulk_callback (struct urb *urb) { /* ftdi_sio_serial_buld_callback */ struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct ftdi_private *priv = (struct ftdi_private *)port->private; struct usb_serial *serial; struct tty_struct *tty = port->tty ; unsigned char *data = urb->transfer_buffer; @@ -443,8 +553,10 @@ dbg("Just status"); } + priv->last_status_byte = data[0]; /* this has modem control lines */ + /* TO DO -- check for hung up line and handle appropriately: */ - /* send hangup (need to find out how to do this) */ + /* send hangup */ /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ /* if CD is dropped and the line is not CLOCAL then we should hangup */ @@ -469,6 +581,53 @@ return; } /* ftdi_sio_serial_read_bulk_callback */ + +__u16 translate_baudrate_to_ftdi(unsigned int cflag, ftdi_type_t ftdi_type) +{ /* translate_baudrate_to_ftdi */ + + __u16 urb_value = ftdi_sio_b9600; + + if (ftdi_type == sio){ + switch(cflag & CBAUD){ + case B0: break; /* ignored by this */ + case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break; + case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break; + case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break; + case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break; + case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break; + case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break; + case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break; + case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break; + case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break; + case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break; + default: dbg(__FUNCTION__ " FTDI_SIO does not support the baudrate (%d) requested", + (cflag & CBAUD)); + break; + } + } else { /* it is 8U232AM */ + switch(cflag & CBAUD){ + case B0: break; /* ignored by this */ + case B300: urb_value = ftdi_8U232AM_48MHz_b300; dbg("Set to 300"); break; + case B600: urb_value = ftdi_8U232AM_48MHz_b600; dbg("Set to 600") ; break; + case B1200: urb_value = ftdi_8U232AM_48MHz_b1200; dbg("Set to 1200") ; break; + case B2400: urb_value = ftdi_8U232AM_48MHz_b2400; dbg("Set to 2400") ; break; + case B4800: urb_value = ftdi_8U232AM_48MHz_b4800; dbg("Set to 4800") ; break; + case B9600: urb_value = ftdi_8U232AM_48MHz_b9600; dbg("Set to 9600") ; break; + case B19200: urb_value = ftdi_8U232AM_48MHz_b19200; dbg("Set to 19200") ; break; + case B38400: urb_value = ftdi_8U232AM_48MHz_b38400; dbg("Set to 38400") ; break; + case B57600: urb_value = ftdi_8U232AM_48MHz_b57600; dbg("Set to 57600") ; break; + case B115200: urb_value = ftdi_8U232AM_48MHz_b115200; dbg("Set to 115200") ; break; + case B230400: urb_value = ftdi_8U232AM_48MHz_b230400; dbg("Set to 230400") ; break; + case B460800: urb_value = ftdi_8U232AM_48MHz_b460800; dbg("Set to 460800") ; break; + case B921600: urb_value = ftdi_8U232AM_48MHz_b921600; dbg("Set to 921600") ; break; + default: dbg(__FUNCTION__ " The baudrate (%d) requested is not implemented", + (cflag & CBAUD)); + break; + } + } + return(urb_value); +} + /* As I understand this - old_termios contains the original termios settings */ /* and tty->termios contains the new setting to be used */ /* */ @@ -478,10 +637,12 @@ { /* ftdi_sio_set_termios */ struct usb_serial *serial = port->serial; unsigned int cflag = port->tty->termios->c_cflag; + struct ftdi_private *priv = (struct ftdi_private *)port->private; __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ - dbg(__FUNCTION__ " port %d", port->number); + + dbg(__FUNCTION__); /* FIXME -For this cut I don't care if the line is really changing or @@ -515,26 +676,12 @@ FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , 0, buf, 0, 100) < 0) { - err("FAILED to set databits/stopbits/parity"); + err(__FUNCTION__ " FAILED to set databits/stopbits/parity"); } /* Now do the baudrate */ - - switch(cflag & CBAUD){ - case B0: break; /* Handled below */ - case B300: urb_value = ftdi_sio_b300; dbg("Set to 300"); break; - case B600: urb_value = ftdi_sio_b600; dbg("Set to 600") ; break; - case B1200: urb_value = ftdi_sio_b1200; dbg("Set to 1200") ; break; - case B2400: urb_value = ftdi_sio_b2400; dbg("Set to 2400") ; break; - case B4800: urb_value = ftdi_sio_b4800; dbg("Set to 4800") ; break; - case B9600: urb_value = ftdi_sio_b9600; dbg("Set to 9600") ; break; - case B19200: urb_value = ftdi_sio_b19200; dbg("Set to 19200") ; break; - case B38400: urb_value = ftdi_sio_b38400; dbg("Set to 38400") ; break; - case B57600: urb_value = ftdi_sio_b57600; dbg("Set to 57600") ; break; - case B115200: urb_value = ftdi_sio_b115200; dbg("Set to 115200") ; break; - default: dbg(__FUNCTION__ "FTDI_SIO does not support the baudrate requested"); - /* FIXME - how to return an error for this? */ break; - } + urb_value = translate_baudrate_to_ftdi((cflag & CBAUD), priv->ftdi_type); + if ((cflag & CBAUD) == B0 ) { /* Disable flow control */ if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -542,30 +689,31 @@ FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, 0, buf, 0, WDR_TIMEOUT) < 0) { - err("error from disable flowcontrol urb"); + err(__FUNCTION__ " error from disable flowcontrol urb"); } /* Drop RTS and DTR */ if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){ - err("Error from DTR LOW urb"); + err(__FUNCTION__ " Error from DTR LOW urb"); } if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){ - err("Error from RTS LOW urb"); + err(__FUNCTION__ " Error from RTS LOW urb"); } } else { + /* set the baudrate determined before */ if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_BAUDRATE_REQUEST, FTDI_SIO_SET_BAUDRATE_REQUEST_TYPE, urb_value, 0, buf, 0, 100) < 0) { - err("urb failed to set baurdrate"); + err(__FUNCTION__ " urb failed to set baurdrate"); } } /* Set flow control */ /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ if (cflag & CRTSCTS) { - dbg(__FUNCTION__ "Setting to CRTSCTS flow control"); + dbg(__FUNCTION__ " Setting to CRTSCTS flow control"); if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, @@ -576,9 +724,8 @@ } } else { - /* CHECK Assuming XON/XOFF handled by stack - not by device */ - /* Disable flow control */ - dbg(__FUNCTION__ "Turning off hardware flow control"); + /* CHECKME Assuming XON/XOFF handled by tty stack - not by device */ + dbg(__FUNCTION__ " Turning off hardware flow control"); if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, @@ -595,6 +742,7 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) { struct usb_serial *serial = port->serial; + struct ftdi_private *priv = (struct ftdi_private *)port->private; __u16 urb_value=0; /* Will hold the new flags */ char buf[1]; int ret, mask; @@ -605,16 +753,27 @@ switch (cmd) { case TIOCMGET: - dbg(__FUNCTION__ "TIOCMGET"); - /* Request the status from the device */ - if ((ret = usb_control_msg(serial->dev, - usb_rcvctrlpipe(serial->dev, 0), - FTDI_SIO_GET_MODEM_STATUS_REQUEST, - FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, - 0, 0, - buf, 1, HZ * 5)) < 0 ) { - dbg(__FUNCTION__ "Get not get modem status of device"); - return(ret); + dbg(__FUNCTION__ " TIOCMGET"); + /* The MODEM_STATUS_REQUEST works for the sio but not the 232 */ + if (priv->ftdi_type == sio){ + /* TO DECIDE - use the 40ms status packets or not? */ + /* PRO: No need to send urb */ + /* CON: Could be 40ms out of date */ + + /* Request the status from the device */ + if ((ret = usb_control_msg(serial->dev, + usb_rcvctrlpipe(serial->dev, 0), + FTDI_SIO_GET_MODEM_STATUS_REQUEST, + FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, + 0, 0, + buf, 1, WDR_TIMEOUT)) < 0 ) { + err(__FUNCTION__ " Could not get modem status of device - err: %d", + ret); + return(ret); + } + } else { + /* This gets updated every 40ms - so just copy it in */ + buf[0] = priv->last_status_byte; } return put_user((buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | @@ -625,32 +784,20 @@ break; case TIOCMSET: /* Turns on and off the lines as specified by the mask */ - dbg(__FUNCTION__ "TIOCMSET"); + dbg(__FUNCTION__ " TIOCMSET"); if ((ret = get_user(mask, (unsigned long *) arg))) return ret; - urb_value = ((mask & TIOCM_DTR) ? FTDI_SIO_SET_DTR_HIGH : FTDI_SIO_SET_DTR_LOW); - if ((ret = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - urb_value , 0, - buf, 0, WDR_TIMEOUT)) < 0){ - err("Urb to set DTR failed"); - return(ret); - } - urb_value = ((mask & TIOCM_RTS) ? FTDI_SIO_SET_RTS_HIGH : FTDI_SIO_SET_RTS_LOW); - if ((ret = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - urb_value , 0, - buf, 0, WDR_TIMEOUT)) < 0){ - err("Urb to set RTS failed"); - return(ret); - } + urb_value = ((mask & TIOCM_DTR) ? HIGH : LOW); + if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ + err("Error from DTR set urb (TIOCMSET)"); + } + urb_value = ((mask & TIOCM_RTS) ? HIGH : LOW); + if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),urb_value) < 0){ + err("Error from RTS set urb (TIOCMSET)"); + } break; case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ - dbg(__FUNCTION__ "TIOCMBIS"); + dbg(__FUNCTION__ " TIOCMBIS"); if ((ret = get_user(mask, (unsigned long *) arg))) return ret; if (mask & TIOCM_DTR){ if ((ret = set_dtr(serial->dev, @@ -671,7 +818,7 @@ break; case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - dbg(__FUNCTION__ "TIOCMBIC"); + dbg(__FUNCTION__ " TIOCMBIC"); if ((ret = get_user(mask, (unsigned long *) arg))) return ret; if (mask & TIOCM_DTR){ if ((ret = set_dtr(serial->dev, @@ -704,25 +851,28 @@ /* This is not an error - turns out the higher layers will do * some ioctls itself (see comment above) */ - dbg(__FUNCTION__ "arg not supported - it was 0x%04x",cmd); + dbg(__FUNCTION__ " arg not supported - it was 0x%04x",cmd); return(-ENOIOCTLCMD); break; } - dbg(__FUNCTION__ " returning 0"); return 0; } /* ftdi_sio_ioctl */ static int __init ftdi_sio_init (void) { + dbg(__FUNCTION__); usb_serial_register (&ftdi_sio_device); + usb_serial_register (&ftdi_8U232AM_device); return 0; } static void __exit ftdi_sio_exit (void) { + dbg(__FUNCTION__); usb_serial_deregister (&ftdi_sio_device); + usb_serial_deregister (&ftdi_8U232AM_device); } @@ -730,4 +880,4 @@ module_exit(ftdi_sio_exit); MODULE_AUTHOR("Greg Kroah-Hartman , Bill Ryder "); -MODULE_DESCRIPTION("USB FTDI SIO driver"); +MODULE_DESCRIPTION("USB FTDI RS232 converters driver"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/ftdi_sio.h linux/drivers/usb/serial/ftdi_sio.h --- v2.4.0-test11/linux/drivers/usb/serial/ftdi_sio.h Sun Apr 2 15:20:16 2000 +++ linux/drivers/usb/serial/ftdi_sio.h Tue Dec 5 23:15:12 2000 @@ -20,9 +20,9 @@ */ #define FTDI_VID 0x0403 /* Vendor Id */ -#define FTDI_SIO_PID 0x8372 /* Product Id */ +#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ +#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ -/* Vendor Request Interface */ #define FTDI_SIO_RESET 0 /* Reset the port */ #define FTDI_SIO_MODEM_CTRL 1 /* Set the modem control register */ #define FTDI_SIO_SET_FLOW_CTRL 2 /* Set flow control register */ @@ -86,6 +86,12 @@ */ typedef enum { + sio = 1, + F8U232AM = 2, +} ftdi_type_t; + + +typedef enum { ftdi_sio_b300 = 0, ftdi_sio_b600 = 1, ftdi_sio_b1200 = 2, @@ -97,6 +103,38 @@ ftdi_sio_b57600 = 8, ftdi_sio_b115200 = 9 } FTDI_SIO_baudrate_t ; + + +typedef enum { + ftdi_8U232AM_12MHz_b300 = 0x09c4, + ftdi_8U232AM_12MHz_b600 = 0x04E2, + ftdi_8U232AM_12MHz_b1200 = 0x0271, + ftdi_8U232AM_12MHz_b2400 = 0x4138, + ftdi_8U232AM_12MHz_b4800 = 0x809c, + ftdi_8U232AM_12MHz_b9600 = 0xc04e, + ftdi_8U232AM_12MHz_b19200 = 0x0027, + ftdi_8U232AM_12MHz_b38400 = 0x4013, + ftdi_8U232AM_12MHz_b57600 = 0x000d, + ftdi_8U232AM_12MHz_b115200 = 0x4006, + ftdi_8U232AM_12MHz_b230400 = 0x8003, +} FTDI_8U232AM_12MHz_baudrate_t; +/* Apparently all devices are 48MHz */ +typedef enum { + ftdi_8U232AM_48MHz_b300 = 0x2710, + ftdi_8U232AM_48MHz_b600 = 0x1388, + ftdi_8U232AM_48MHz_b1200 = 0x09c4, + ftdi_8U232AM_48MHz_b2400 = 0x04e2, + ftdi_8U232AM_48MHz_b4800 = 0x0271, + ftdi_8U232AM_48MHz_b9600 = 0x4138, + ftdi_8U232AM_48MHz_b19200 = 0x809c, + ftdi_8U232AM_48MHz_b38400 = 0xc04e, + ftdi_8U232AM_48MHz_b57600 = 0x0034, + ftdi_8U232AM_48MHz_b115200 = 0x001a, + ftdi_8U232AM_48MHz_b230400 = 0x000d, + ftdi_8U232AM_48MHz_b460800 = 0x4006, + ftdi_8U232AM_48MHz_b921600 = 0x8003, + +} FTDI_8U232AM_48MHz_baudrate_t; #define FTDI_SIO_SET_DATA_REQUEST FTDI_SIO_SET_DATA #define FTDI_SIO_SET_DATA_REQUEST_TYPE 0x40 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.0-test11/linux/drivers/usb/serial/keyspan.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/keyspan.c Mon Dec 11 13:47:32 2000 @@ -19,28 +19,36 @@ and Keyspan, Inc the manufacturers of the Keyspan USB-serial products. Thanks Guys :) + Thanks to Paulus for miscellaneous tidy ups, some largish chunks + of much nicer and/or completely new code and (perhaps most uniquely) + having the patience to sit down and explain why and where he'd changed + stuff. + Tip 'o the hat to Linuxcare for supporting staff in their work on open source projects. - (11/01/2000) Adam J. Richter + Change History + (11/01/2000) Adam J. Richter usb_device_id table support. + + Tue Oct 10 23:15:33 EST 2000 Hugh + Merged Paul's changes with my USA-49W mods. Work in progress + still... + + Wed Jul 19 14:00:42 EST 2000 gkh + Added module_init and module_exit functions to handle the fact that + this driver is a loadable module now. - (10/05/2000) gkh - Fixed bug with urb->dev not being set properly, now that the usb - core needs it. - - Wed Jul 19 14:00:42 EST 2000 gkh - Added module_init and module_exit functions to handle the fact that this - driver is a loadable module now. - - Tue Jul 18 16:14:52 EST 2000 Hugh - Basic character input/output for USA-19 now mostly works, - fixed at 9600 baud for the moment. - + Tue Jul 18 16:14:52 EST 2000 Hugh + Basic character input/output for USA-19 now mostly works, + fixed at 9600 baud for the moment. + + Sat Jul 8 11:11:48 EST 2000 Hugh + First public release - nothing works except the firmware upload. + Tested on PPC and x86 architectures, seems to behave... */ -#include #include #include #include @@ -55,53 +63,130 @@ #include #include -#ifdef CONFIG_USB_SERIAL_DEBUG +#define DEBUG +/* #ifdef CONFIG_USB_SERIAL_DEBUG */ #define DEBUG -#else - #undef DEBUG -#endif +/* #endif */ #include #include "usb-serial.h" #include "keyspan.h" +#define INSTAT_BUFLEN 32 +#define GLOCONT_BUFLEN 64 + /* Per device and per port private data */ struct keyspan_serial_private { - struct urb *in_urbs[8]; - struct urb *out_urbs[8]; - char out_buffer[64]; - char in_buffer[64]; + /* number of active ports */ + atomic_t active_count; + + const keyspan_device_details *device_details; + + urb_t *instat_urb; + char instat_buf[INSTAT_BUFLEN]; + + /* XXX this one probably will need a lock */ + urb_t *glocont_urb; + char glocont_buf[GLOCONT_BUFLEN]; }; struct keyspan_port_private { - /* Keep track of which output endpoint to use */ + /* Keep track of which input & output endpoints to use */ + int in_flip; int out_flip; - /* Settings for the port */ + /* Keep duplicate of device details in each port + structure as well - simplifies some of the + callback functions etc. */ + const keyspan_device_details *device_details; + + /* Input endpoints and buffer for this port */ + urb_t *in_urbs[2]; + char in_buffer[2][64]; + /* Output endpoints and buffer for this port */ + urb_t *out_urbs[2]; + char out_buffer[2][64]; + + /* Input ack endpoint */ + urb_t *inack_urb; + char inack_buffer[1]; + + /* Output control endpoint */ + urb_t *outcont_urb; + char outcont_buffer[64]; + + /* Settings for the port */ int baud; int old_baud; - enum {parity_none, parity_odd, parity_even} parity; + unsigned int cflag; enum {flow_none, flow_cts, flow_xon} flow_control; - int rts_state; + int rts_state; /* Handshaking pins (outputs) */ int dtr_state; + int cts_state; /* Handshaking pins (inputs) */ + int dsr_state; + int dcd_state; + int ri_state; + unsigned long tx_start_time[2]; + int resend_cont; /* need to resend control packet */ }; - - /* FIXME this will break if multiple physical interfaces used */ -static wait_queue_head_t out_wait; - /* Include Keyspan message headers (not both yet, need some tweaks - to get clean build) */ -/*#include "keyspan_usa26msg.h"*/ +/* Include Keyspan message headers. All current Keyspan Adapters + make use of one of three message formats which are referred + to as USA-26, USA-28 and USA-49 by Keyspan and within this driver. */ +#include "keyspan_usa26msg.h" #include "keyspan_usa28msg.h" +#include "keyspan_usa49msg.h" - /* If you don't get debugging output, uncomment the following - two lines to enable cheat. */ -#undef dbg -#define dbg printk +/* If you don't get debugging output, uncomment the following + two lines to enable cheat. */ +#if 0 + #undef dbg + #define dbg printk +#endif + +static void keyspan_send_setup(struct usb_serial_port *port); + +/* Functions used by new usb-serial code. */ +int keyspan_init (void) +{ + usb_serial_register (&keyspan_usa18x_pre_device); + usb_serial_register (&keyspan_usa19_pre_device); + usb_serial_register (&keyspan_usa19w_pre_device); + usb_serial_register (&keyspan_usa28_pre_device); + usb_serial_register (&keyspan_usa28x_pre_device); + usb_serial_register (&keyspan_usa49w_pre_device); + + usb_serial_register (&keyspan_usa18x_device); + usb_serial_register (&keyspan_usa19_device); + usb_serial_register (&keyspan_usa19w_device); + usb_serial_register (&keyspan_usa28_device); + usb_serial_register (&keyspan_usa28x_device); + usb_serial_register (&keyspan_usa49w_device); + return 0; +} + +void keyspan_exit (void) +{ + usb_serial_deregister (&keyspan_usa18x_pre_device); + usb_serial_deregister (&keyspan_usa19_pre_device); + usb_serial_deregister (&keyspan_usa19w_pre_device); + usb_serial_deregister (&keyspan_usa28_pre_device); + usb_serial_deregister (&keyspan_usa28x_pre_device); + usb_serial_deregister (&keyspan_usa49w_pre_device); + + usb_serial_deregister (&keyspan_usa18x_device); + usb_serial_deregister (&keyspan_usa19_device); + usb_serial_deregister (&keyspan_usa19w_device); + usb_serial_deregister (&keyspan_usa28_device); + usb_serial_deregister (&keyspan_usa28x_device); + usb_serial_deregister (&keyspan_usa49w_device); +} + +module_init(keyspan_init); +module_exit(keyspan_exit); - /* Functions - mostly stubs for now */ static void keyspan_rx_throttle (struct usb_serial_port *port) { dbg("keyspan_rx_throttle port %d", port->number); @@ -123,194 +208,597 @@ static void keyspan_set_termios (struct usb_serial_port *port, struct termios *old_termios) { - dbg("keyspan_set_termios"); + int baud_rate; + struct keyspan_port_private *p_priv; + const keyspan_device_details *d_details; + unsigned int cflag; + + /* dbg(__FUNCTION__ "."); */ + + p_priv = (struct keyspan_port_private *)(port->private); + d_details = p_priv->device_details; + cflag = port->tty->termios->c_cflag; + + /* Baud rate calculation takes baud rate as an integer + so other rates can be generated if desired. */ + baud_rate = tty_get_baud_rate(port->tty); + /* If no match or invalid, don't change */ + if (baud_rate >= 0 + && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, + NULL, NULL, NULL) == KEYSPAN_BAUD_RATE_OK) { + /* FIXME - more to do here to ensure rate changes cleanly */ + p_priv->baud = baud_rate; + } + + /* set CTS/RTS handshake etc. */ + p_priv->cflag = cflag; + p_priv->flow_control = (cflag & CRTSCTS)? flow_cts: flow_none; + + keyspan_send_setup(port); } static int keyspan_ioctl(struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg) { - unsigned int value; + unsigned int value, set; + struct keyspan_port_private *p_priv; - dbg("keyspan_ioctl_info"); + p_priv = (struct keyspan_port_private *)(port->private); switch (cmd) { case TIOCMGET: - value = TIOCM_DTR | TIOCM_RNG; - if (copy_to_user((unsigned int *)arg, &value, sizeof(int))) { + value = ((p_priv->rts_state) ? TIOCM_RTS : 0) | + ((p_priv->dtr_state) ? TIOCM_DTR : 0) | + ((p_priv->cts_state) ? TIOCM_CTS : 0) | + ((p_priv->dsr_state) ? TIOCM_DSR : 0) | + ((p_priv->dcd_state) ? TIOCM_CAR : 0) | + ((p_priv->ri_state) ? TIOCM_RNG : 0); + + if (put_user(value, (unsigned int *) arg)) return -EFAULT; - } - else { - return 0; - } - - default: - return -ENOIOCTLCMD; + return 0; + + case TIOCMSET: + if (get_user(value, (unsigned int *) arg)) + return -EFAULT; + p_priv->rts_state = ((value & TIOCM_RTS) ? 1 : 0); + p_priv->dtr_state = ((value & TIOCM_DTR) ? 1 : 0); + keyspan_send_setup(port); + return 0; + + case TIOCMBIS: + case TIOCMBIC: + if (get_user(value, (unsigned int *) arg)) + return -EFAULT; + set = (cmd == TIOCMBIS); + if (value & TIOCM_RTS) + p_priv->rts_state = set; + if (value & TIOCM_DTR) + p_priv->dtr_state = set; + keyspan_send_setup(port); + return 0; } return -ENOIOCTLCMD; } + /* Write function is generic for the three protocols used + with only a minor change for usa49 required */ static int keyspan_write(struct usb_serial_port *port, int from_user, - const unsigned char *buf, int count) + const unsigned char *buf, int count) { - struct usb_serial *serial = port->serial; - struct keyspan_serial_private *s_priv; struct keyspan_port_private *p_priv; - int current_urb; - int i; + const keyspan_device_details *d_details; + int flip; + int left, todo; + urb_t *this_urb; + int err; - s_priv = (struct keyspan_serial_private *)(serial->private); p_priv = (struct keyspan_port_private *)(port->private); - - if (p_priv->out_flip == 0) { - current_urb = 0; - p_priv->out_flip = 1; - } - else { - current_urb = 1; - p_priv->out_flip = 0; - } + d_details = p_priv->device_details; - dbg("keyspan_write called for port %d (%d) chars {", port->number, count); - for (i = 0; i < count ; i++) { - dbg("%02x ", buf[i]); - } - dbg("}\n"); +#if 0 + dbg(__FUNCTION__ " for port %d (%d chars [%x]), flip=%d", + port->number, count, buf[0], p_priv->out_flip); +#endif - if (count == 0) { - dbg("write request of 0 bytes"); - return (0); - } + for (left = count; left > 0; left -= todo) { + todo = left; + if (todo > 63) + todo = 63; + + flip = p_priv->out_flip; + + /* Check we have a valid urb/endpoint before we use it... */ + if ((this_urb = p_priv->out_urbs[flip]) == 0) { + /* no bulk out, so return 0 bytes written */ + dbg(__FUNCTION__ " no output urb :("); + return count; + } - /* only send data if we have a bulk out endpoint */ - if (s_priv->out_urbs[current_urb]) { - while (s_priv->out_urbs[current_urb]->status == -EINPROGRESS) { - dbg (__FUNCTION__ " INPROGRES\n"); - interruptible_sleep_on(&out_wait); - if (signal_pending(current)) { - dbg (__FUNCTION__ " signal\n"); - return (-ERESTARTSYS); - } + if (this_urb->status == -EINPROGRESS) { + if (this_urb->transfer_flags & USB_ASYNC_UNLINK) + break; + if (jiffies - p_priv->tx_start_time[flip] < 10 * HZ) + break; + this_urb->transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb(this_urb); + break; } - /*if (s_priv->out_urbs[current_urb]->status == -EINPROGRESS) { - dbg ("already writing"); - return (-EAGAIN); - }*/ - /* First byte in buffer is "last flag" - unused so - for now so set to zero */ - memset(s_priv->out_urbs[current_urb]->transfer_buffer, 0, 1); + + /* First byte in buffer is "last flag" - unused so + for now so set to zero */ + ((char *)this_urb->transfer_buffer)[0] = 0; if (from_user) { - copy_from_user(s_priv->out_urbs[current_urb]->transfer_buffer + 1, buf, count); + copy_from_user(this_urb->transfer_buffer + 1, buf, todo); + } else { + memcpy (this_urb->transfer_buffer + 1, buf, todo); } - else { - memcpy (s_priv->out_urbs[current_urb]->transfer_buffer + 1, buf, count); - } + buf += todo; /* send the data out the bulk port */ - s_priv->out_urbs[current_urb]->transfer_buffer_length = count + 1; - s_priv->out_urbs[current_urb]->dev = serial->dev; + this_urb->transfer_buffer_length = todo + 1; - if (usb_submit_urb(s_priv->out_urbs[current_urb])) { - dbg("usb_submit_urb(write bulk) failed"); + this_urb->transfer_flags &= ~USB_ASYNC_UNLINK; + this_urb->dev = port->serial->dev; + if ((err = usb_submit_urb(this_urb)) != 0) { + dbg("usb_submit_urb(write bulk) failed (%d)", err); } + p_priv->tx_start_time[flip] = jiffies; - return (count); + /* Flip for next time if usa26 or usa28 interface + (not used on usa49) */ + p_priv->out_flip = (flip + 1) & d_details->outdat_endp_flip; } - - /* no bulk out, so return 0 bytes written */ - return (0); -} + return count - left; +} -static void keyspan_write_bulk_callback (struct urb *urb) +static void usa26_indat_callback(struct urb *urb) { - int endpoint; - + int i, err; + int endpoint; + struct usb_serial_port *port; + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + + /* dbg (__FUNCTION__); */ + endpoint = usb_pipeendpoint(urb->pipe); - dbg("keyspan_write_bulk_callback for endpoint %d\n", endpoint); + if (urb->status) { + dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.", + urb->status, endpoint); + return; + } - /* Only do wakeup if this callback is from one of the data - endpoints. */ - if (endpoint == 2 || endpoint == 3) { - wake_up_interruptible(&out_wait); + port = (struct usb_serial_port *) urb->context; + tty = port->tty; + if (urb->actual_length) { + if (data[0] == 0) { + /* no error on any byte */ + for (i = 1; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + } else { + /* some bytes had errors, every byte has status */ + for (i = 0; i + 1 < urb->actual_length; i += 2) { + int stat = data[i], flag = 0; + if (stat & RXERROR_OVERRUN) + flag |= TTY_OVERRUN; + if (stat & RXERROR_FRAMING) + flag |= TTY_FRAME; + if (stat & RXERROR_PARITY) + flag |= TTY_PARITY; + /* XXX should handle break (0x10) */ + tty_insert_flip_char(tty, data[i+1], flag); + } + } + tty_flip_buffer_push(tty); + } + + /* Resubmit urb so we continue receiving */ + urb->dev = port->serial->dev; + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err); } + return; +} + + /* Outdat handling is common for usa26, usa28 and usa49 messages */ +static void usa2x_outdat_callback(struct urb *urb) +{ + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + + port = (struct usb_serial_port *) urb->context; + p_priv = (struct keyspan_port_private *)(port->private); + /* dbg (__FUNCTION__ " urb %d", urb == p_priv->out_urbs[1]); */ + if (port->active) { + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } } +static void usa26_inack_callback(struct urb *urb) +{ + dbg (__FUNCTION__); + +} -static void keyspan_read_bulk_callback (struct urb *urb) +static void usa26_outcont_callback(struct urb *urb) { - struct usb_serial *serial = (struct usb_serial *)urb->context; - struct usb_serial_port *port; - int i; - int endpoint; - struct tty_struct *tty; - unsigned char *data = urb->transfer_buffer; + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; - if (serial_paranoia_check (serial, __FUNCTION__)) + port = (struct usb_serial_port *) urb->context; + p_priv = (struct keyspan_port_private *)(port->private); + + if (p_priv->resend_cont) { + /* dbg (__FUNCTION__ " sending setup"); */ + keyspan_usa26_send_setup(port->serial, port); + } +} + +static void usa26_instat_callback(struct urb *urb) +{ + unsigned char *data = urb->transfer_buffer; + keyspan_usa26_portStatusMessage *msg; + struct usb_serial *serial; + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + int old_dcd_state, err; + + serial = (struct usb_serial *) urb->context; + + if (urb->status) { + dbg(__FUNCTION__ " nonzero status: %x", urb->status); return; - port = &serial->port[0]; - if (port_paranoia_check (port, __FUNCTION__)) + } + if (urb->actual_length != 9) { + dbg(__FUNCTION__ " %d byte report??", urb->actual_length); + goto exit; + } + + msg = (keyspan_usa26_portStatusMessage *)data; + +#if 0 + dbg(__FUNCTION__ " port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d", + msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff, + msg->_txXoff, msg->rxEnabled, msg->controlResponse); +#endif + + /* Now do something useful with the data */ + + + /* Check port number from message and retrieve private data */ + if (msg->port >= serial->num_ports) { + dbg ("Unexpected port number %d", msg->port); + goto exit; + } + port = &serial->port[msg->port]; + p_priv = (struct keyspan_port_private *)(port->private); + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; + p_priv->cts_state = ((msg->hskia_cts) ? 1 : 0); + p_priv->dsr_state = ((msg->dsr) ? 1 : 0); + p_priv->dcd_state = ((msg->gpia_dcd) ? 1 : 0); + p_priv->ri_state = ((msg->ri) ? 1 : 0); + + if (port->tty && !C_CLOCAL(port->tty) + && old_dcd_state != p_priv->dcd_state) { + if (old_dcd_state) + tty_hangup(port->tty); + /* else */ + /* wake_up_interruptible(&p_priv->open_wait); */ + } + +exit: + /* Resubmit urb so we continue receiving */ + urb->dev = serial->dev; + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err); + } +} + +static void usa26_glocont_callback(struct urb *urb) +{ + dbg (__FUNCTION__); + +} + + +static void usa28_indat_callback(struct urb *urb) +{ + int i, err; + struct usb_serial_port *port; + struct tty_struct *tty; + unsigned char *data; + struct keyspan_port_private *p_priv; + + /* dbg (__FUNCTION__); */ + + port = (struct usb_serial_port *) urb->context; + p_priv = (struct keyspan_port_private *)(port->private); + data = urb->transfer_buffer; + + if (urb != p_priv->in_urbs[p_priv->in_flip]) return; + do { + if (urb->status) { + dbg(__FUNCTION__ "nonzero status: %x on endpoint +%d.", + urb->status, usb_pipeendpoint(urb->pipe)); + return; + } + + port = (struct usb_serial_port *) urb->context; + p_priv = (struct keyspan_port_private *)(port->private); + data = urb->transfer_buffer; + + tty = port->tty; + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + + /* Resubmit urb so we continue receiving */ + urb->dev = port->serial->dev; + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ "resubmit read urb failed. (%d)", +err); + } + p_priv->in_flip ^= 1; + + urb = p_priv->in_urbs[p_priv->in_flip]; + } while (urb->status != -EINPROGRESS); +} + +static void usa28_inack_callback(struct urb *urb) +{ + dbg (__FUNCTION__); +} + +static void usa28_outcont_callback(struct urb *urb) +{ + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + + port = (struct usb_serial_port *) urb->context; + p_priv = (struct keyspan_port_private *)(port->private); + + if (p_priv->resend_cont) { + dbg (__FUNCTION__ " sending setup"); + keyspan_usa28_send_setup(port->serial, port); + } +} + +static void usa28_instat_callback(struct urb *urb) +{ + int err; + unsigned char *data = urb->transfer_buffer; + keyspan_usa28_portStatusMessage *msg; + struct usb_serial *serial; + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + int old_dcd_state; + + serial = (struct usb_serial *) urb->context; + if (urb->status) { - dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + dbg(__FUNCTION__ " nonzero status: %x", urb->status); return; } - usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) { + dbg(__FUNCTION__ " bad length %d", urb->actual_length); + goto exit; + } - endpoint = usb_pipeendpoint(urb->pipe); + /*dbg(__FUNCTION__ " %x %x %x %x %x %x %x %x %x %x %x %x", + data[0], data[1], data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], data[10], data[11]);*/ + + /* Now do something useful with the data */ + msg = (keyspan_usa28_portStatusMessage *)data; + + + /* Check port number from message and retrieve private data */ + if (msg->port >= serial->num_ports) { + dbg ("Unexpected port number %d", msg->port); + goto exit; + } + port = &serial->port[msg->port]; + p_priv = (struct keyspan_port_private *)(port->private); + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; + p_priv->cts_state = ((msg->cts) ? 1 : 0); + p_priv->dsr_state = ((msg->dsr) ? 1 : 0); + p_priv->dcd_state = ((msg->dcd) ? 1 : 0); + p_priv->ri_state = ((msg->ri) ? 1 : 0); + + if (port->tty && !C_CLOCAL(port->tty) + && old_dcd_state != p_priv->dcd_state) { + if (old_dcd_state) + tty_hangup(port->tty); + /* else */ + /* wake_up_interruptible(&p_priv->open_wait); */ + } + +exit: + /* Resubmit urb so we continue receiving */ + urb->dev = serial->dev; + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err); + } +} + +static void usa28_glocont_callback(struct urb *urb) +{ + dbg (__FUNCTION__); +} + + +static void usa49_glocont_callback(struct urb *urb) +{ + struct usb_serial *serial; + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + int i; + /* dbg (__FUNCTION__); */ + + serial = (struct usb_serial *) urb->context; + for (i = 0; i < serial->num_ports; ++i) { + port = &serial->port[i]; + p_priv = (struct keyspan_port_private *)(port->private); + + if (p_priv->resend_cont) { + /* dbg (__FUNCTION__ " sending setup"); */ + keyspan_usa49_send_setup(serial, port); + break; + } + } +} + + /* This is actually called glostat in the Keyspan + doco */ +static void usa49_instat_callback(struct urb *urb) +{ + int err; + unsigned char *data = urb->transfer_buffer; + keyspan_usa49_portStatusMessage *msg; + struct usb_serial *serial; + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + int old_dcd_state; + + /* dbg (__FUNCTION__); */ + + serial = (struct usb_serial *) urb->context; if (urb->status) { - dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.\n", - urb->status, endpoint); + dbg(__FUNCTION__ " nonzero status: %x", urb->status); return; } - switch (endpoint) { + if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) { + dbg(__FUNCTION__ " bad length %d", urb->actual_length); + goto exit; + } - /* If this is one of the data endpoints, stuff it's - contents into the tty flip_buffer. */ - case 1: - case 2: - tty = port->tty; - if (urb->actual_length) { - for (i = 0; i < urb->actual_length ; ++i) { - tty_insert_flip_char(tty, data[i], 0); - } - tty_flip_buffer_push(tty); - } - break; + /*dbg(__FUNCTION__ " %x %x %x %x %x %x %x %x %x %x %x", + data[0], data[1], data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], data[10]);*/ + + /* Now do something useful with the data */ + msg = (keyspan_usa49_portStatusMessage *)data; - /* INACK endpoint */ - case 3: dbg(__FUNCTION__ " callback for INACK endpoint\n"); - break; + /* Check port number from message and retrieve private data */ + if (msg->portNumber >= serial->num_ports) { + dbg ("Unexpected port number %d", msg->portNumber); + goto exit; + } + port = &serial->port[msg->portNumber]; + p_priv = (struct keyspan_port_private *)(port->private); + + /* Update handshaking pin state information */ + old_dcd_state = p_priv->dcd_state; + p_priv->cts_state = ((msg->cts) ? 1 : 0); + p_priv->dsr_state = ((msg->dsr) ? 1 : 0); + p_priv->dcd_state = ((msg->dcd) ? 1 : 0); + p_priv->ri_state = ((msg->ri) ? 1 : 0); + + if (port->tty && !C_CLOCAL(port->tty) + && old_dcd_state != p_priv->dcd_state) { + if (old_dcd_state) + tty_hangup(port->tty); + /* else */ + /* wake_up_interruptible(&p_priv->open_wait); */ + } - /* INSTAT endpoint */ - case 4: dbg(__FUNCTION__ " callback for INSTAT endpoint\n"); - break; - - default: - dbg(__FUNCTION__ " callback for unknown endpoint!\n"); - break; +exit: + /* Resubmit urb so we continue receiving */ + urb->dev = serial->dev; + + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err); + } +} + +static void usa49_inack_callback(struct urb *urb) +{ + dbg (__FUNCTION__); +} + +static void usa49_indat_callback(struct urb *urb) +{ + int i, err; + int endpoint; + struct usb_serial_port *port; + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + + /* dbg (__FUNCTION__); */ + + endpoint = usb_pipeendpoint(urb->pipe); + + if (urb->status) { + dbg(__FUNCTION__ "nonzero status: %x on endpoint %d.", + urb->status, endpoint); + return; + } + + port = (struct usb_serial_port *) urb->context; + tty = port->tty; + if (urb->actual_length) { + if (data[0] == 0) { + /* no error on any byte */ + for (i = 1; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + } else { + /* some bytes had errors, every byte has status */ + for (i = 0; i + 1 < urb->actual_length; i += 2) { + int stat = data[i], flag = 0; + if (stat & RXERROR_OVERRUN) + flag |= TTY_OVERRUN; + if (stat & RXERROR_FRAMING) + flag |= TTY_FRAME; + if (stat & RXERROR_PARITY) + flag |= TTY_PARITY; + /* XXX should handle break (0x10) */ + tty_insert_flip_char(tty, data[i+1], flag); + } + } + tty_flip_buffer_push(tty); } - /* Resubmit urb so we continue receiving */ - urb->dev = serial->dev; - if (usb_submit_urb(urb)) { - dbg(__FUNCTION__ "resubmit read urb failed.\n"); + /* Resubmit urb so we continue receiving */ + urb->dev = port->serial->dev; + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ "resubmit read urb failed. (%d)", err); } - return; - } +/* not used, usa-49 doesn't have per-port control endpoints */ +static void usa49_outcont_callback(struct urb *urb) +{ + dbg (__FUNCTION__); +} + + + static int keyspan_write_room (struct usb_serial_port *port) { -// dbg("keyspan_write_room called\n"); +// dbg("keyspan_write_room called"); return (32); } @@ -327,63 +815,103 @@ struct keyspan_port_private *p_priv; struct keyspan_serial_private *s_priv; struct usb_serial *serial = port->serial; - int i; + const keyspan_device_details *d_details; + int i, already_active, err; + unsigned long flags; + urb_t *urb; s_priv = (struct keyspan_serial_private *)(serial->private); p_priv = (struct keyspan_port_private *)(port->private); + d_details = s_priv->device_details; - dbg("keyspan_open called.\n"); - - if (port->active) { - dbg(__FUNCTION__ "port->active already true!\n"); - return (-EINVAL); - } + /* dbg("keyspan_open called."); */ + MOD_INC_USE_COUNT; - p_priv = (struct keyspan_port_private *)(port->private); - - p_priv->out_flip = 0; + spin_lock_irqsave (&port->port_lock, flags); + ++port->open_count; + already_active = port->active; port->active = 1; + spin_unlock_irqrestore (&port->port_lock, flags); - /* Start reading from port */ - for (i = 0; i < 4; i++) { - if (s_priv->in_urbs[i]) { - s_priv->in_urbs[i]->dev = serial->dev; - if (usb_submit_urb(s_priv->in_urbs[i])) { - dbg(__FUNCTION__ " submit in urb %d failed", i); - } - } + if (already_active) + return 0; + + p_priv = (struct keyspan_port_private *)(port->private); + /* Set some sane defaults */ + p_priv->baud = 9600; + p_priv->cflag = CREAD | CLOCAL; + p_priv->flow_control = flow_none; + p_priv->rts_state = 1; + p_priv->dtr_state = 1; + + /* Start reading from endpoints */ + for (i = 0; i < 2; i++) { + if ((urb = p_priv->in_urbs[i]) == NULL) + continue; + urb->dev = serial->dev; + if ((err = usb_submit_urb(urb)) != 0) { + dbg(__FUNCTION__ " submit urb %d failed (%d)", i, err); + } } - - keyspan_usa19_send_setup(serial, port); +/* Now done in startup routine + if (atomic_inc_return(&s_priv->active_count) == 1) { + s_priv->instat_urb->dev = serial->dev; + if ((err = usb_submit_urb(s_priv->instat_urb)) != 0) { + dbg(__FUNCTION__ " submit instat urb failed %d", err); + } + } +*/ + + keyspan_send_setup(port); return (0); } +static inline void stop_urb(urb_t *urb) +{ + if (urb && urb->status == -EINPROGRESS) { + urb->transfer_flags &= ~USB_ASYNC_UNLINK; + usb_unlink_urb(urb); + } +} static void keyspan_close(struct usb_serial_port *port, struct file *filp) { int i; struct usb_serial *serial = port->serial; /* FIXME should so sanity check */ struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + unsigned long flags; + /* dbg("keyspan_close called"); */ s_priv = (struct keyspan_serial_private *)(serial->private); - - /* Stop reading/writing urbs */ - for (i = 0; i < 4; i++) { - if (s_priv->in_urbs[i]) { - usb_unlink_urb(s_priv->in_urbs[i]); - } + p_priv = (struct keyspan_port_private *)(port->private); - } - for (i = 0; i < 3; i++) { - if (s_priv->out_urbs[i]) { - usb_unlink_urb(s_priv->out_urbs[i]); - } + spin_lock_irqsave (&port->port_lock, flags); + if (--port->open_count <= 0) { + if (port->active) { + /* Stop reading/writing urbs */ + stop_urb(p_priv->inack_urb); + stop_urb(p_priv->outcont_urb); + for (i = 0; i < 2; i++) { + stop_urb(p_priv->in_urbs[i]); + stop_urb(p_priv->out_urbs[i]); + } + /* Now done in shutdown + if (atomic_dec_return(&s_priv->active_count) <= 0) { + stop_urb(s_priv->instat_urb); + stop_urb(s_priv->glocont_urb); + } */ + } + port->active = 0; + port->open_count = 0; + port->tty = 0; } - port->active = 0; - dbg("keyspan_close called\n"); + spin_unlock_irqrestore (&port->port_lock, flags); + + MOD_DEC_USE_COUNT; } @@ -394,47 +922,59 @@ const struct ezusb_hex_record *record; char *fw_name; - dbg("Keyspan startup version %04x product %04x\n", serial->dev->descriptor.bcdDevice, - serial->dev->descriptor.idProduct); + dbg("Keyspan startup version %04x product %04x", + serial->dev->descriptor.bcdDevice, + serial->dev->descriptor.idProduct); if ((serial->dev->descriptor.bcdDevice & 0x8000) != 0x8000) { - dbg("Firmware already loaded. Quitting.\n"); + dbg("Firmware already loaded. Quitting."); return(1); } /* Select firmware image on the basis of idProduct */ switch (serial->dev->descriptor.idProduct) { - case 0x0101: record = &keyspan_usa28_firmware[0]; - fw_name = "USA28"; - break; - - case 0x0102: record = &keyspan_usa28x_firmware[0]; - fw_name = "USA28X"; - break; - - case 0x0103: record = &keyspan_usa19_firmware[0]; - fw_name = "USA19"; - break; + case 0x0101: + record = &keyspan_usa28_firmware[0]; + fw_name = "USA28"; + break; + + case 0x0102: + record = &keyspan_usa28x_firmware[0]; + fw_name = "USA28X"; + break; + + case 0x0103: + record = &keyspan_usa19_firmware[0]; + fw_name = "USA19"; + break; - case 0x0105: record = &keyspan_usa18x_firmware[0]; - fw_name = "USA18X"; - break; + case 0x0105: + record = &keyspan_usa18x_firmware[0]; + fw_name = "USA18X"; + break; - case 0x0106: record = &keyspan_usa19w_firmware[0]; - fw_name = "USA19W"; - break; + case 0x0106: + record = &keyspan_usa19w_firmware[0]; + fw_name = "USA19W"; + break; - default: record = NULL; - fw_name = "Unknown"; - break; + case 0x0109: + record = &keyspan_usa49w_firmware[0]; + fw_name = "USA49W"; + break; + + default: + record = NULL; + fw_name = "Unknown"; + break; } if (record == NULL) { - err("Required keyspan firmware image (%s) unavailable.\n", fw_name); + err("Required keyspan firmware image (%s) unavailable.", fw_name); return(1); } - dbg("Uploading Keyspan %s firmware.\n", fw_name); + dbg("Uploading Keyspan %s firmware.", fw_name); /* download the firmware image */ response = ezusb_set_reset(serial, 1); @@ -456,72 +996,165 @@ moment and the new device will bind to the real driver */ response = ezusb_set_reset(serial, 0); - /* we don't want this device to have a driver assigned to it. */ + /* we don't want this device to have a driver assigned to it. */ return (1); } - /* USA-19 uses three output endpoints and four input - endpoints. First two output endpoints are for - data (used in an alternating fashion), the third is - output control. First two input endpoints are for - data (again alternating), the third is the ACK - endpoint, the fourth is input status. */ -static void keyspan_usa19_setup_urbs(struct usb_serial *serial) +/* Helper functions used by keyspan_setup_urbs */ +static urb_t *keyspan_setup_urb(struct usb_serial *serial, int endpoint, + int dir, void *ctx, char *buf, int len, + void (*callback)(urb_t *)) { + urb_t *urb; + + if (endpoint == -1) + return NULL; /* endpoint not needed */ + + /* dbg (__FUNCTION__ " alloc for endpoint %d.", endpoint); */ + urb = usb_alloc_urb(0); /* No ISO */ + if (urb == NULL) { + dbg (__FUNCTION__ " alloc for endpoint %d failed.", endpoint); + return NULL; + } + + /* Fill URB using supplied data. */ + FILL_BULK_URB(urb, serial->dev, + usb_sndbulkpipe(serial->dev, endpoint) | dir, + buf, len, callback, ctx); + + return urb; +} + +struct callbacks { + void (*instat_callback)(urb_t *); + void (*glocont_callback)(urb_t *); + void (*indat_callback)(urb_t *); + void (*outdat_callback)(urb_t *); + void (*inack_callback)(urb_t *); + void (*outcont_callback)(urb_t *); +} keyspan_callbacks[] = { + { + /* msg_usa26 callbacks */ + instat_callback: usa26_instat_callback, + glocont_callback: usa26_glocont_callback, + indat_callback: usa26_indat_callback, + outdat_callback: usa2x_outdat_callback, + inack_callback: usa26_inack_callback, + outcont_callback: usa26_outcont_callback, + }, { + /* msg_usa28 callbacks */ + instat_callback: usa28_instat_callback, + glocont_callback: usa28_glocont_callback, + indat_callback: usa28_indat_callback, + outdat_callback: usa2x_outdat_callback, + inack_callback: usa28_inack_callback, + outcont_callback: usa28_outcont_callback, + }, { + /* msg_usa49 callbacks */ + instat_callback: usa49_instat_callback, + glocont_callback: usa49_glocont_callback, + indat_callback: usa49_indat_callback, + outdat_callback: usa2x_outdat_callback, + inack_callback: usa49_inack_callback, + outcont_callback: usa49_outcont_callback, + } +}; + + /* Generic setup urbs function that uses + data in device_details */ +static void keyspan_setup_urbs(struct usb_serial *serial) +{ + int i, j; struct keyspan_serial_private *s_priv; - int i; + const keyspan_device_details *d_details; + struct usb_serial_port *port; + struct keyspan_port_private *p_priv; + struct callbacks *cback; + int endp; + + /* dbg (__FUNCTION__); */ s_priv = (struct keyspan_serial_private *)(serial->private); + d_details = s_priv->device_details; - /* Output urbs first */ - dbg(__FUNCTION__ "Allocating output urbs.\n"); - for (i = 0; i < 3; i++) { - - s_priv->out_urbs[i] = usb_alloc_urb (0); /* No ISO */ - if (!s_priv->out_urbs[i]) { - dbg (__FUNCTION__ "Alloc for %d out urb failed.\n", i); - return; - } + /* Setup values for the various callback routines */ + cback = &keyspan_callbacks[d_details->msg_format]; - FILL_BULK_URB(s_priv->out_urbs[i], serial->dev, - usb_sndbulkpipe(serial->dev, i + 1), - &s_priv->out_buffer[i], sizeof(s_priv->out_buffer[i]), - keyspan_write_bulk_callback, - serial); - } + /* Allocate and set up urbs for each one that is in use, + starting with instat endpoints */ + s_priv->instat_urb = keyspan_setup_urb + (serial, d_details->instat_endpoint, USB_DIR_IN, + serial, s_priv->instat_buf, INSTAT_BUFLEN, + cback->instat_callback); + + s_priv->glocont_urb = keyspan_setup_urb + (serial, d_details->glocont_endpoint, USB_DIR_OUT, + serial, s_priv->glocont_buf, GLOCONT_BUFLEN, + cback->glocont_callback); - /* Now input urbs */ - dbg(__FUNCTION__ "Allocating input urbs.\n"); - for (i = 0; i < 4; i++) { - - s_priv->in_urbs[i] = usb_alloc_urb (0); /* No ISO */ - if (!s_priv->in_urbs[i]) { - dbg (__FUNCTION__ "Alloc for %d in urb failed.\n", i); - return; + /* Setup endpoints for each port specific thing */ + for (i = 0; i < d_details->num_ports; i ++) { + port = &serial->port[i]; + p_priv = (struct keyspan_port_private *)(port->private); + + /* Do indat endpoints first, once for each flip */ + endp = d_details->indat_endpoints[i]; + for (j = 0; j <= d_details->indat_endp_flip; ++j, ++endp) { + p_priv->in_urbs[j] = keyspan_setup_urb + (serial, endp, USB_DIR_IN, port, + p_priv->in_buffer[j], 64, + cback->indat_callback); } + for (; j < 2; ++j) + p_priv->in_urbs[j] = NULL; + + /* outdat endpoints also have flip */ + endp = d_details->outdat_endpoints[i]; + for (j = 0; j <= d_details->outdat_endp_flip; ++j, ++endp) { + p_priv->out_urbs[j] = keyspan_setup_urb + (serial, endp, USB_DIR_OUT, port, + p_priv->out_buffer[j], 64, + cback->outdat_callback); + } + for (; j < 2; ++j) + p_priv->out_urbs[j] = NULL; + + /* inack endpoint */ + p_priv->inack_urb = keyspan_setup_urb + (serial, d_details->inack_endpoints[i], USB_DIR_IN, + port, p_priv->inack_buffer, 1, cback->inack_callback); + + /* outcont endpoint */ + p_priv->outcont_urb = keyspan_setup_urb + (serial, d_details->outcont_endpoints[i], USB_DIR_OUT, + port, p_priv->outcont_buffer, 64, + cback->outcont_callback); + } - FILL_BULK_URB(s_priv->in_urbs[i], serial->dev, - usb_rcvbulkpipe(serial->dev, i + 0x81), - &s_priv->in_buffer[i], sizeof(s_priv->in_buffer[i]), - keyspan_read_bulk_callback, - serial); - } - } -static int keyspan_usa19_calc_baud(u32 baud_rate, u8 *rate_hi, u8 *rate_low) +/* usa19 function doesn't require prescaler */ +static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, + u8 *rate_hi, u8 *rate_low, u8 *prescaler) { - u32 b16, /* baud rate times 16 (actual rate used internally) */ + u32 b16, /* baud rate times 16 (actual rate used internally) */ div, /* divisor */ cnt; /* inverse of divisor (programmed into 8051) */ + /* prevent divide by zero... */ if( (b16 = (baud_rate * 16L)) == 0) { return (KEYSPAN_INVALID_BAUD_RATE); } + /* Any "standard" rate over 57k6 is marginal on the USA-19 + as we run out of divisor resolution. */ + if (baud_rate > 57600) { + return (KEYSPAN_INVALID_BAUD_RATE); + } + /* calculate the divisor and the counter (its inverse) */ - if( (div = (USA19_BAUDCLK / b16)) == 0) { + if( (div = (baudclk / b16)) == 0) { return (KEYSPAN_INVALID_BAUD_RATE); } else { @@ -532,217 +1165,520 @@ return (KEYSPAN_INVALID_BAUD_RATE); } - /* return the counter values */ - *rate_low = (u8) (cnt & 0xff); - *rate_hi = (u8) ((cnt >> 8) & 0xff); + /* return the counter values if non-null */ + if (rate_low) { + *rate_low = (u8) (cnt & 0xff); + } + if (rate_hi) { + *rate_hi = (u8) ((cnt >> 8) & 0xff); + } + if (rate_low && rate_hi) { + dbg (__FUNCTION__ " %d %02x %02x.", baud_rate, *rate_hi, *rate_low); + } - dbg(__FUNCTION__ " Baud rate of %d is %02x %02x.\n", baud_rate, *rate_hi, *rate_low); + return (KEYSPAN_BAUD_RATE_OK); +} + +static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, + u8 *rate_hi, u8 *rate_low, u8 *prescaler) +{ + u32 b16, /* baud rate times 16 (actual rate used internally) */ + clk, /* clock with 13/8 prescaler */ + div, /* divisor using 13/8 prescaler */ + res, /* resulting baud rate using 13/8 prescaler */ + diff, /* error using 13/8 prescaler */ + smallest_diff; + u8 best_prescaler; + int i; + + /* dbg (__FUNCTION__ " %d.", baud_rate); */ + /* prevent divide by zero */ + if( (b16 = baud_rate * 16L) == 0) { + return (KEYSPAN_INVALID_BAUD_RATE); + } + + /* Calculate prescaler by trying them all and looking + for best fit */ + + /* start with largest possible difference */ + smallest_diff = 0xffffffff; + + /* 0 is an invalid prescaler, used as a flag */ + best_prescaler = 0; + + for(i = 8; i <= 0xff; ++i) + { + clk = (baudclk * 8) / (u32) i; + + if( (div = clk / b16) == 0) { + continue; + } + + res = clk / div; + diff= (res > b16) ? (res-b16) : (b16-res); + + if(diff < smallest_diff) + { + best_prescaler = i; + smallest_diff = diff; + } + } + + if(best_prescaler == 0) { + return (KEYSPAN_INVALID_BAUD_RATE); + } + + clk = (baudclk * 8) / (u32) best_prescaler; + div = clk / b16; + + /* return the divisor and prescaler if non-null */ + if (rate_low) { + *rate_low = (u8) (div & 0xff); + } + if (rate_hi) { + *rate_hi = (u8) ((div >> 8) & 0xff); + } + if (prescaler) { + *prescaler = best_prescaler; + /* dbg(__FUNCTION__ " %d %d", *prescaler, div); */ + } return (KEYSPAN_BAUD_RATE_OK); } -static int keyspan_usa19_send_setup(struct usb_serial *serial, struct usb_serial_port *port) +static int keyspan_usa26_send_setup(struct usb_serial *serial, + struct usb_serial_port *port) { - struct portControlMessage msg; - struct keyspan_serial_private *s_priv; - struct keyspan_port_private *p_priv; + struct keyspan_usa26_portControlMessage msg; + struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const keyspan_device_details *d_details; + int outcont_urb; + urb_t *this_urb; + int err; + + /* dbg (__FUNCTION__); */ s_priv = (struct keyspan_serial_private *)(serial->private); p_priv = (struct keyspan_port_private *)(port->private); + d_details = s_priv->device_details; + + outcont_urb = d_details->outcont_endpoints[port->number]; + this_urb = p_priv->outcont_urb; + + /* Make sure we have an urb then send the message */ + if (this_urb == NULL) { + dbg(__FUNCTION__ " oops no urb."); + return -1; + } + + p_priv->resend_cont = 1; + if (this_urb->status == -EINPROGRESS) { + /* dbg (__FUNCTION__ " already writing"); */ + return(-1); + } + + memset(&msg, 0, sizeof (struct keyspan_usa26_portControlMessage)); + + /* Only set baud rate if it's changed */ + if (p_priv->old_baud != p_priv->baud) { + p_priv->old_baud = p_priv->baud; + msg.setClocking = 0xff; + if (d_details->calculate_baud_rate + (p_priv->baud, d_details->baudclk, &msg.baudHi, + &msg.baudLo, &msg.prescaler) == KEYSPAN_INVALID_BAUD_RATE ) { + dbg(__FUNCTION__ "Invalid baud rate %d requested, using 9600.", + p_priv->baud); + msg.baudLo = 0; + msg.baudHi = 125; /* Values for 9600 baud */ + msg.prescaler = 10; + } + msg.setPrescaler = 0xff; + } + + msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1; + if (p_priv->cflag & PARENB) { + /* note USA_PARITY_NONE == 0 */ + msg.lcr |= (p_priv->cflag & PARODD)? + USA_PARITY_ODD: USA_PARITY_EVEN; + } + msg.setLcr = 0xff; + + msg.ctsFlowControl = (p_priv->flow_control == flow_cts); + msg.xonFlowControl = 0; + msg.setFlowControl = 0xff; + + msg.forwardingLength = 1; + msg.xonChar = 17; + msg.xoffChar = 19; + + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 0; + msg.rxForward = 0; + /*msg.returnStatus = 1; + msg.resetDataToggle = 0xff;*/ + + /* Do handshaking outputs */ + msg.setTxTriState_setRts = 0xff; + msg.txTriState_rts = p_priv->rts_state; - //memset(msg, 0, sizeof (struct portControlMessage)); + msg.setHskoa_setDtr = 0xff; + msg.hskoa_dtr = p_priv->dtr_state; + p_priv->resend_cont = 0; + memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); + + /* send the data out the device on control endpoint */ + this_urb->transfer_buffer_length = sizeof(msg); + + this_urb->dev = serial->dev; + if ((err = usb_submit_urb(this_urb)) != 0) { + dbg(__FUNCTION__ " usb_submit_urb(setup) failed (%d)", err); + } +#if 0 + else { + dbg(__FUNCTION__ " usb_submit_urb(%d) OK %d bytes (end %d)", + outcont_urb, this_urb->transfer_buffer_length, + usb_pipeendpoint(this_urb->pipe)); + } +#endif + + return (0); +} + +static int keyspan_usa28_send_setup(struct usb_serial *serial, + struct usb_serial_port *port) +{ + struct keyspan_usa28_portControlMessage msg; + struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const keyspan_device_details *d_details; + urb_t *this_urb; + int err; + + s_priv = (struct keyspan_serial_private *)(serial->private); + p_priv = (struct keyspan_port_private *)(port->private); + d_details = s_priv->device_details; + + /* only do something if we have a bulk out endpoint */ + if ((this_urb = p_priv->outcont_urb) == NULL) { + dbg(__FUNCTION__ " oops no urb."); + return -1; + } + + p_priv->resend_cont = 1; + if (this_urb->status == -EINPROGRESS) { + dbg (__FUNCTION__ " already writing"); + return(-1); + } + + memset(&msg, 0, sizeof (struct keyspan_usa28_portControlMessage)); + msg.setBaudRate = 1; - if (keyspan_usa19_calc_baud(9600, &msg.baudHi, &msg.baudLo) == - KEYSPAN_INVALID_BAUD_RATE ) { - dbg(__FUNCTION__ "Invalid baud rate requested %d.\n", 9600); + if (keyspan_usa19_calc_baud(p_priv->baud, d_details->baudclk, + &msg.baudHi, &msg.baudLo, NULL) == KEYSPAN_INVALID_BAUD_RATE ) { + dbg(__FUNCTION__ "Invalid baud rate requested %d.", 9600); msg.baudLo = 0xff; msg.baudHi = 0xb2; /* Values for 9600 baud */ } - /* If parity is enabled, we must calculate it ourselves. */ - if (p_priv->parity) { - msg.parity = 1; + /* If parity is enabled, we must calculate it ourselves. */ + msg.parity = 0; /* XXX for now */ + + msg.ctsFlowControl = (p_priv->flow_control == flow_cts); + msg.xonFlowControl = 0; + + /* Do handshaking outputs, DTR is inverted relative to RTS */ + msg.rts = p_priv->rts_state; + msg.dtr = p_priv->dtr_state; + + msg.forwardingLength = 1; + msg.forwardMs = 10; + msg.breakThreshold = 45; + msg.xonChar = 17; + msg.xoffChar = 19; + + msg._txOn = 1; + msg._txOff = 0; + msg.txFlush = 0; + msg.txForceXoff = 0; + msg.txBreak = 0; + msg.rxOn = 1; + msg.rxOff = 0; + msg.rxFlush = 0; + msg.rxForward = 0; + /*msg.returnStatus = 1; + msg.resetDataToggle = 0xff;*/ + + p_priv->resend_cont = 0; + memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); + + /* send the data out the device on control endpoint */ + this_urb->transfer_buffer_length = sizeof(msg); + + this_urb->dev = serial->dev; + if ((err = usb_submit_urb(this_urb)) != 0) { + dbg(__FUNCTION__ " usb_submit_urb(setup) failed"); } +#if 0 else { - msg.parity = 0; + dbg(__FUNCTION__ " usb_submit_urb(setup) OK %d bytes", + this_urb->transfer_buffer_length); } +#endif + + return (0); +} - msg.ctsFlowControl = 0; +static int keyspan_usa49_send_setup(struct usb_serial *serial, + struct usb_serial_port *port) +{ + struct keyspan_usa49_portControlMessage msg; + struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const keyspan_device_details *d_details; + int glocont_urb; + urb_t *this_urb; + int err; + + /* dbg (__FUNCTION__); */ + + s_priv = (struct keyspan_serial_private *)(serial->private); + p_priv = (struct keyspan_port_private *)(port->private); + d_details = s_priv->device_details; + + glocont_urb = d_details->glocont_endpoint; + this_urb = s_priv->glocont_urb; + + /* dbg(__FUNCTION__ " port %d\n", port->number); */ + + /* Make sure we have an urb then send the message */ + if (this_urb == NULL) { + dbg(__FUNCTION__ " oops no urb for port %d.", port->number); + return -1; + } + + p_priv->resend_cont = 1; + if (this_urb->status == -EINPROGRESS) { + /* dbg (__FUNCTION__ " already writing"); */ + return(-1); + } + + memset(&msg, 0, sizeof (struct keyspan_usa49_portControlMessage)); + + msg.portNumber = port->number; + + /* Only set baud rate if it's changed */ + if (p_priv->old_baud != p_priv->baud) { + p_priv->old_baud = p_priv->baud; + msg.setClocking = 0xff; + if (d_details->calculate_baud_rate + (p_priv->baud, d_details->baudclk, &msg.baudHi, + &msg.baudLo, &msg.prescaler) == KEYSPAN_INVALID_BAUD_RATE ) { + dbg(__FUNCTION__ "Invalid baud rate %d requested, using 9600.", + p_priv->baud); + msg.baudLo = 0; + msg.baudHi = 125; /* Values for 9600 baud */ + msg.prescaler = 10; + } + //msg.setPrescaler = 0xff; + } + + msg.lcr = USA_DATABITS_8 | STOPBITS_5678_1; + if (p_priv->cflag & PARENB) { + /* note USA_PARITY_NONE == 0 */ + msg.lcr |= (p_priv->cflag & PARODD)? + USA_PARITY_ODD: USA_PARITY_EVEN; + } + msg.setLcr = 0xff; + + msg.ctsFlowControl = (p_priv->flow_control == flow_cts); msg.xonFlowControl = 0; - msg.rts = 1; - msg.dtr = 0; + msg.setFlowControl = 0xff; msg.forwardingLength = 1; - msg.forwardMs = 10; - msg.breakThreshold = 45; msg.xonChar = 17; msg.xoffChar = 19; msg._txOn = 1; msg._txOff = 0; msg.txFlush = 0; - msg.txForceXoff = 0; msg.txBreak = 0; msg.rxOn = 1; msg.rxOff = 0; msg.rxFlush = 0; msg.rxForward = 0; - msg.returnStatus = 1; - msg.resetDataToggle = 1; + msg.enablePort = 0xff; + msg.disablePort = 0; - - /* only do something if we have a bulk out endpoint */ - if (s_priv->out_urbs[2]) { - if (s_priv->out_urbs[2]->status == -EINPROGRESS) { - dbg (__FUNCTION__ " already writing"); - return(-1); - } - memcpy (s_priv->out_urbs[2]->transfer_buffer, &msg, sizeof(msg)); - - /* send the data out the device on control endpoint */ - s_priv->out_urbs[2]->transfer_buffer_length = sizeof(msg); - s_priv->out_urbs[2]->dev = serial->dev; + /* Do handshaking outputs */ + msg.setRts = 0xff; + msg.rts = p_priv->rts_state; - if (usb_submit_urb(s_priv->out_urbs[2])) { - dbg(__FUNCTION__ " usb_submit_urb(setup) failed\n"); - } - else { - dbg(__FUNCTION__ " usb_submit_urb(setup) OK %d bytes\n", s_priv->out_urbs[2]->transfer_buffer_length); - } + msg.setDtr = 0xff; + msg.dtr = p_priv->dtr_state; + + p_priv->resend_cont = 0; + memcpy (this_urb->transfer_buffer, &msg, sizeof(msg)); + /* send the data out the device on control endpoint */ + this_urb->transfer_buffer_length = sizeof(msg); + + this_urb->dev = serial->dev; + if ((err = usb_submit_urb(this_urb)) != 0) { + dbg(__FUNCTION__ " usb_submit_urb(setup) failed (%d)", err); } +#if 0 + else { + dbg(__FUNCTION__ " usb_submit_urb(%d) OK %d bytes (end %d)", + outcont_urb, this_urb->transfer_buffer_length, + usb_pipeendpoint(this_urb->pipe)); + } +#endif + return (0); } +static void keyspan_send_setup(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + struct keyspan_serial_private *s_priv; + const keyspan_device_details *d_details; - /* Gets called by the "real" driver (ie once firmware is loaded - and renumeration has taken place. */ + s_priv = (struct keyspan_serial_private *)(serial->private); + d_details = s_priv->device_details; + + switch (d_details->msg_format) { + case msg_usa26: + keyspan_usa26_send_setup(serial, port); + break; + case msg_usa28: + keyspan_usa28_send_setup(serial, port); + break; + case msg_usa49: + keyspan_usa49_send_setup(serial, port); + break; + } +} + +/* Gets called by the "real" driver (ie once firmware is loaded + and renumeration has taken place. */ static int keyspan_startup (struct usb_serial *serial) { - int i; - struct usb_serial_port *port; + int i, err; + struct usb_serial_port *port; + struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; + const keyspan_device_details *d_details; - dbg("keyspan_startup called.\n"); + /* dbg("keyspan_startup called."); */ - /* Setup private data for serial driver */ - serial->private = kmalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); + for (i = 0; (d_details = keyspan_devices[i]) != NULL; ++i) + if (d_details->product_id == serial->dev->descriptor.idProduct) + break; + if (d_details == NULL) { + printk(KERN_ERR __FUNCTION__ ": unknown product id %x\n", + serial->dev->descriptor.idProduct); + return 1; + } + + /* Setup private data for serial driver */ + serial->private = kmalloc(sizeof(struct keyspan_serial_private), + GFP_KERNEL); if (!serial->private) { - dbg(__FUNCTION__ "kmalloc for keyspan_serial_private failed!.\n"); + dbg(__FUNCTION__ "kmalloc for keyspan_serial_private failed."); return (1); } memset(serial->private, 0, sizeof(struct keyspan_serial_private)); + + s_priv = (struct keyspan_serial_private *)(serial->private); + s_priv->device_details = d_details; - init_waitqueue_head(&out_wait); - - /* Now setup per port private data */ + /* Now setup per port private data */ for (i = 0; i < serial->num_ports; i++) { port = &serial->port[i]; - port->private = kmalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); + port->private = kmalloc(sizeof(struct keyspan_port_private), + GFP_KERNEL); if (!port->private) { - dbg(__FUNCTION__ "kmalloc for keyspan_port_private (%d) failed!.\n", i); + dbg(__FUNCTION__ "kmalloc for keyspan_port_private (%d) failed!.", i); return (1); } memset(port->private, 0, sizeof(struct keyspan_port_private)); + p_priv = (struct keyspan_port_private *)(port->private); + p_priv->device_details = d_details; } - + keyspan_setup_urbs(serial); - switch (serial->dev->descriptor.idProduct) { - case 0x0107: keyspan_usa19_setup_urbs(serial); - //keyspan_send_usa19_setup(serial); - break; - - default: break; + s_priv->instat_urb->dev = serial->dev; + if ((err = usb_submit_urb(s_priv->instat_urb)) != 0) { + dbg(__FUNCTION__ " submit instat urb failed %d", err); } - return (0); } static void keyspan_shutdown (struct usb_serial *serial) { - int i; + int i, j; struct usb_serial_port *port; struct keyspan_serial_private *s_priv; + struct keyspan_port_private *p_priv; - dbg("keyspan_shutdown called freeing "); + /* dbg("keyspan_shutdown called"); */ s_priv = (struct keyspan_serial_private *)(serial->private); - /* Stop reading/writing urbs */ - for (i = 0; i < 4; i++) { - if (s_priv->in_urbs[i]) { - usb_unlink_urb(s_priv->in_urbs[i]); + /* Stop reading/writing urbs */ + stop_urb(s_priv->instat_urb); + stop_urb(s_priv->glocont_urb); + for (i = 0; i < serial->num_ports; ++i) { + port = &serial->port[i]; + p_priv = (struct keyspan_port_private *)(port->private); + stop_urb(p_priv->inack_urb); + stop_urb(p_priv->outcont_urb); + for (j = 0; j < 2; j++) { + stop_urb(p_priv->in_urbs[j]); + stop_urb(p_priv->out_urbs[j]); } - } - for (i = 0; i < 3; i++) { - if (s_priv->out_urbs[i]) { - usb_unlink_urb(s_priv->out_urbs[i]); - } - } - /* Now free them */ - for (i = 0; i < 7; i ++) { - if (s_priv->in_urbs[i] != NULL) { - dbg("in%d ", i); - usb_free_urb(s_priv->in_urbs[i]); - } - - if (s_priv->out_urbs[i] != NULL) { - dbg("out%d ", i); - usb_free_urb(s_priv->out_urbs[i]); + /* Now free them */ + if (s_priv->instat_urb) + usb_free_urb(s_priv->instat_urb); + if (s_priv->glocont_urb) + usb_free_urb(s_priv->glocont_urb); + for (i = 0; i < serial->num_ports; ++i) { + port = &serial->port[i]; + p_priv = (struct keyspan_port_private *)(port->private); + if (p_priv->inack_urb) + usb_free_urb(p_priv->inack_urb); + if (p_priv->outcont_urb) + usb_free_urb(p_priv->outcont_urb); + for (j = 0; j < 2; j++) { + if (p_priv->in_urbs[j]) + usb_free_urb(p_priv->in_urbs[j]); + if (p_priv->out_urbs[j]) + usb_free_urb(p_priv->out_urbs[j]); } } - dbg("urbs.\n"); - dbg("Freeing serial->private.\n"); + /* dbg("Freeing serial->private."); */ kfree(serial->private); - dbg("Freeing port->private.\n"); - /* Now free per port private data */ + /* dbg("Freeing port->private."); */ + /* Now free per port private data */ for (i = 0; i < serial->num_ports; i++) { port = &serial->port[i]; + while (port->open_count > 0) { + --port->open_count; + MOD_DEC_USE_COUNT; + } kfree(port->private); } - -} - - -static int __init keyspan_init (void) -{ - usb_serial_register (&keyspan_usa18x_pre_device); - usb_serial_register (&keyspan_usa19_pre_device); - usb_serial_register (&keyspan_usa19w_pre_device); - usb_serial_register (&keyspan_usa28_pre_device); - usb_serial_register (&keyspan_usa28x_pre_device); - usb_serial_register (&keyspan_usa18x_device); - usb_serial_register (&keyspan_usa19_device); - usb_serial_register (&keyspan_usa19w_device); - usb_serial_register (&keyspan_usa28_device); - usb_serial_register (&keyspan_usa28x_device); - return 0; } - - -static void __exit keyspan_exit (void) -{ - usb_serial_deregister (&keyspan_usa18x_pre_device); - usb_serial_deregister (&keyspan_usa19_pre_device); - usb_serial_deregister (&keyspan_usa19w_pre_device); - usb_serial_deregister (&keyspan_usa28_pre_device); - usb_serial_deregister (&keyspan_usa28x_pre_device); - usb_serial_deregister (&keyspan_usa18x_device); - usb_serial_deregister (&keyspan_usa19_device); - usb_serial_deregister (&keyspan_usa19w_device); - usb_serial_deregister (&keyspan_usa28_device); - usb_serial_deregister (&keyspan_usa28x_device); -} - - -module_init(keyspan_init); -module_exit(keyspan_exit); - -MODULE_AUTHOR("Hugh Blemings "); -MODULE_DESCRIPTION("Keyspan USB to Serial Converter driver"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan.h linux/drivers/usb/serial/keyspan.h --- v2.4.0-test11/linux/drivers/usb/serial/keyspan.h Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/keyspan.h Mon Dec 11 13:47:32 2000 @@ -19,6 +19,11 @@ and Keyspan, Inc the manufacturers of the Keyspan USB-serial products. Thanks Guys :) + Thanks to Paulus for miscellaneous tidy ups, some largish chunks + of much nicer and/or completely new code and (perhaps most uniquely) + having the patience to sit down and explain why and where he'd changed + stuff. + Tip 'o the hat to Linuxcare for supporting staff in their work on open source projects. @@ -41,12 +46,18 @@ static void keyspan_rx_throttle (struct usb_serial_port *port); static void keyspan_rx_unthrottle (struct usb_serial_port *port); static int keyspan_write_room (struct usb_serial_port *port); + static int keyspan_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); + +#if 0 static void keyspan_write_bulk_callback (struct urb *urb); -static void keyspan_read_bulk_callback (struct urb *urb); +#endif + +//static void keyspan_usa26_read_int_callback (struct urb *urb); +//static void keyspan_usa28_read_int_callback (struct urb *urb); static int keyspan_chars_in_buffer (struct usb_serial_port *port); static int keyspan_ioctl (struct usb_serial_port *port, struct file *file, @@ -58,12 +69,20 @@ int break_state); static int keyspan_fake_startup (struct usb_serial *serial); -static int keyspan_usa19_calc_baud (u32 baud_rate, u8 *rate_hi, - u8 *rate_low); -static void keyspan_usa19_setup_urbs (struct usb_serial *serial); -static int keyspan_usa19_send_setup (struct usb_serial *serial, - struct usb_serial_port *port); +static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk, + u8 *rate_hi, u8 *rate_low, u8 *prescaler); + +static int keyspan_usa19w_calc_baud (u32 baud_rate, u32 baudclk, + u8 *rate_hi, u8 *rate_low, u8 *prescaler); + +//static void keyspan_usa19_setup_urbs (struct usb_serial *serial); +static int keyspan_usa28_send_setup (struct usb_serial *serial, + struct usb_serial_port *port); +static int keyspan_usa26_send_setup (struct usb_serial *serial, + struct usb_serial_port *port); +static int keyspan_usa49_send_setup (struct usb_serial *serial, + struct usb_serial_port *port); /* Functions from usbserial.c for ezusb firmware handling */ extern int ezusb_set_reset (struct usb_serial *serial, unsigned char reset_bit); @@ -109,13 +128,162 @@ static const struct ezusb_hex_record *keyspan_usa19w_firmware = NULL; #endif - +#ifdef CONFIG_USB_SERIAL_KEYSPAN_USA49W + #include "keyspan_usa49w_fw.h" +#else + static const struct ezusb_hex_record *keyspan_usa49w_firmware = NULL; +#endif + /* Values used for baud rate calculation - device specific */ #define KEYSPAN_INVALID_BAUD_RATE (-1) #define KEYSPAN_BAUD_RATE_OK (0) -#define USA19_BAUDCLK (12000000L) +#define KEYSPAN_USA18X_BAUDCLK (12000000L) /* a guess */ +#define KEYSPAN_USA19_BAUDCLK (12000000L) +#define KEYSPAN_USA19W_BAUDCLK (24000000L) +#define KEYSPAN_USA28X_BAUDCLK (12000000L) +#define KEYSPAN_USA49W_BAUDCLK (48000000L) + + /* Some constants used to characterise each device. + There is a four port device due later in the year, + we allow for it now in the following */ +#define KEYSPAN_MAX_NUM_PORTS (4) +#define KEYSPAN_MAX_FLIPS (2) + +typedef struct { + /* product ID value */ + int product_id; + + enum {msg_usa26, msg_usa28, msg_usa49} msg_format; + + /* Number of physical ports */ + int num_ports; + + /* 1 if endpoint flipping used on input, 0 if not */ + int indat_endp_flip; + + /* 1 if endpoint flipping used on output, 0 if not */ + int outdat_endp_flip; + + /* Table mapping input data endpoint IDs to physical + port number and flip if used */ + int indat_endpoints[KEYSPAN_MAX_NUM_PORTS]; + + /* Same for output endpoints */ + int outdat_endpoints[KEYSPAN_MAX_NUM_PORTS]; + + /* Input acknowledge endpoints */ + int inack_endpoints[KEYSPAN_MAX_NUM_PORTS]; + + /* Output control endpoints */ + int outcont_endpoints[KEYSPAN_MAX_NUM_PORTS]; + + /* Endpoint used for input status */ + int instat_endpoint; + + /* Endpoint used for global control functions */ + int glocont_endpoint; + + int (*calculate_baud_rate) (u32 baud_rate, u32 baudclk, + u8 *rate_hi, u8 *rate_low, u8 *prescaler); + u32 baudclk; + +} keyspan_device_details; + + /* Now for each device type we setup the device detail + structure with the appropriate information (provided + in Keyspan's documentation) */ + +static const keyspan_device_details usa18x_device_details = { + 0x112, /* product ID */ + msg_usa26, /* msg type*/ + 1, /* num ports */ + 0, /* indat endpoint flip */ + 1, /* outdat endpoint flip */ + {0x81}, /* per port indat */ + {0x01}, /* per port outdat */ + {0x85}, /* per port inack */ + {0x05}, /* per port outcont */ + 0x87, /* instat endpoint */ + 0x07, /* glocont endpoint */ + keyspan_usa19w_calc_baud, /* calc baud rate */ + KEYSPAN_USA18X_BAUDCLK /* base baud clock */ +}; + +static const keyspan_device_details usa19_device_details = { + 0x107, /* product ID */ + msg_usa28, /* msg type*/ + 1, /* num ports */ + 1, /* indat endpoint flip */ + 1, /* outdat endpoint flip */ + {0x81}, /* per port indat */ + {0x01}, /* per port outdat */ + {0x83}, /* per port inack */ + {0x03}, /* per port outcont */ + 0x84, /* instat endpoint */ + -1, /* glocont endpoint */ + keyspan_usa19_calc_baud, /* calc baud rate */ + KEYSPAN_USA19_BAUDCLK /* base baud clock */ +}; + +static const keyspan_device_details usa19w_device_details = { + 0x108, /* product ID */ + msg_usa26, /* msg type*/ + 1, /* num ports */ + 0, /* indat endpoint flip */ + 1, /* outdat endpoint flip */ + {0x81}, /* per port indat */ + {0x01}, /* per port outdat */ + {0x85}, /* per port inack */ + {0x05}, /* per port outcont */ + 0x87, /* instat endpoint */ + 0x07, /* glocont endpoint */ + keyspan_usa19w_calc_baud, /* calc baud rate */ + KEYSPAN_USA19W_BAUDCLK /* base baud clock */ +}; + +static const keyspan_device_details usa28x_device_details = { + 0x110, /* product ID */ + msg_usa26, /* msg type*/ + 2, /* num ports */ + 0, /* indat endpoint flip */ + 1, /* outdat endpoint flip */ + {0x81, 0x83}, /* per port indat */ + {0x01, 0x03}, /* per port outdat */ + {0x85, 0x86}, /* per port inack */ + {0x05, 0x06}, /* per port outcont */ + 0x87, /* instat endpoint */ + 0x07, /* glocont endpoint */ + keyspan_usa19w_calc_baud, /* calc baud rate */ + KEYSPAN_USA28X_BAUDCLK +}; + +static const keyspan_device_details usa49w_device_details = { + 0x010a, /* product ID */ + msg_usa49, /* msg type*/ + 4, /* num ports */ + 0, /* indat endpoint flip */ + 0, /* outdat endpoint flip */ + { 0x81, 0x82, 0x83, 0x84}, /* per port indat */ + { 0x01, 0x02, 0x03, 0x04}, /* per port outdat */ + {-1, -1, -1, -1}, /* per port inack */ + {-1, -1, -1, -1}, /* per port outcont */ + 0x87, /* instat endpoint */ + 0x07, /* glocont endpoint */ + keyspan_usa19w_calc_baud, /* calc baud rate */ + KEYSPAN_USA49W_BAUDCLK +}; + +static const keyspan_device_details *keyspan_devices[] = { + &usa18x_device_details, + &usa19_device_details, + &usa19w_device_details, + &usa28x_device_details, + &usa49w_device_details, + NULL +}; - /* Device info for the Keyspan serial converter */ + /* Device info for the Keyspan serial converter, used + by the overall usb-serial probe function */ #define KEYSPAN_VENDOR_ID (0x06cd) /* Product IDs for the five products supported, pre-renumeration */ @@ -124,6 +292,7 @@ #define keyspan_usa19w_pre_product_id 0x0106 #define keyspan_usa28_pre_product_id 0x0101 #define keyspan_usa28x_pre_product_id 0x0102 +#define keyspan_usa49w_pre_product_id 0x0109 /* Product IDs post-renumeration */ #define keyspan_usa18x_product_id 0x0112 @@ -131,6 +300,7 @@ #define keyspan_usa19w_product_id 0x0108 #define keyspan_usa28_product_id 0x010f #define keyspan_usa28x_product_id 0x0110 +#define keyspan_usa49w_product_id 0x010a static __devinitdata struct usb_device_id keyspan_ids_combined[] = { {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_pre_product_id}, @@ -138,11 +308,13 @@ {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19w_pre_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28_pre_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28x_pre_product_id}, + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_pre_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19w_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28_product_id}, {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28x_product_id}, + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_product_id}, { } /* Terminating entry */ }; @@ -177,6 +349,11 @@ { } /* Terminating entry */ }; +static __devinitdata struct usb_device_id keyspan_usa49w_pre_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_pre_product_id}, + { } /* Terminating entry */ +}; + static __devinitdata struct usb_device_id keyspan_usa18x_ids[] = { {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_product_id}, { } /* Terminating entry */ @@ -202,10 +379,15 @@ { } /* Terminating entry */ }; +static __devinitdata struct usb_device_id keyspan_usa49w_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa49w_product_id}, + { } /* Terminating entry */ +}; + /* Structs for the devices, pre and post renumeration. These are incomplete at present - HAB 20000708 */ struct usb_serial_device_type keyspan_usa18x_pre_device = { - name: "Keyspan USA18X - (prerenumeration)", + name: "Keyspan USA18X - (without firmware)", id_table: keyspan_usa18x_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, @@ -218,7 +400,7 @@ }; struct usb_serial_device_type keyspan_usa19_pre_device = { - name: "Keyspan USA19 - (prerenumeration)", + name: "Keyspan USA19 - (without firmware)", id_table: keyspan_usa19_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, @@ -232,7 +414,7 @@ struct usb_serial_device_type keyspan_usa19w_pre_device = { - name: "Keyspan USA19W - (prerenumeration)", + name: "Keyspan USA19W - (without firmware)", id_table: keyspan_usa19w_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, @@ -246,7 +428,7 @@ struct usb_serial_device_type keyspan_usa28_pre_device = { - name: "Keyspan USA28 - (prerenumeration)", + name: "Keyspan USA28 - (without firmware)", id_table: keyspan_usa28_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, @@ -259,7 +441,7 @@ }; struct usb_serial_device_type keyspan_usa28x_pre_device = { - name: "Keyspan USA28X - (prerenumeration)", + name: "Keyspan USA28X - (without firmware)", id_table: keyspan_usa28x_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, @@ -271,22 +453,43 @@ startup: keyspan_fake_startup }; +struct usb_serial_device_type keyspan_usa49w_pre_device = { + name: "Keyspan USA49W - (without firmware)", + id_table: keyspan_usa49w_pre_ids, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: DONT_CARE, + needs_bulk_out: DONT_CARE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: NUM_DONT_CARE, + num_bulk_out: NUM_DONT_CARE, + num_ports: 4, + startup: keyspan_fake_startup +}; struct usb_serial_device_type keyspan_usa18x_device = { name: "Keyspan USA18X", id_table: keyspan_usa18x_ids, needs_interrupt_in: DONT_CARE, - needs_bulk_in: DONT_CARE, - needs_bulk_out: DONT_CARE, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, num_interrupt_in: NUM_DONT_CARE, - num_bulk_in: NUM_DONT_CARE, - num_bulk_out: NUM_DONT_CARE, + num_bulk_in: 3, + num_bulk_out: 4, num_ports: 1, open: keyspan_open, close: keyspan_close, + write: keyspan_write, + write_room: keyspan_write_room, + //write_bulk_callback: Not used - we define our own herbs + //read_int_callback: keyspan_usa26_read_int_callback, + chars_in_buffer: keyspan_chars_in_buffer, throttle: keyspan_rx_throttle, unthrottle: keyspan_rx_unthrottle, + ioctl: keyspan_ioctl, set_termios: keyspan_set_termios, + break_ctl: keyspan_break_ctl, + startup: keyspan_startup, + shutdown: keyspan_shutdown, }; struct usb_serial_device_type keyspan_usa19_device = { @@ -303,8 +506,8 @@ close: keyspan_close, write: keyspan_write, write_room: keyspan_write_room, - write_bulk_callback: keyspan_write_bulk_callback, - read_int_callback: keyspan_read_bulk_callback, +// write_bulk_callback: keyspan_write_bulk_callback, +// read_int_callback: keyspan_usa28_read_int_callback, chars_in_buffer: keyspan_chars_in_buffer, throttle: keyspan_rx_throttle, unthrottle: keyspan_rx_unthrottle, @@ -320,17 +523,26 @@ name: "Keyspan USA19W", id_table: keyspan_usa19w_ids, needs_interrupt_in: DONT_CARE, - needs_bulk_in: DONT_CARE, - needs_bulk_out: DONT_CARE, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, num_interrupt_in: NUM_DONT_CARE, - num_bulk_in: NUM_DONT_CARE, - num_bulk_out: NUM_DONT_CARE, + num_bulk_in: 3, + num_bulk_out: 4, num_ports: 1, open: keyspan_open, close: keyspan_close, + write: keyspan_write, + write_room: keyspan_write_room, + //write_bulk_callback: Not used - we define our own herbs + //read_int_callback: keyspan_usa26_read_int_callback, + chars_in_buffer: keyspan_chars_in_buffer, throttle: keyspan_rx_throttle, unthrottle: keyspan_rx_unthrottle, + ioctl: keyspan_ioctl, set_termios: keyspan_set_termios, + break_ctl: keyspan_break_ctl, + startup: keyspan_startup, + shutdown: keyspan_shutdown, }; @@ -366,8 +578,8 @@ close: keyspan_close, write: keyspan_write, write_room: keyspan_write_room, - write_bulk_callback: keyspan_write_bulk_callback, - read_int_callback: keyspan_read_bulk_callback, +// write_bulk_callback: keyspan_write_bulk_callback, +// read_int_callback: keyspan_usa26_read_int_callback, chars_in_buffer: keyspan_chars_in_buffer, throttle: keyspan_rx_throttle, unthrottle: keyspan_rx_unthrottle, @@ -377,10 +589,34 @@ startup: keyspan_startup, shutdown: keyspan_shutdown, +}; +struct usb_serial_device_type keyspan_usa49w_device = { + name: "Keyspan USA49W", + id_table: keyspan_usa49w_ids, + needs_interrupt_in: DONT_CARE, + needs_bulk_in: MUST_HAVE, + needs_bulk_out: MUST_HAVE, + num_interrupt_in: NUM_DONT_CARE, + num_bulk_in: 5, + num_bulk_out: 5, + num_ports: 4, + open: keyspan_open, + close: keyspan_close, + write: keyspan_write, + write_room: keyspan_write_room, + //write_bulk_callback: Not used - we define our own herbs + //read_int_callback: keyspan_usa26_read_int_callback, + chars_in_buffer: keyspan_chars_in_buffer, + throttle: keyspan_rx_throttle, + unthrottle: keyspan_rx_unthrottle, + ioctl: keyspan_ioctl, + set_termios: keyspan_set_termios, + break_ctl: keyspan_break_ctl, + startup: keyspan_startup, + shutdown: keyspan_shutdown, }; - #endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.4.0-test11/linux/drivers/usb/serial/keyspan_pda.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/keyspan_pda.c Mon Dec 11 12:39:45 2000 @@ -130,7 +130,7 @@ /* wake up other tty processes */ wake_up_interruptible( &tty->write_wait ); /* For 2.2.16 backport -- wake_up_interruptible( &tty->poll_wait ); */ - + MOD_DEC_USE_COUNT; } static void keyspan_pda_request_unthrottle( struct usb_serial *serial ) @@ -149,7 +149,7 @@ NULL, 0, 2*HZ); - + MOD_DEC_USE_COUNT; } @@ -198,7 +198,9 @@ tty = serial->port[0].tty; priv->tx_throttled = 0; /* queue up a wakeup at scheduler time */ - queue_task( &priv->wakeup_task, &tq_scheduler ); + MOD_INC_USE_COUNT; + if (schedule_task(&priv->wakeup_task) == 0) + MOD_DEC_USE_COUNT; break; default: break; @@ -540,7 +542,9 @@ if (request_unthrottle) { priv->tx_throttled = 1; /* block writers */ - queue_task( &priv->unthrottle_task, &tq_scheduler ); + MOD_INC_USE_COUNT; + if (schedule_task(&priv->unthrottle_task) == 0) + MOD_DEC_USE_COUNT; } spin_unlock_irqrestore (&port->port_lock, flags); @@ -566,8 +570,9 @@ } /* queue up a wakeup at scheduler time */ - queue_task( &priv->wakeup_task, &tq_scheduler ); - + MOD_INC_USE_COUNT; + if (schedule_task(&priv->wakeup_task) == 0) + MOD_DEC_USE_COUNT; } @@ -737,11 +742,11 @@ if (!priv) return (1); /* error */ init_waitqueue_head(&serial->port[0].write_wait); - priv->wakeup_task.next = NULL; + INIT_LIST_HEAD(&priv->wakeup_task.list); priv->wakeup_task.sync = 0; priv->wakeup_task.routine = (void *)keyspan_pda_wakeup_write; priv->wakeup_task.data = (void *)(&serial->port[0]); - priv->unthrottle_task.next = NULL; + INIT_LIST_HEAD(&priv->unthrottle_task.list); priv->unthrottle_task.sync = 0; priv->unthrottle_task.routine = (void *)keyspan_pda_request_unthrottle; priv->unthrottle_task.data = (void *)(serial); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa26msg.h linux/drivers/usb/serial/keyspan_usa26msg.h --- v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa26msg.h Mon Jul 10 14:33:04 2000 +++ linux/drivers/usb/serial/keyspan_usa26msg.h Thu Dec 7 16:13:38 2000 @@ -92,16 +92,8 @@ #ifndef __USA26MSG__ #define __USA26MSG__ -#ifndef __stubs__ -#include "datadefs.h" -#endif -typedef struct txAckMessage -{ - u8 dummy; -} txAckMessage; - -typedef struct portControlMessage +typedef struct keyspan_usa26_portControlMessage { /* there are three types of "commands" sent in the control message: @@ -172,7 +164,7 @@ returnStatus, // BOTH: return current status (even if it hasn't changed) resetDataToggle;// BOTH: reset data toggle state to DATA0 -} portControlMessage; +} keyspan_usa26_portControlMessage; // defines for bits in lcr #define USA_DATABITS_5 0x00 @@ -190,7 +182,7 @@ // all things called "StatusMessage" are sent on the status endpoint -typedef struct portStatusMessage // one for each port +typedef struct keyspan_usa26_portStatusMessage // one for each port { u8 port, // BOTH: 0=first, 1=second, other=see below hskia_cts, // USA26: reports HSKIA pin @@ -203,7 +195,7 @@ _txXoff, // port is in XOFF state (either host or RX XOFF) rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off controlResponse;// 1=a control message has been processed -} portStatusMessage; +} keyspan_usa26_portStatusMessage; // bits in RX data message when STAT byte is included #define RXERROR_OVERRUN 0x02 @@ -211,28 +203,28 @@ #define RXERROR_FRAMING 0x08 #define RXERROR_BREAK 0x10 -typedef struct globalControlMessage +typedef struct keyspan_usa26_globalControlMessage { u8 sendGlobalStatus, // 2=request for two status responses resetStatusToggle, // 1=reset global status toggle resetStatusCount; // a cycling value -} globalControlMessage; +} keyspan_usa26_globalControlMessage; -typedef struct globalStatusMessage +typedef struct keyspan_usa26_globalStatusMessage { u8 port, // 3 sendGlobalStatus, // from request, decremented resetStatusCount; // as in request -} globalStatusMessage; +} keyspan_usa26_globalStatusMessage; -typedef struct globalDebugMessage +typedef struct keyspan_usa26_globalDebugMessage { u8 port, // 2 a, b, c, d; -} globalDebugMessage; +} keyspan_usa26_globalDebugMessage; // ie: the maximum length of an EZUSB endpoint buffer #define MAX_DATA_LEN 64 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa28msg.h linux/drivers/usb/serial/keyspan_usa28msg.h --- v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa28msg.h Tue Jul 18 14:52:22 2000 +++ linux/drivers/usb/serial/keyspan_usa28msg.h Thu Dec 7 16:13:38 2000 @@ -94,16 +94,8 @@ #ifndef __USA28MSG__ #define __USA28MSG__ -/*#ifndef STUBS -#include "datadefs.h" -#endif*/ -typedef struct txAckMessage -{ - u8 dummy; -} txAckMessage; - -typedef struct portControlMessage +typedef struct keyspan_usa28_portControlMessage { /* there are four types of "commands" sent in the control message: @@ -153,9 +145,9 @@ returnStatus, // return current status n times (1 or 2) resetDataToggle;// reset data toggle state to DATA0 -} portControlMessage; +} keyspan_usa28_portControlMessage; -typedef struct portStatusMessage +typedef struct keyspan_usa28_portStatusMessage { u8 port, // 0=first, 1=second, 2=global (see below) cts, @@ -171,32 +163,32 @@ rxBreak, // 1=we're in break state rs232invalid, // 1=no valid signals on rs-232 inputs controlResponse;// 1=a control messages has been processed -} portStatusMessage; +} keyspan_usa28_portStatusMessage; // bit defines in txState #define TX_OFF 0x01 // requested by host txOff command #define TX_XOFF 0x02 // either real, or simulated by host -typedef struct globalControlMessage +typedef struct keyspan_usa28_globalControlMessage { u8 sendGlobalStatus, // 2=request for two status responses resetStatusToggle, // 1=reset global status toggle resetStatusCount; // a cycling value -} globalControlMessage; +} keyspan_usa28_globalControlMessage; -typedef struct globalStatusMessage +typedef struct keyspan_usa28_globalStatusMessage { u8 port, // 3 sendGlobalStatus, // from request, decremented resetStatusCount; // as in request -} globalStatusMessage; +} keyspan_usa28_globalStatusMessage; -typedef struct globalDebugMessage +typedef struct keyspan_usa28_globalDebugMessage { u8 port, // 2 n, // typically a count/status byte b; // typically a data byte -} globalDebugMessage; +} keyspan_usa28_globalDebugMessage; // ie: the maximum length of an EZUSB endpoint buffer #define MAX_DATA_LEN 64 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa49msg.h linux/drivers/usb/serial/keyspan_usa49msg.h --- v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa49msg.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa49msg.h Thu Dec 7 16:13:38 2000 @@ -0,0 +1,255 @@ +/* + usa49msg.h + + Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + This file is available under a BSD-style copyright + + Keyspan USB Async Firmware to run on Anchor EZ-USB + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain this licence text + without modification, this list of conditions, and the following + disclaimer. The following copyright notice must appear immediately at + the beginning of all source files: + + Copyright (c) 1998-2000 InnoSys Incorporated. All Rights Reserved + + This file is available under a BSD-style copyright + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of InnoSys Incorprated may not be used to endorse or promote + products derived from this software without specific prior written + permission. + + THIS SOFTWARE IS PROVIDED BY INNOSYS CORP. ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + + 4th revision: USA49W version + + See usa26msg.h for description of message formats + + Third revision: USA28X version (aka USA26) + + Buffer formats for RX/TX data messages are not defined by + a structure, but are described here: + + USB OUT (host -> USA26, transmit) messages contain a + REQUEST_ACK indicator (set to 0xff to request an ACK at the + completion of transmit; 0x00 otherwise), followed by data: + + RQSTACK DAT DAT DAT ... + + with a total data length of 63. + + USB IN (USA26 -> host, receive) messages contain either a zero + flag (indicating no error in any data bytes): + + 00 DAT DAT DAT ... + + for a total of 63 data bytes, or a non-zero status flag (indicating + that all data bytes will be preceded by status flag): + + STAT DAT STAT DAT STAT DAT ... + + for a total of 32 data bytes. The valid bits in the STAT bytes are: + + OVERRUN 0x02 + PARITY 0x04 + FRAMING 0x08 + BREAK 0x10 + + Notes: + + 1. a "no status" RX data message (first byte zero) can serve as + a "break off" indicator. + 2. a control message specifying disablePort will be answered + with a status message, but no further status will be sent + until a control messages with enablePort is sent + + revision history: + + 1999feb10 add reportHskiaChanges to allow us to ignore them + 1999feb10 add txAckThreshold for fast+loose throughput enhancement + 1999mar30 beef up support for RX error reporting + 1999apr14 add resetDataToggle to control message + 2000jan04 merge with usa17msg.h + 2000mar08 clone from usa26msg.h -> usa49msg.h + 2000mar09 change to support 4 ports + 2000may03 change external clocking to match USA-49W hardware + 2000jun01 add extended BSD-style copyright text +*/ + +#ifndef __USA49MSG__ +#define __USA49MSG__ + + +/* + Host->device messages sent on the global control endpoint: + + portNumber message + ---------- -------------------- + 0,1,2,3 portControlMessage + 0x80 globalControlMessage +*/ + +typedef struct keyspan_usa49_portControlMessage +{ + /* + 0. 0/1/2/3 port control message follows + 0x80 set non-port control message follows + */ + u8 portNumber, + + /* + there are three types of "commands" sent in the control message: + + 1. configuration changes which must be requested by setting + the corresponding "set" flag (and should only be requested + when necessary, to reduce overhead on the USA26): + */ + setClocking, // host requests baud rate be set + baudLo, // host does baud divisor calculation + baudHi, // baudHi is only used for first port (gives lower rates) + prescaler, // specified as N/8; values 8-ff are valid + // must be set any time internal baud rate is set; + txClocking, // 0=internal, 1=external/DSR + rxClocking, // 0=internal, 1=external/DSR + + setLcr, // host requests lcr be set + lcr, // use PARITY, STOPBITS, DATABITS below + + setFlowControl, // host requests flow control be set + ctsFlowControl, // 1=use CTS flow control, 0=don't + xonFlowControl, // 1=use XON/XOFF flow control, 0=don't + xonChar, // specified in current character format + xoffChar, // specified in current character format + + setRts, // host requests RTS output be set + rts, // 1=active, 0=inactive + + setDtr, // host requests DTR output be set + dtr; // 1=on, 0=off + + + /* + 3. configuration data which is simply used as is (no overhead, + but must be specified correctly in every host message). + */ + u8 forwardingLength, // forward when this number of chars available + dsrFlowControl, // 1=use DSR flow control, 0=don't + txAckThreshold, // 0=not allowed, 1=normal, 2-255 deliver ACK faster + loopbackMode; // 0=no loopback, 1=loopback enabled + + /* + 4. commands which are flags only; these are processed in order + (so that, e.g., if both _txOn and _txOff flags are set, the + port ends in a TX_OFF state); any non-zero value is respected + */ + u8 _txOn, // enable transmitting (and continue if there's data) + _txOff, // stop transmitting + txFlush, // toss outbound data + txBreak, // turn on break (cleared by _txOn) + rxOn, // turn on receiver + rxOff, // turn off receiver + rxFlush, // toss inbound data + rxForward, // forward all inbound data, NOW (as if fwdLen==1) + returnStatus, // return current status (even if it hasn't changed) + resetDataToggle,// reset data toggle state to DATA0 + enablePort, // start servicing port (move data, check status) + disablePort; // stop servicing port (does implicit tx/rx flush/off) + +} keyspan_usa49_portControlMessage; + +// defines for bits in lcr +#define USA_DATABITS_5 0x00 +#define USA_DATABITS_6 0x01 +#define USA_DATABITS_7 0x02 +#define USA_DATABITS_8 0x03 +#define STOPBITS_5678_1 0x00 // 1 stop bit for all byte sizes +#define STOPBITS_5_1p5 0x04 // 1.5 stop bits for 5-bit byte +#define STOPBITS_678_2 0x04 // 2 stop bits for 6/7/8-bit byte +#define USA_PARITY_NONE 0x00 +#define USA_PARITY_ODD 0x08 +#define USA_PARITY_EVEN 0x18 +#define PARITY_1 0x28 +#define PARITY_0 0x38 + +typedef struct keyspan_usa49_globalControlMessage +{ + u8 portNumber, // 0x80 + sendGlobalStatus, // 1/2=number of status responses requested + resetStatusToggle, // 1=reset global status toggle + resetStatusCount, // a cycling value + remoteWakeupEnable; // 0x10=P1, 0x20=P2, 0x40=P3, 0x80=P3 +} keyspan_usa49_globalControlMessage; + +/* + Device->host messages send on the global status endpoint + + portNumber message + ---------- -------------------- + 0x00,0x01,0x02,0x03 portStatusMessage + 0x80 globalStatusMessage + 0x81 globalDebugMessage +*/ + +typedef struct keyspan_usa49_portStatusMessage // one for each port +{ + u8 portNumber, // 0,1,2,3 + cts, // reports CTS pin + dcd, // reports DCD pin + dsr, // reports DSR pin + ri, // reports RI pin + _txOff, // transmit has been disabled (by host) + _txXoff, // transmit is in XOFF state (either host or RX XOFF) + rxEnabled, // as configured by rxOn/rxOff 1=on, 0=off + controlResponse,// 1=a control message has been processed + txAck, // ACK (data TX complete) + rs232valid; // RS-232 signal valid +} keyspan_usa49_portStatusMessage; + +// bits in RX data message when STAT byte is included +#define RXERROR_OVERRUN 0x02 +#define RXERROR_PARITY 0x04 +#define RXERROR_FRAMING 0x08 +#define RXERROR_BREAK 0x10 + +typedef struct keyspan_usa49_globalStatusMessage +{ + u8 portNumber, // 0x80=globalStatusMessage + sendGlobalStatus, // from request, decremented + resetStatusCount; // as in request +} keyspan_usa49_globalStatusMessage; + +typedef struct keyspan_usa49_globalDebugMessage +{ + u8 portNumber, // 0x81=globalDebugMessage + n, // typically a count/status byte + b; // typically a data byte +} keyspan_usa49_globalDebugMessage; + +// ie: the maximum length of an EZUSB endpoint buffer +#define MAX_DATA_LEN 64 + +// update status approx. 60 times a second (16.6666 ms) +#define STATUS_UPDATE_INTERVAL 16 + +// status rationing tuning value (each port gets checked each n ms) +#define STATUS_RATION 10 + +#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa49w_fw.h linux/drivers/usb/serial/keyspan_usa49w_fw.h --- v2.4.0-test11/linux/drivers/usb/serial/keyspan_usa49w_fw.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/keyspan_usa49w_fw.h Thu Dec 7 16:13:38 2000 @@ -0,0 +1,457 @@ +/* keyspan_usa49w_fw.h + + Generated from Keyspan firmware image Thu Sep 28 09:13:26 2000 EST + This firmware is for the Keyspan USA-49W Serial Adaptor + + "The firmware contained herein as keyspan_usa49w_fw.h is + Copyright (C) 1999-2000 Keyspan, A division of InnoSys Incorporated + ("Keyspan"), as an unpublished work. This notice does not imply + unrestricted or public access to this firmware which is a trade secret of + Keyspan, and which may not be reproduced, used, sold or transferred to any + third party without Keyspan's prior written consent. All Rights Reserved. + + This firmware may not be modified and may only be used with the Keyspan + USA-49W Serial Adapter. Distribution and/or Modification of the + keyspan.c driver which includes this firmware, in whole or in part, + requires the inclusion of this statement." + +*/ + +static const struct ezusb_hex_record keyspan_usa49w_firmware[] = { +{ 0x0000, 3, {0x02, 0x10, 0x36} }, +{ 0x0003, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} }, +{ 0x0013, 16, {0x01, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} }, +{ 0x0023, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x0033, 3, {0x02, 0x17, 0xf0} }, +{ 0x0036, 12, {0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x0043, 3, {0x02, 0x18, 0x00} }, +{ 0x0046, 16, {0xe4, 0xff, 0x74, 0x40, 0x2f, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xe0, 0xfe, 0xe5, 0x27} }, +{ 0x0056, 16, {0x24, 0x04, 0xfd, 0xe4, 0x35, 0x26, 0xfa, 0xa9, 0x05, 0x7b, 0x01, 0xef, 0x7c, 0x00, 0x29, 0xf9} }, +{ 0x0066, 16, {0xec, 0x3a, 0xfa, 0xee, 0x12, 0x11, 0x90, 0x0f, 0xbf, 0x22, 0xd7, 0xe5, 0x27, 0x24, 0x05, 0xf5} }, +{ 0x0076, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x01, 0x4f, 0x7f, 0x01, 0xe5, 0x27} }, +{ 0x0086, 16, {0x24, 0x08, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x15, 0x3d, 0xe5, 0x27} }, +{ 0x0096, 16, {0x24, 0x06, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x15, 0x6c, 0xe5, 0x27} }, +{ 0x00a6, 16, {0x24, 0x07, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0x12, 0x00, 0x03, 0xe5, 0x27} }, +{ 0x00b6, 16, {0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x30, 0xf0, 0x7d, 0x04, 0x44} }, +{ 0x00c6, 16, {0x20, 0xf0, 0xe5, 0x27, 0x24, 0x09, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x12} }, +{ 0x00d6, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xdf, 0xf0, 0x43} }, +{ 0x00e6, 16, {0x05, 0xc0, 0xe5, 0x27, 0x24, 0x0a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x14} }, +{ 0x00f6, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xdf, 0xf0, 0x43} }, +{ 0x0106, 16, {0x05, 0x0b, 0x80, 0x03, 0x43, 0x05, 0x02, 0x7f, 0x03, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x39} }, +{ 0x0116, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04} }, +{ 0x0126, 16, {0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00} }, +{ 0x0136, 16, {0xf0, 0x90, 0x78, 0x41, 0x74, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0146, 16, {0xf5, 0x83, 0xe0, 0x44, 0x06, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x0b, 0xf5, 0x82, 0xe4} }, +{ 0x0156, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x32, 0xe5, 0x27, 0x24, 0x0c, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0166, 16, {0xf5, 0x83, 0xe0, 0x54, 0x3f, 0xff, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x0176, 16, {0x83, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4} }, +{ 0x0186, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x0d, 0xf5, 0x82, 0xe4} }, +{ 0x0196, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x03, 0x02, 0x02, 0x6a, 0xe5, 0x27, 0x24, 0x17, 0xf5, 0x82} }, +{ 0x01a6, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x01b6, 16, {0x26, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4} }, +{ 0x01c6, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfb, 0xf0, 0xe4, 0xff, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82} }, +{ 0x01d6, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xfd, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x0e, 0xf5, 0x82} }, +{ 0x01e6, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x01f6, 16, {0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4} }, +{ 0x0206, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0216, 16, {0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfc, 0xf0, 0xe5, 0x27, 0x24, 0x0f, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0226, 16, {0xf5, 0x83, 0xe0, 0x60, 0x2f, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x0236, 16, {0xe0, 0x44, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x10, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0246, 16, {0xff, 0x12, 0x14, 0xdd, 0xe5, 0x27, 0x24, 0x11, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0256, 16, {0xff, 0x12, 0x15, 0x0d, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0266, 16, {0xff, 0x12, 0x14, 0xad, 0xe5, 0x27, 0x24, 0x14, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0276, 16, {0x60, 0x44, 0xe5, 0x27, 0x24, 0x15, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11} }, +{ 0x0286, 16, {0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xf0, 0x80} }, +{ 0x0296, 16, {0x0f, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xf0} }, +{ 0x02a6, 16, {0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x02b6, 16, {0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x12, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x02c6, 16, {0x83, 0xe0, 0x60, 0x44, 0xe5, 0x27, 0x24, 0x13, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x02d6, 16, {0x60, 0x11, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x02} }, +{ 0x02e6, 16, {0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54} }, +{ 0x02f6, 16, {0xfd, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0306, 16, {0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x16, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0316, 16, {0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x27, 0x24, 0x35, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x0326, 16, {0xef, 0xf0, 0xe5, 0x27, 0x24, 0x17, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe0} }, +{ 0x0336, 16, {0x11, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x40, 0xf0} }, +{ 0x0346, 16, {0x80, 0x0f, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xbf} }, +{ 0x0356, 16, {0xf0, 0xe5, 0x27, 0x24, 0x18, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x27} }, +{ 0x0366, 16, {0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xef, 0xf0, 0xe5, 0x27, 0x24, 0x19, 0xf5} }, +{ 0x0376, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x11, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4} }, +{ 0x0386, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x10, 0xf0, 0x80, 0x0f, 0xe5, 0x27, 0x24, 0x39, 0xf5, 0x82} }, +{ 0x0396, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5} }, +{ 0x03a6, 16, {0x27, 0x24, 0x39, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x90, 0xc0, 0x00, 0xf0, 0xe5} }, +{ 0x03b6, 16, {0x27, 0x24, 0x1a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x6b, 0xe5, 0x27, 0x24} }, +{ 0x03c6, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} }, +{ 0x03d6, 16, {0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f} }, +{ 0x03e6, 16, {0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x12, 0x00, 0x36, 0xef, 0x54, 0xfe} }, +{ 0x03f6, 16, {0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0406, 16, {0x54, 0xfd, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x2c, 0xf5, 0x82} }, +{ 0x0416, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x27, 0x24, 0x2b, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0426, 16, {0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x27, 0x24, 0x1b, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0436, 16, {0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x0446, 16, {0x83, 0xe0, 0x60, 0x28, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0456, 16, {0x44, 0x02, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24, 0x2b, 0xf5, 0x82} }, +{ 0x0466, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x27, 0x24, 0x1c} }, +{ 0x0476, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82} }, +{ 0x0486, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x2c, 0x90, 0x78, 0x41, 0x74, 0x02, 0xf0, 0xe5, 0x27} }, +{ 0x0496, 16, {0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x04, 0x90, 0xc0, 0x00, 0xf0} }, +{ 0x04a6, 16, {0xe4, 0xff, 0x12, 0x14, 0x0c, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x04b6, 16, {0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x27, 0x24, 0x1d, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x04c6, 16, {0x60, 0x27, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x40} }, +{ 0x04d6, 16, {0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x04e6, 16, {0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x1e, 0xf5, 0x82, 0xe4} }, +{ 0x04f6, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x28, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0506, 16, {0xf5, 0x83, 0xe0, 0x54, 0xfe, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15, 0x3d, 0xe5, 0x27, 0x24} }, +{ 0x0516, 16, {0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5} }, +{ 0x0526, 16, {0x27, 0x24, 0x1f, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e, 0xe5, 0x27, 0x24} }, +{ 0x0536, 16, {0x25, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x27, 0xe5, 0x27, 0x24, 0x32, 0xf5} }, +{ 0x0546, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x01, 0xff, 0xf0, 0xfd, 0xe4, 0xff, 0x12, 0x15} }, +{ 0x0556, 16, {0x3d, 0xe5, 0x27, 0x24, 0x2d, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x28} }, +{ 0x0566, 16, {0x42, 0x25, 0xe5, 0x27, 0x24, 0x20, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x70, 0x0e} }, +{ 0x0576, 16, {0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x18, 0x90, 0x78} }, +{ 0x0586, 16, {0x41, 0x74, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x0596, 16, {0x44, 0x02, 0x90, 0xc0, 0x00, 0xf0, 0xe5, 0x27, 0x24, 0x21, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x05a6, 16, {0x83, 0xe0, 0x60, 0x0f, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x05b6, 16, {0x44, 0x02, 0xf0, 0xe5, 0x27, 0x24, 0x22, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60} }, +{ 0x05c6, 16, {0x1f, 0xe5, 0x27, 0x24, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5} }, +{ 0x05d6, 16, {0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0xe5, 0x28, 0x42, 0x25} }, +{ 0x05e6, 16, {0xe5, 0x27, 0x24, 0x23, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x03, 0x12, 0x17} }, +{ 0x05f6, 16, {0x4e, 0xe5, 0x27, 0x24, 0x24, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x1b, 0xe5} }, +{ 0x0606, 16, {0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x08, 0xf0, 0x90, 0x7f} }, +{ 0x0616, 16, {0x98, 0xe0, 0xff, 0xe5, 0x28, 0xf4, 0xfe, 0xef, 0x5e, 0xf0, 0xe5, 0x27, 0x24, 0x25, 0xf5, 0x82} }, +{ 0x0626, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x60, 0x16, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0636, 14, {0x26, 0xf5, 0x83, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x7f, 0x98, 0xe0, 0x45, 0x28, 0xf0} }, +{ 0x0644, 1, {0x22} }, +{ 0x0645, 16, {0x90, 0x7f, 0xe9, 0xe0, 0x12, 0x11, 0xa2, 0x07, 0x42, 0x00, 0x07, 0xb6, 0x01, 0x08, 0x22, 0x03} }, +{ 0x0655, 16, {0x06, 0x68, 0x06, 0x07, 0x35, 0x08, 0x07, 0x2f, 0x09, 0x07, 0x17, 0x0a, 0x07, 0x26, 0x0b, 0x00} }, +{ 0x0665, 16, {0x00, 0x08, 0x71, 0x90, 0x7f, 0xeb, 0xe0, 0x24, 0xfe, 0x60, 0x19, 0x14, 0x60, 0x77, 0x24, 0x02} }, +{ 0x0675, 16, {0x60, 0x03, 0x02, 0x07, 0x0d, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x00, 0x90, 0x7f, 0xd5} }, +{ 0x0685, 16, {0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xea, 0xe0, 0x04, 0x75, 0x82, 0x17, 0x75, 0x83, 0x19, 0xf0} }, +{ 0x0695, 16, {0x90, 0x7f, 0xea, 0xe0, 0x30, 0xe0, 0x04, 0x7f, 0x03, 0x80, 0x02, 0x7f, 0x02, 0x75, 0x82, 0x82} }, +{ 0x06a5, 16, {0x75, 0x83, 0x19, 0xef, 0xf0, 0x75, 0x82, 0x6d, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x66, 0x75} }, +{ 0x06b5, 16, {0x83, 0x19, 0xf0, 0x75, 0x82, 0x5f, 0x75, 0x83, 0x19, 0xf0, 0x75, 0x82, 0x58, 0x75, 0x83, 0x19} }, +{ 0x06c5, 16, {0xf0, 0x90, 0x7f, 0xea, 0xe0, 0x30, 0xe1, 0x04, 0x7f, 0x64, 0x80, 0x02, 0x7f, 0x32, 0x75, 0x82} }, +{ 0x06d5, 16, {0x1a, 0x75, 0x83, 0x19, 0xef, 0xf0, 0x74, 0x19, 0x90, 0x7f, 0xd4, 0xf0, 0x74, 0x12, 0x90, 0x7f} }, +{ 0x06e5, 16, {0xd5, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xea, 0xe0, 0xff, 0x12, 0x13, 0x54, 0xea, 0x49, 0x60} }, +{ 0x06f5, 16, {0x0d, 0xea, 0x90, 0x7f, 0xd4, 0xf0, 0xe9, 0x90, 0x7f, 0xd5, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f} }, +{ 0x0705, 16, {0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02} }, +{ 0x0715, 16, {0x08, 0x78, 0x90, 0x7f, 0x00, 0xe5, 0x0a, 0xf0, 0x90, 0x7f, 0xb5, 0x74, 0x01, 0xf0, 0x02, 0x08} }, +{ 0x0725, 16, {0x78, 0x90, 0x7f, 0xea, 0xe0, 0xf5, 0x0a, 0x02, 0x08, 0x78, 0x12, 0x0a, 0x6a, 0x02, 0x08, 0x78} }, +{ 0x0735, 16, {0x90, 0x7f, 0x00, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xb5, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xe8} }, +{ 0x0745, 16, {0xe0, 0x24, 0x7f, 0x60, 0x24, 0x14, 0x60, 0x31, 0x24, 0x02, 0x70, 0x5b, 0xa2, 0x00, 0xe4, 0x33} }, +{ 0x0755, 16, {0xff, 0x25, 0xe0, 0xff, 0xa2, 0x06, 0xe4, 0x33, 0x4f, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0} }, +{ 0x0765, 16, {0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0x78, 0xe4, 0x90, 0x7f, 0x00, 0xf0, 0xa3, 0xf0} }, +{ 0x0775, 16, {0x90, 0x7f, 0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80} }, +{ 0x0785, 16, {0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4} }, +{ 0x0795, 16, {0x34, 0x7f, 0xf5, 0x83, 0xe0, 0x54, 0xfd, 0x90, 0x7f, 0x00, 0xf0, 0xe4, 0xa3, 0xf0, 0x90, 0x7f} }, +{ 0x07a5, 16, {0xb5, 0x74, 0x02, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x02, 0x08} }, +{ 0x07b5, 16, {0x78, 0x90, 0x7f, 0xe8, 0xe0, 0x24, 0xfe, 0x60, 0x1d, 0x24, 0x02, 0x60, 0x03, 0x02, 0x08, 0x78} }, +{ 0x07c5, 16, {0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x05, 0xc2, 0x00, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x07d5, 16, {0x44, 0x01, 0xf0, 0x02, 0x08, 0x78, 0x90, 0x7f, 0xea, 0xe0, 0x70, 0x38, 0x90, 0x7f, 0xec, 0xe0} }, +{ 0x07e5, 16, {0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4} }, +{ 0x07f5, 16, {0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0xe4, 0xf0, 0x90, 0x7f, 0xec, 0xe0, 0x54, 0x80, 0xff} }, +{ 0x0805, 16, {0x13, 0x13, 0x13, 0x54, 0x1f, 0xff, 0xe0, 0x54, 0x07, 0x2f, 0x90, 0x7f, 0xd7, 0xf0, 0xe0, 0x44} }, +{ 0x0815, 16, {0x20, 0xf0, 0x80, 0x5f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x56, 0x90, 0x7f, 0xe8} }, +{ 0x0825, 16, {0xe0, 0x24, 0xfe, 0x60, 0x18, 0x24, 0x02, 0x70, 0x4a, 0x90, 0x7f, 0xea, 0xe0, 0xb4, 0x01, 0x04} }, +{ 0x0835, 16, {0xd2, 0x00, 0x80, 0x3f, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x36, 0x90, 0x7f, 0xea} }, +{ 0x0845, 16, {0xe0, 0x70, 0x20, 0x90, 0x7f, 0xec, 0xe0, 0xf4, 0x54, 0x80, 0xff, 0xc4, 0x54, 0x0f, 0xff, 0xe0} }, +{ 0x0855, 16, {0x54, 0x07, 0x2f, 0x25, 0xe0, 0x24, 0xb4, 0xf5, 0x82, 0xe4, 0x34, 0x7f, 0xf5, 0x83, 0x74, 0x01} }, +{ 0x0865, 16, {0xf0, 0x80, 0x10, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x01, 0xf0, 0x80, 0x07, 0x90, 0x7f, 0xb4, 0xe0} }, +{ 0x0875, 10, {0x44, 0x01, 0xf0, 0x90, 0x7f, 0xb4, 0xe0, 0x44, 0x02, 0xf0} }, +{ 0x087f, 1, {0x22} }, +{ 0x0880, 16, {0xe5, 0x23, 0x54, 0x0f, 0x70, 0x03, 0x02, 0x09, 0x5f, 0x12, 0x15, 0x9b, 0xef, 0x20, 0xe1, 0x63} }, +{ 0x0890, 16, {0x12, 0x15, 0xf9, 0xef, 0x14, 0xf5, 0x1a, 0x12, 0x17, 0xc1, 0xef, 0x25, 0x1a, 0xff, 0xe4, 0x33} }, +{ 0x08a0, 16, {0xfe, 0xc3, 0xef, 0x94, 0x80, 0xee, 0x64, 0x80, 0x94, 0x80, 0x50, 0x47, 0x85, 0x27, 0x82, 0x85} }, +{ 0x08b0, 16, {0x26, 0x83, 0xe0, 0xfe, 0xa3, 0xe0, 0xff, 0xf5, 0x82, 0x8e, 0x83, 0xe0, 0x30, 0xe0, 0x11, 0xe5} }, +{ 0x08c0, 16, {0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80, 0xf0, 0x80, 0x0f} }, +{ 0x08d0, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0xf0, 0x85} }, +{ 0x08e0, 16, {0x1a, 0x08, 0xef, 0x24, 0x01, 0xf5, 0x10, 0xe4, 0x3e, 0xf5, 0x0f, 0x12, 0x13, 0xd6, 0xe4, 0xff} }, +{ 0x08f0, 16, {0x12, 0x14, 0x0c, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30} }, +{ 0x0900, 16, {0xe7, 0x5d, 0x12, 0x17, 0xc1, 0xe5, 0x27, 0x24, 0x3b, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x0910, 16, {0xe0, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x48, 0xe5, 0x27, 0x24, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0920, 16, {0xf5, 0x83, 0x74, 0x01, 0xf0, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x0930, 16, {0xe0, 0x54, 0x7f, 0xf0, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4} }, +{ 0x0940, 16, {0xf0, 0xe5, 0x28, 0x42, 0x25, 0x90, 0x7f, 0xc2, 0xe0, 0x30, 0xe1, 0x10, 0xe5, 0x27, 0x24, 0x26} }, +{ 0x0950, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xf5, 0x09, 0x80, 0x03, 0x12, 0x12, 0x3d, 0x12} }, +{ 0x0960, 16, {0x15, 0xca, 0xef, 0x30, 0xe1, 0x03, 0x02, 0x0a, 0x69, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4} }, +{ 0x0970, 16, {0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x80, 0xf0, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0980, 16, {0x26, 0xf5, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfe, 0x12, 0x17, 0xcd, 0xee, 0x4f, 0xd0, 0x82} }, +{ 0x0990, 16, {0xd0, 0x83, 0xf0, 0x12, 0x16, 0xd1, 0x8f, 0x1a, 0xe5, 0x27, 0x24, 0x35, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x09a0, 16, {0x26, 0xf5, 0x83, 0xe0, 0xfe, 0xef, 0xc3, 0x9e, 0x50, 0x28, 0x12, 0x17, 0xa9, 0xef, 0x30, 0xe0} }, +{ 0x09b0, 16, {0x21, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x20, 0xe7, 0x12} }, +{ 0x09c0, 16, {0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x20, 0xe1, 0x03, 0x02} }, +{ 0x09d0, 16, {0x0a, 0x69, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0xfd} }, +{ 0x09e0, 16, {0xf0, 0xe5, 0x1a, 0x70, 0x0e, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x09f0, 16, {0xe4, 0xf0, 0x22, 0xe5, 0x27, 0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff} }, +{ 0x0a00, 16, {0x30, 0xe7, 0x29, 0xe5, 0x1a, 0xd3, 0x94, 0x20, 0x40, 0x03, 0x75, 0x1a, 0x20, 0x85, 0x1a, 0x08} }, +{ 0x0a10, 16, {0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0xe0, 0xfc, 0xa3, 0xe0, 0x8c, 0x0f, 0xf5, 0x10} }, +{ 0x0a20, 16, {0x12, 0x13, 0x06, 0xe5, 0x1a, 0x25, 0xe0, 0xff, 0x12, 0x14, 0x42, 0x22, 0xe5, 0x1a, 0xd3, 0x94} }, +{ 0x0a30, 16, {0x3f, 0x40, 0x03, 0x75, 0x1a, 0x3f, 0x85, 0x1a, 0x08, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3} }, +{ 0x0a40, 16, {0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0xf5, 0x82, 0x8e, 0x83, 0xe4, 0xf0, 0x85, 0x27, 0x82, 0x85, 0x26} }, +{ 0x0a50, 16, {0x83, 0xa3, 0xa3, 0xe0, 0xfe, 0xa3, 0xe0, 0x24, 0x01, 0xf5, 0x10, 0xe4, 0x3e, 0xf5, 0x0f, 0x12} }, +{ 0x0a60, 9, {0x13, 0x95, 0xe5, 0x1a, 0x04, 0xff, 0x12, 0x14, 0x42} }, +{ 0x0a69, 1, {0x22} }, +{ 0x0a6a, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xf0, 0xf0, 0x90, 0x7f, 0x96, 0xf0, 0xe4} }, +{ 0x0a7a, 16, {0x90, 0x7f, 0x94, 0xf0, 0x90, 0x78, 0x4a, 0x04, 0xf0, 0xf5, 0x8e, 0x90, 0x7f, 0x95, 0x74, 0xc0} }, +{ 0x0a8a, 16, {0xf0, 0x90, 0x7f, 0x9e, 0x74, 0x3f, 0xf0, 0x90, 0x7f, 0x98, 0x74, 0x1f, 0xf0, 0x90, 0x78, 0x43} }, +{ 0x0a9a, 16, {0x74, 0xff, 0xf0, 0xe4, 0x90, 0x78, 0x41, 0xf0, 0x90, 0x7f, 0xdf, 0x74, 0x9f, 0xf0, 0x90, 0x7f} }, +{ 0x0aaa, 16, {0xde, 0xf0, 0x90, 0x7f, 0x92, 0xe0, 0x44, 0x02, 0xf0, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b} }, +{ 0x0aba, 16, {0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x12, 0x0e, 0xb3, 0x7e} }, +{ 0x0aca, 16, {0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75} }, +{ 0x0ada, 16, {0x28, 0x01, 0xe5, 0x27, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0, 0x7e} }, +{ 0x0aea, 16, {0x7e, 0x7f, 0x40, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x40, 0xf0} }, +{ 0x0afa, 16, {0x7e, 0x7e, 0x7f, 0x80, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0x74, 0x7e, 0xf0, 0xa3} }, +{ 0x0b0a, 16, {0x74, 0x80, 0xf0, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x00, 0x90, 0x7f, 0x96} }, +{ 0x0b1a, 16, {0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x12, 0x0e, 0xb3, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c} }, +{ 0x0b2a, 16, {0x75, 0x27, 0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0xe5, 0x27, 0x24, 0x26} }, +{ 0x0b3a, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x7e, 0x7d, 0x7f, 0xc0, 0x85, 0x27} }, +{ 0x0b4a, 16, {0x82, 0x85, 0x26, 0x83, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0xc0, 0xf0, 0x7e, 0x7e, 0x7f, 0x00, 0x85} }, +{ 0x0b5a, 16, {0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0x74, 0x7e, 0xf0, 0xa3, 0x74, 0x00, 0xf0, 0x7e, 0x7c} }, +{ 0x0b6a, 16, {0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28} }, +{ 0x0b7a, 16, {0x04, 0x12, 0x0e, 0xb3, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f} }, +{ 0x0b8a, 16, {0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28, 0x04, 0xe5, 0x27, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0b9a, 16, {0xf5, 0x83, 0x74, 0x02, 0xf0, 0x7e, 0x7d, 0x7f, 0x40, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0x74} }, +{ 0x0baa, 16, {0x7d, 0xf0, 0xa3, 0x74, 0x40, 0xf0, 0x7e, 0x7d, 0x7f, 0x80, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83} }, +{ 0x0bba, 16, {0xa3, 0xa3, 0x74, 0x7d, 0xf0, 0xa3, 0x74, 0x80, 0xf0, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c} }, +{ 0x0bca, 16, {0x75, 0x27, 0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0x12, 0x0e, 0xb3, 0x7e} }, +{ 0x0bda, 16, {0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f, 0xf0, 0x75} }, +{ 0x0bea, 16, {0x28, 0x08, 0xe5, 0x27, 0x24, 0x26, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x03, 0xf0} }, +{ 0x0bfa, 16, {0x7e, 0x7c, 0x7f, 0xc0, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0x74, 0x7c, 0xf0, 0xa3, 0x74, 0xc0} }, +{ 0x0c0a, 16, {0xf0, 0x7e, 0x7d, 0x7f, 0x00, 0x85, 0x27, 0x82, 0x85, 0x26, 0x83, 0xa3, 0xa3, 0x74, 0x7d, 0xf0} }, +{ 0x0c1a, 7, {0xa3, 0x74, 0x00, 0xf0, 0xd2, 0x02, 0x22} }, +{ 0x0c21, 16, {0xe5, 0x22, 0x04, 0x54, 0x03, 0xf5, 0x22, 0x14, 0x60, 0x1f, 0x14, 0x60, 0x31, 0x14, 0x60, 0x43} }, +{ 0x0c31, 16, {0x24, 0x03, 0x70, 0x52, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f} }, +{ 0x0c41, 16, {0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x80, 0x3d, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c} }, +{ 0x0c51, 16, {0x75, 0x27, 0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x80, 0x28, 0x7e, 0x7c} }, +{ 0x0c61, 16, {0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28} }, +{ 0x0c71, 16, {0x04, 0x80, 0x13, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96} }, +{ 0x0c81, 16, {0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0xe5, 0x15, 0x55, 0x28, 0x70, 0x03, 0x02, 0x0d, 0xbf, 0xe5} }, +{ 0x0c91, 16, {0x28, 0xf4, 0xff, 0x52, 0x15, 0xe5, 0x0b, 0x54, 0x7f, 0xfe, 0x70, 0x0f, 0xe5, 0x0d, 0x55, 0x28} }, +{ 0x0ca1, 16, {0x60, 0x24, 0x90, 0x7f, 0x98, 0xe0, 0x45, 0x28, 0xf0, 0x80, 0x1b, 0xbe, 0x20, 0x18, 0xe5, 0x27} }, +{ 0x0cb1, 16, {0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe3, 0x09, 0xe4, 0xf5, 0x0d} }, +{ 0x0cc1, 16, {0x90, 0x7f, 0x98, 0xe0, 0x5f, 0xf0, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x0cd1, 16, {0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe5, 0x27, 0x24, 0x34, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0ce1, 16, {0xf5, 0x83, 0xe0, 0x60, 0x03, 0xe0, 0x14, 0xf0, 0xe0, 0x60, 0x03, 0x02, 0x0d, 0xbf, 0x74, 0x0a} }, +{ 0x0cf1, 16, {0xf0, 0x12, 0x00, 0x36, 0xef, 0x54, 0x01, 0xff, 0xf5, 0x1a, 0xe5, 0x27, 0x24, 0x2c, 0xf5, 0x82} }, +{ 0x0d01, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x07, 0xe5, 0x1a, 0xf0, 0xe5, 0x28, 0x42, 0x25} }, +{ 0x0d11, 16, {0x12, 0x17, 0xd9, 0x8f, 0x1a, 0xe5, 0x27, 0x24, 0x27, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83} }, +{ 0x0d21, 16, {0xe0, 0xff, 0xe5, 0x1a, 0x54, 0x10, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, 0xe5, 0x28, 0x42, 0x25} }, +{ 0x0d31, 16, {0xe5, 0x27, 0x24, 0x28, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x1a, 0x54} }, +{ 0x0d41, 16, {0x80, 0xfe, 0x6f, 0x60, 0x06, 0xee, 0xf0, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x27, 0x24, 0x29, 0xf5} }, +{ 0x0d51, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0xff, 0xe5, 0x1a, 0x54, 0x20, 0xfe, 0x6f, 0x60, 0x15} }, +{ 0x0d61, 16, {0xee, 0xf0, 0xe5, 0x27, 0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe4} }, +{ 0x0d71, 16, {0x04, 0xe5, 0x28, 0x42, 0x25, 0xe5, 0x24, 0x55, 0x28, 0xff, 0xf5, 0x1a, 0xe5, 0x27, 0x24, 0x2a} }, +{ 0x0d81, 16, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x16, 0xe5, 0x1a, 0xf0, 0xe5, 0x27} }, +{ 0x0d91, 16, {0x24, 0x31, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x30, 0xe5, 0x04, 0xe5, 0x28, 0x42} }, +{ 0x0da1, 16, {0x25, 0xe5, 0x29, 0x55, 0x28, 0xff, 0xf5, 0x1a, 0xe5, 0x27, 0x24, 0x30, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x0db1, 14, {0x26, 0xf5, 0x83, 0xe0, 0x6f, 0x60, 0x07, 0xe5, 0x1a, 0xf0, 0xe5, 0x28, 0x42, 0x25} }, +{ 0x0dbf, 1, {0x22} }, +{ 0x0dc0, 16, {0xe5, 0x09, 0x14, 0x60, 0x2a, 0x14, 0x60, 0x41, 0x14, 0x60, 0x58, 0x14, 0x60, 0x6f, 0x24, 0x04} }, +{ 0x0dd0, 16, {0x60, 0x03, 0x02, 0x0e, 0x77, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90} }, +{ 0x0de0, 16, {0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x12, 0x12, 0x3d, 0x75, 0x09, 0x01, 0x22, 0x7e} }, +{ 0x0df0, 16, {0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75} }, +{ 0x0e00, 16, {0x28, 0x02, 0x12, 0x12, 0x3d, 0x75, 0x09, 0x02, 0x22, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c} }, +{ 0x0e10, 16, {0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28, 0x04, 0x12, 0x12, 0x3d, 0x75} }, +{ 0x0e20, 16, {0x09, 0x03, 0x22, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96} }, +{ 0x0e30, 16, {0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0x12, 0x12, 0x3d, 0x75, 0x09, 0x04, 0x22, 0x30, 0x04, 0x33} }, +{ 0x0e40, 16, {0xc2, 0x04, 0x53, 0x25, 0xdf, 0xe4, 0xf5, 0x1a, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x11, 0x25, 0x1a} }, +{ 0x0e50, 16, {0xf9, 0xee, 0x34, 0x00, 0xfa, 0x12, 0x11, 0x4a, 0xff, 0x74, 0x80, 0x25, 0x1a, 0xf5, 0x82, 0xe4} }, +{ 0x0e60, 16, {0x34, 0x7b, 0xf5, 0x83, 0xef, 0xf0, 0x05, 0x1a, 0xe5, 0x1a, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3} }, +{ 0x0e70, 16, {0x74, 0x03, 0xf0, 0x75, 0x09, 0x05, 0x22, 0xe5, 0x17, 0x60, 0x34, 0xd5, 0x17, 0x03, 0x53, 0x25} }, +{ 0x0e80, 16, {0xef, 0xe4, 0xf5, 0x1a, 0x7e, 0x00, 0x7b, 0x00, 0x74, 0x16, 0x25, 0x1a, 0xf9, 0xee, 0x34, 0x00} }, +{ 0x0e90, 16, {0xfa, 0x12, 0x11, 0x4a, 0xff, 0x74, 0x80, 0x25, 0x1a, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83} }, +{ 0x0ea0, 16, {0xef, 0xf0, 0x05, 0x1a, 0xe5, 0x1a, 0xb4, 0x03, 0xdb, 0x90, 0x7f, 0xc3, 0x74, 0x03, 0xf0, 0xe4} }, +{ 0x0eb0, 2, {0xf5, 0x09} }, +{ 0x0eb2, 1, {0x22} }, +{ 0x0eb3, 16, {0xe4, 0xf5, 0x19, 0x7e, 0x00, 0x7b, 0x01, 0xe5, 0x27, 0x25, 0x19, 0xf9, 0xee, 0x35, 0x26, 0xfa} }, +{ 0x0ec3, 16, {0xe4, 0x12, 0x11, 0x90, 0x05, 0x19, 0xe5, 0x19, 0xb4, 0x3c, 0xe8, 0xe5, 0x27, 0x24, 0x35, 0xf5} }, +{ 0x0ed3, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x01, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5} }, +{ 0x0ee3, 16, {0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00} }, +{ 0x0ef3, 16, {0xf0, 0x7f, 0x0c, 0xe4, 0xfd, 0x12, 0x15, 0x3d, 0x7f, 0x10, 0xe5, 0x27, 0x24, 0x33, 0xf5, 0x82} }, +{ 0x0f03, 16, {0xe4, 0x35, 0x26, 0xf5, 0x83, 0xef, 0xf0, 0x12, 0x14, 0xad, 0x90, 0x78, 0x41, 0x74, 0x02, 0xf0} }, +{ 0x0f13, 16, {0x7f, 0x01, 0xe5, 0x27, 0x24, 0x36, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xef, 0xf0, 0x44} }, +{ 0x0f23, 16, {0x06, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0xe5, 0x27, 0x24, 0x39, 0xf5} }, +{ 0x0f33, 16, {0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0x74, 0x80, 0xf0, 0x90, 0xc0, 0x00, 0xf0, 0x0f, 0xe4, 0xfd} }, +{ 0x0f43, 16, {0x12, 0x15, 0x3d, 0xe4, 0xff, 0x7e, 0xa3, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26} }, +{ 0x0f53, 16, {0xf5, 0x83, 0xee, 0xf0, 0xfd, 0x12, 0x15, 0x3d, 0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x90, 0xc0} }, +{ 0x0f63, 16, {0x00, 0xe4, 0xf0, 0x7f, 0x05, 0x7d, 0x7f, 0x12, 0x15, 0x3d, 0x7f, 0x01, 0x12, 0x14, 0x78, 0x7f} }, +{ 0x0f73, 6, {0x03, 0x7d, 0x07, 0x12, 0x15, 0x3d} }, +{ 0x0f79, 1, {0x22} }, +{ 0x0f7a, 16, {0x53, 0x25, 0x3f, 0x90, 0x7b, 0xf1, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7b, 0x7f, 0xc0, 0x75, 0x26} }, +{ 0x0f8a, 16, {0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75, 0x28, 0x01, 0x12, 0x08, 0x80} }, +{ 0x0f9a, 16, {0x90, 0x7c, 0x31, 0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27} }, +{ 0x0faa, 16, {0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x12, 0x08, 0x80, 0x90, 0x7c, 0x71} }, +{ 0x0fba, 16, {0xe0, 0x30, 0xe3, 0x16, 0x7e, 0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f} }, +{ 0x0fca, 16, {0x96, 0x74, 0xbf, 0xf0, 0x75, 0x28, 0x04, 0x12, 0x08, 0x80, 0x90, 0x7c, 0xb1, 0xe0, 0x30, 0xe3} }, +{ 0x0fda, 16, {0x16, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f} }, +{ 0x0fea, 16, {0xf0, 0x75, 0x28, 0x08, 0x12, 0x08, 0x80, 0x05, 0x23, 0xe5, 0x23, 0x54, 0x0f, 0xf5, 0x19, 0x70} }, +{ 0x0ffa, 16, {0x1f, 0x90, 0x78, 0x41, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x7f, 0x99, 0xe0, 0xf5, 0x29, 0x90, 0x78} }, +{ 0x100a, 16, {0x41, 0xe0, 0x44, 0x08, 0xf0, 0x90, 0x7f, 0x99, 0xe0, 0xf4, 0xf5, 0x24, 0x12, 0x10, 0xc2, 0x22} }, +{ 0x101a, 16, {0xe5, 0x19, 0xb4, 0x01, 0x04, 0x12, 0x0c, 0x21, 0x22, 0x90, 0x7f, 0xc2, 0xe0, 0x20, 0xe1, 0x08} }, +{ 0x102a, 11, {0xe5, 0x25, 0x60, 0x04, 0x12, 0x0d, 0xc0, 0x22, 0x12, 0x0c, 0x21} }, +{ 0x1035, 1, {0x22} }, +{ 0x1036, 12, {0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0x29, 0x02, 0x10, 0x7d} }, +{ 0x1042, 16, {0x02, 0x11, 0xc8, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0x40, 0x03, 0xf6, 0x80, 0x01, 0xf2} }, +{ 0x1052, 16, {0x08, 0xdf, 0xf4, 0x80, 0x29, 0xe4, 0x93, 0xa3, 0xf8, 0x54, 0x07, 0x24, 0x0c, 0xc8, 0xc3, 0x33} }, +{ 0x1062, 16, {0xc4, 0x54, 0x0f, 0x44, 0x20, 0xc8, 0x83, 0x40, 0x04, 0xf4, 0x56, 0x80, 0x01, 0x46, 0xf6, 0xdf} }, +{ 0x1072, 16, {0xe4, 0x80, 0x0b, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x90, 0x17, 0x67, 0xe4, 0x7e} }, +{ 0x1082, 16, {0x01, 0x93, 0x60, 0xbc, 0xa3, 0xff, 0x54, 0x3f, 0x30, 0xe5, 0x09, 0x54, 0x1f, 0xfe, 0xe4, 0x93} }, +{ 0x1092, 16, {0xa3, 0x60, 0x01, 0x0e, 0xcf, 0x54, 0xc0, 0x25, 0xe0, 0x60, 0xa8, 0x40, 0xb8, 0xe4, 0x93, 0xa3} }, +{ 0x10a2, 16, {0xfa, 0xe4, 0x93, 0xa3, 0xf8, 0xe4, 0x93, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca} }, +{ 0x10b2, 16, {0xf0, 0xa3, 0xc8, 0xc5, 0x82, 0xc8, 0xca, 0xc5, 0x83, 0xca, 0xdf, 0xe9, 0xde, 0xe7, 0x80, 0xbe} }, +{ 0x10c2, 16, {0x90, 0x7f, 0xd2, 0xe0, 0x30, 0xe1, 0x03, 0x02, 0x11, 0x49, 0x90, 0x7b, 0x40, 0xe0, 0x14, 0x60} }, +{ 0x10d2, 16, {0x26, 0x14, 0x60, 0x3b, 0x14, 0x60, 0x50, 0x24, 0x83, 0x60, 0x64, 0x24, 0x80, 0x70, 0x63, 0x7e} }, +{ 0x10e2, 16, {0x7b, 0x7f, 0xc0, 0x75, 0x26, 0x7b, 0x75, 0x27, 0xc0, 0x90, 0x7f, 0x96, 0x74, 0xef, 0xf0, 0x75} }, +{ 0x10f2, 16, {0x28, 0x01, 0x12, 0x00, 0x46, 0x80, 0x4b, 0x7e, 0x7c, 0x7f, 0x00, 0x75, 0x26, 0x7c, 0x75, 0x27} }, +{ 0x1102, 16, {0x00, 0x90, 0x7f, 0x96, 0x74, 0xdf, 0xf0, 0x75, 0x28, 0x02, 0x12, 0x00, 0x46, 0x80, 0x33, 0x7e} }, +{ 0x1112, 16, {0x7c, 0x7f, 0x40, 0x75, 0x26, 0x7c, 0x75, 0x27, 0x40, 0x90, 0x7f, 0x96, 0x74, 0xbf, 0xf0, 0x75} }, +{ 0x1122, 16, {0x28, 0x04, 0x12, 0x00, 0x46, 0x80, 0x1b, 0x7e, 0x7c, 0x7f, 0x80, 0x75, 0x26, 0x7c, 0x75, 0x27} }, +{ 0x1132, 16, {0x80, 0x90, 0x7f, 0x96, 0x74, 0x7f, 0xf0, 0x75, 0x28, 0x08, 0x12, 0x00, 0x46, 0x80, 0x03, 0x12} }, +{ 0x1142, 8, {0x16, 0x56, 0xe4, 0x90, 0x7f, 0xd3, 0xf0, 0x22} }, +{ 0x114a, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xe0, 0x22, 0x50, 0x02, 0xe7, 0x22, 0xbb, 0xfe, 0x02} }, +{ 0x115a, 9, {0xe3, 0x22, 0x89, 0x82, 0x8a, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x1163, 16, {0xbb, 0x01, 0x0c, 0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe0, 0x22, 0x50} }, +{ 0x1173, 16, {0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe6, 0x22, 0xbb, 0xfe, 0x06, 0xe9, 0x25, 0x82, 0xf8, 0xe2, 0x22} }, +{ 0x1183, 13, {0xe5, 0x82, 0x29, 0xf5, 0x82, 0xe5, 0x83, 0x3a, 0xf5, 0x83, 0xe4, 0x93, 0x22} }, +{ 0x1190, 16, {0xbb, 0x01, 0x06, 0x89, 0x82, 0x8a, 0x83, 0xf0, 0x22, 0x50, 0x02, 0xf7, 0x22, 0xbb, 0xfe, 0x01} }, +{ 0x11a0, 2, {0xf3, 0x22} }, +{ 0x11a2, 16, {0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, 0xa3} }, +{ 0x11b2, 16, {0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, 0x60} }, +{ 0x11c2, 6, {0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf} }, +{ 0x11c8, 16, {0x90, 0x7f, 0xae, 0xe0, 0xff, 0xd3, 0x92, 0x00, 0xe4, 0x33, 0xfe, 0xef, 0x4e, 0xf0, 0xd2, 0xe8} }, +{ 0x11d8, 16, {0x43, 0xd8, 0x20, 0x90, 0x7f, 0xde, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xdf, 0xf0, 0x90, 0x7f, 0xab} }, +{ 0x11e8, 16, {0x74, 0xff, 0xf0, 0x90, 0x7f, 0xa9, 0xf0, 0x90, 0x7f, 0xaa, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f} }, +{ 0x11f8, 16, {0xaf, 0x74, 0x01, 0xf0, 0x90, 0x7f, 0xae, 0x74, 0x0d, 0xf0, 0xd2, 0xaf, 0xd2, 0x09, 0x12, 0x17} }, +{ 0x1208, 16, {0x13, 0xc2, 0x01, 0xe4, 0xf5, 0x0e, 0xf5, 0x14, 0xc2, 0x07, 0xc2, 0x02, 0x90, 0x7f, 0xd8, 0xe0} }, +{ 0x1218, 16, {0x65, 0x0b, 0x60, 0x06, 0x75, 0x15, 0x0f, 0xe0, 0xf5, 0x0b, 0x30, 0x02, 0x03, 0x12, 0x0f, 0x7a} }, +{ 0x1228, 16, {0x30, 0x01, 0x07, 0xc2, 0x01, 0x12, 0x06, 0x45, 0x80, 0xe2, 0x30, 0x08, 0xdf, 0xc2, 0x08, 0x12} }, +{ 0x1238, 5, {0x17, 0x95, 0x80, 0xd8, 0x22} }, +{ 0x123d, 16, {0xe5, 0x25, 0x55, 0x28, 0x60, 0x6a, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x124d, 16, {0x83, 0xe0, 0x70, 0x5c, 0xe5, 0x28, 0xf4, 0x52, 0x25, 0xe5, 0x27, 0x24, 0x26, 0xff, 0xe4, 0x35} }, +{ 0x125d, 16, {0x26, 0xfe, 0xe4, 0xfd, 0x0f, 0xef, 0xaa, 0x06, 0x70, 0x01, 0x0e, 0x14, 0xf5, 0x82, 0x8a, 0x83} }, +{ 0x126d, 16, {0xe0, 0xfc, 0x74, 0x80, 0x2d, 0xf5, 0x82, 0xe4, 0x34, 0x7b, 0xf5, 0x83, 0xec, 0xf0, 0x0d, 0xbd} }, +{ 0x127d, 16, {0x0b, 0xe2, 0x90, 0x7f, 0xc3, 0x74, 0x0b, 0xf0, 0xe5, 0x27, 0x24, 0x3a, 0xf5, 0x82, 0xe4, 0x35} }, +{ 0x128d, 16, {0x26, 0xf5, 0x83, 0x74, 0x10, 0xf0, 0xe5, 0x27, 0x24, 0x2e, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x129d, 16, {0x83, 0xe4, 0xf0, 0xe5, 0x27, 0x24, 0x2f, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe4, 0xf0} }, +{ 0x12ad, 1, {0x22} }, +{ 0x12ae, 16, {0xe4, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xf0, 0xf0, 0x90, 0x7f, 0x96, 0xf0, 0xe4} }, +{ 0x12be, 16, {0x90, 0x78, 0x4a, 0xf0, 0x90, 0x7f, 0x94, 0xf0, 0x90, 0x7f, 0x9d, 0x74, 0xff, 0xf0, 0xe4, 0x90} }, +{ 0x12ce, 16, {0x7f, 0x97, 0xf0, 0xe5, 0x0c, 0x54, 0xf0, 0x44, 0x08, 0x90, 0x78, 0x41, 0xf0, 0xe4, 0x90, 0x7f} }, +{ 0x12de, 16, {0x98, 0xf0, 0x90, 0x7f, 0x95, 0xf0, 0x90, 0x7f, 0x9e, 0x74, 0xff, 0xf0, 0xe4, 0x90, 0x7f, 0x98} }, +{ 0x12ee, 16, {0xf0, 0x90, 0x7f, 0x93, 0xf0, 0x90, 0x7f, 0x9c, 0x74, 0xf0, 0xf0, 0xe4, 0x90, 0x7f, 0x96, 0xf0} }, +{ 0x12fe, 8, {0x90, 0x7f, 0x92, 0xe0, 0x54, 0xfd, 0xf0, 0x22} }, +{ 0x1306, 16, {0x8f, 0x1b, 0x05, 0x10, 0xe5, 0x10, 0xae, 0x0f, 0x70, 0x02, 0x05, 0x0f, 0x14, 0xf5, 0x82, 0x8e} }, +{ 0x1316, 16, {0x83, 0xe5, 0x1b, 0xf0, 0x12, 0x17, 0xe5, 0x05, 0x10, 0xe5, 0x10, 0xac, 0x0f, 0x70, 0x02, 0x05} }, +{ 0x1326, 16, {0x0f, 0x14, 0xf5, 0x82, 0x8c, 0x83, 0xef, 0xf0, 0x15, 0x08, 0xe5, 0x08, 0x60, 0x1f, 0xe5, 0x27} }, +{ 0x1336, 16, {0x24, 0x38, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xc0, 0x83, 0xc0, 0x82, 0xe0, 0xfe, 0x12} }, +{ 0x1346, 14, {0x17, 0xcd, 0x8f, 0x1b, 0xee, 0x4f, 0xd0, 0x82, 0xd0, 0x83, 0xf0, 0x80, 0xb5, 0x22} }, +{ 0x1354, 2, {0x8f, 0x19} }, +{ 0x1356, 16, {0xe4, 0xf5, 0x1a, 0x75, 0x1b, 0xff, 0x75, 0x1c, 0x19, 0x75, 0x1d, 0x86, 0xab, 0x1b, 0xaa, 0x1c} }, +{ 0x1366, 16, {0xa9, 0x1d, 0x90, 0x00, 0x01, 0x12, 0x11, 0x63, 0xb4, 0x03, 0x1d, 0xaf, 0x1a, 0x05, 0x1a, 0xef} }, +{ 0x1376, 16, {0xb5, 0x19, 0x01, 0x22, 0x12, 0x11, 0x4a, 0x7e, 0x00, 0x29, 0xff, 0xee, 0x3a, 0xa9, 0x07, 0x75} }, +{ 0x1386, 14, {0x1b, 0xff, 0xf5, 0x1c, 0x89, 0x1d, 0x80, 0xd4, 0x7b, 0x00, 0x7a, 0x00, 0x79, 0x00} }, +{ 0x1394, 1, {0x22} }, +{ 0x1395, 16, {0xe4, 0x90, 0x78, 0x41, 0xf0, 0x90, 0x78, 0x4f, 0x74, 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x50, 0xf0} }, +{ 0x13a5, 16, {0xe5, 0x0f, 0x90, 0x78, 0x51, 0xf0, 0xae, 0x0f, 0xe5, 0x10, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78} }, +{ 0x13b5, 16, {0x54, 0xe5, 0x08, 0xf0, 0x90, 0x78, 0x57, 0x74, 0x04, 0xf0, 0x90, 0x7f, 0xe2, 0xe0, 0x44, 0x10} }, +{ 0x13c5, 16, {0xf0, 0xe0, 0x54, 0xf7, 0xf0, 0xe4, 0x90, 0x78, 0x55, 0xf0, 0x90, 0x78, 0x55, 0xe0, 0x60, 0xfa} }, +{ 0x13d5, 1, {0x22} }, +{ 0x13d6, 16, {0xe4, 0x90, 0x78, 0x41, 0xf0, 0xe5, 0x0f, 0x90, 0x78, 0x4f, 0xf0, 0xae, 0x0f, 0xe5, 0x10, 0x90} }, +{ 0x13e6, 16, {0x78, 0x50, 0xf0, 0x90, 0x78, 0x51, 0x74, 0xc0, 0xf0, 0xe4, 0x90, 0x78, 0x52, 0xf0, 0x90, 0x78} }, +{ 0x13f6, 16, {0x54, 0xe5, 0x08, 0xf0, 0x90, 0x78, 0x57, 0x74, 0x04, 0xf0, 0xe4, 0x90, 0x78, 0x55, 0xf0, 0x90} }, +{ 0x1406, 6, {0x78, 0x55, 0xe0, 0x60, 0xfa, 0x22} }, +{ 0x140c, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14} }, +{ 0x141c, 16, {0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f} }, +{ 0x142c, 16, {0xc9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xcb, 0xef, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xcd, 0xef} }, +{ 0x143c, 6, {0xf0, 0xe5, 0x28, 0x42, 0x0d, 0x22} }, +{ 0x1442, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0f, 0x14} }, +{ 0x1452, 16, {0x60, 0x13, 0x14, 0x60, 0x17, 0x80, 0x00, 0x90, 0x7f, 0xb7, 0xef, 0xf0, 0x80, 0x13, 0x90, 0x7f} }, +{ 0x1462, 16, {0xb9, 0xef, 0xf0, 0x80, 0x0c, 0x90, 0x7f, 0xbb, 0xef, 0xf0, 0x80, 0x05, 0x90, 0x7f, 0xbd, 0xef} }, +{ 0x1472, 6, {0xf0, 0xe5, 0x28, 0x42, 0x0d, 0x22} }, +{ 0x1478, 16, {0xae, 0x07, 0xe4, 0xff, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0} }, +{ 0x1488, 16, {0x54, 0x7f, 0xfd, 0x12, 0x15, 0x3d, 0x90, 0x78, 0x41, 0x74, 0x01, 0xf0, 0x90, 0xc0, 0x00, 0xee} }, +{ 0x1498, 16, {0xf0, 0xe4, 0xe5, 0x27, 0x24, 0x32, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x44, 0x80} }, +{ 0x14a8, 5, {0xfd, 0x12, 0x15, 0x3d, 0x22} }, +{ 0x14ad, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} }, +{ 0x14bd, 16, {0x02, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} }, +{ 0x14cd, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x14dd, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} }, +{ 0x14ed, 16, {0x04, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} }, +{ 0x14fd, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x150d, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0x90, 0x78, 0x41, 0x74} }, +{ 0x151d, 16, {0x06, 0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24} }, +{ 0x152d, 16, {0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x153d, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5} }, +{ 0x154d, 16, {0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x07, 0xf0, 0x90, 0xc0} }, +{ 0x155d, 15, {0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x05, 0xf0, 0x90, 0xc0, 0x00, 0xed, 0xf0, 0x22} }, +{ 0x156c, 16, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0x74, 0xbf, 0xf0, 0xe4, 0x90, 0x78, 0x41} }, +{ 0x157c, 16, {0xf0, 0x90, 0xc0, 0x00, 0xef, 0xf0, 0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0xe5, 0x27, 0x24, 0x37} }, +{ 0x158c, 15, {0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x54, 0x7f, 0x90, 0xc0, 0x00, 0xf0, 0x22} }, +{ 0x159b, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0e, 0x14} }, +{ 0x15ab, 16, {0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc6, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xc8} }, +{ 0x15bb, 15, {0xe0, 0xff, 0x22, 0x90, 0x7f, 0xca, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcc, 0xe0, 0xff, 0x22} }, +{ 0x15ca, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0e, 0x14} }, +{ 0x15da, 16, {0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xb6, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xb8} }, +{ 0x15ea, 15, {0xe0, 0xff, 0x22, 0x90, 0x7f, 0xba, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xbc, 0xe0, 0xff, 0x22} }, +{ 0x15f9, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x14, 0x60, 0x0e, 0x14} }, +{ 0x1609, 16, {0x60, 0x11, 0x14, 0x60, 0x14, 0x80, 0x00, 0x90, 0x7f, 0xc7, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xc9} }, +{ 0x1619, 15, {0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcb, 0xe0, 0xff, 0x22, 0x90, 0x7f, 0xcd, 0xe0, 0xff, 0x22} }, +{ 0x1628, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x30} }, +{ 0x1638, 16, {0x05, 0x04, 0xc2, 0x05, 0x80, 0x02, 0xd2, 0x08, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x08} }, +{ 0x1648, 14, {0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x1656, 16, {0x90, 0x7b, 0x41, 0xe0, 0xf5, 0x17, 0x43, 0x25, 0x10, 0xa3, 0xe0, 0x60, 0x09, 0x90, 0x7f, 0xd7} }, +{ 0x1666, 16, {0x74, 0x17, 0xf0, 0x74, 0x37, 0xf0, 0x90, 0x7b, 0x43, 0xe0, 0xf5, 0x18, 0x30, 0x00, 0x07, 0xa3} }, +{ 0x1676, 10, {0xe0, 0x54, 0xf0, 0xf5, 0x0c, 0x22, 0xe4, 0xf5, 0x0c, 0x22} }, +{ 0x1680, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0x90} }, +{ 0x1690, 16, {0x7f, 0xc4, 0xe4, 0xf0, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x04, 0xf0, 0xd0, 0x86, 0xd0} }, +{ 0x16a0, 10, {0x84, 0xd0, 0x85, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x16aa, 16, {0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, 0x85, 0xc0, 0x84, 0xc0, 0x86, 0x75, 0x86, 0x00, 0xd2} }, +{ 0x16ba, 16, {0x01, 0x53, 0x91, 0xef, 0x90, 0x7f, 0xab, 0x74, 0x01, 0xf0, 0xd0, 0x86, 0xd0, 0x84, 0xd0, 0x85} }, +{ 0x16ca, 7, {0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32} }, +{ 0x16d1, 16, {0x12, 0x17, 0xb5, 0xae, 0x07, 0x12, 0x17, 0xb5, 0xad, 0x07, 0xee, 0x6d, 0x60, 0x10, 0x12, 0x17} }, +{ 0x16e1, 16, {0xb5, 0xae, 0x07, 0xee, 0x6d, 0x60, 0x07, 0x12, 0x17, 0xb5, 0xad, 0x07, 0x80, 0xec, 0xaf, 0x06} }, +{ 0x16f1, 1, {0x22} }, +{ 0x16f2, 16, {0x74, 0x00, 0xf5, 0x86, 0x90, 0xfd, 0xa5, 0x7c, 0x05, 0xa3, 0xe5, 0x82, 0x45, 0x83, 0x70, 0xf9} }, +{ 0x1702, 1, {0x22} }, +{ 0x1703, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x80, 0xf0, 0x43, 0x87, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22} }, +{ 0x1713, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x04, 0xf0, 0xe0, 0x44, 0x08, 0xf0, 0x30, 0x09, 0x04, 0xe0, 0x44} }, +{ 0x1723, 16, {0x02, 0xf0, 0x7f, 0xf4, 0x7e, 0x01, 0x12, 0x17, 0x34, 0x90, 0x7f, 0xd6, 0xe0, 0x54, 0xf7, 0xf0} }, +{ 0x1733, 1, {0x22} }, +{ 0x1734, 16, {0x8e, 0x19, 0x8f, 0x1a, 0xe5, 0x1a, 0x15, 0x1a, 0xae, 0x19, 0x70, 0x02, 0x15, 0x19, 0x4e, 0x60} }, +{ 0x1744, 10, {0x08, 0x12, 0x16, 0xf2, 0x12, 0x16, 0xf2, 0x80, 0xeb, 0x22} }, +{ 0x174e, 16, {0xe5, 0x27, 0x24, 0x04, 0xf5, 0x82, 0xe4, 0x35, 0x26, 0xf5, 0x83, 0xe0, 0x04, 0xff, 0x44, 0x10} }, +{ 0x175e, 9, {0x90, 0x7f, 0xd7, 0xf0, 0xef, 0x44, 0x30, 0xf0, 0x22} }, +{ 0x1767, 16, {0x03, 0x16, 0x80, 0x00, 0x00, 0x03, 0x11, 0x81, 0x00, 0x00, 0xc1, 0x85, 0xc1, 0x81, 0xc1, 0x08} }, +{ 0x1777, 7, {0xc1, 0x00, 0xc1, 0x86, 0x01, 0x09, 0x00} }, +{ 0x177e, 1, {0x00} }, +{ 0x177f, 16, {0x90, 0x7f, 0xd6, 0xe0, 0x44, 0x01, 0xf0, 0x7f, 0x0d, 0x7e, 0x00, 0x12, 0x17, 0x34, 0x90, 0x7f} }, +{ 0x178f, 6, {0xd6, 0xe0, 0x54, 0xfe, 0xf0, 0x22} }, +{ 0x1795, 16, {0x12, 0x12, 0xae, 0x12, 0x17, 0x03, 0x90, 0x7f, 0xd6, 0xe0, 0x30, 0xe7, 0x03, 0x12, 0x17, 0x7f} }, +{ 0x17a5, 4, {0x12, 0x0a, 0x6a, 0x22} }, +{ 0x17a9, 12, {0x90, 0x78, 0x41, 0x74, 0x02, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x17b5, 12, {0x90, 0x78, 0x41, 0x74, 0x03, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x17c1, 12, {0x90, 0x78, 0x41, 0x74, 0x04, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x17cd, 12, {0x90, 0x78, 0x41, 0x74, 0x05, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x17d9, 12, {0x90, 0x78, 0x41, 0x74, 0x06, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x17e5, 11, {0xe4, 0x90, 0x78, 0x41, 0xf0, 0x90, 0xc0, 0x00, 0xe0, 0xff, 0x22} }, +{ 0x17f0, 4, {0x53, 0xd8, 0xef, 0x32} }, +{ 0x1800, 15, {0x02, 0x16, 0xaa, 0x00, 0x02, 0x18, 0x04, 0x00, 0x02, 0x16, 0x80, 0x00, 0x02, 0x16, 0x28} }, +{ 0x1900, 16, {0x12, 0x01, 0x01, 0x00, 0xff, 0x00, 0x00, 0x40, 0xcd, 0x06, 0x0a, 0x01, 0x00, 0x00, 0x01, 0x02} }, +{ 0x1910, 16, {0x00, 0x04, 0x09, 0x02, 0x74, 0x00, 0x01, 0x01, 0x00, 0xa0, 0x32, 0x09, 0x04, 0x00, 0x00, 0x0e} }, +{ 0x1920, 16, {0xff, 0x00, 0x00, 0x00, 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x02, 0x02, 0x40} }, +{ 0x1930, 16, {0x00, 0x00, 0x07, 0x05, 0x03, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00} }, +{ 0x1940, 16, {0x07, 0x05, 0x05, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x06, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05} }, +{ 0x1950, 16, {0x07, 0x02, 0x40, 0x00, 0x00, 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x82, 0x02} }, +{ 0x1960, 16, {0x40, 0x00, 0x01, 0x07, 0x05, 0x83, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x84, 0x02, 0x40, 0x00} }, +{ 0x1970, 16, {0x01, 0x07, 0x05, 0x85, 0x02, 0x40, 0x00, 0x01, 0x07, 0x05, 0x86, 0x02, 0x40, 0x00, 0x01, 0x07} }, +{ 0x1980, 16, {0x05, 0x87, 0x02, 0x40, 0x00, 0x01, 0x04, 0x03, 0x09, 0x04, 0x48, 0x03, 0x4b, 0x00, 0x65, 0x00} }, +{ 0x1990, 16, {0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x2c, 0x00, 0x20, 0x00, 0x61, 0x00} }, +{ 0x19a0, 16, {0x20, 0x00, 0x64, 0x00, 0x69, 0x00, 0x76, 0x00, 0x69, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00} }, +{ 0x19b0, 16, {0x6e, 0x00, 0x20, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x6e, 0x00} }, +{ 0x19c0, 16, {0x6f, 0x00, 0x53, 0x00, 0x79, 0x00, 0x73, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x63, 0x00} }, +{ 0x19d0, 16, {0x2e, 0x00, 0x36, 0x03, 0x4b, 0x00, 0x65, 0x00, 0x79, 0x00, 0x73, 0x00, 0x70, 0x00, 0x61, 0x00} }, +{ 0x19e0, 16, {0x6e, 0x00, 0x20, 0x00, 0x55, 0x00, 0x53, 0x00, 0x42, 0x00, 0x20, 0x00, 0x53, 0x00, 0x65, 0x00} }, +{ 0x19f0, 16, {0x72, 0x00, 0x69, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x41, 0x00, 0x64, 0x00, 0x61, 0x00} }, +{ 0x1a00, 10, {0x70, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00} }, +{ 0xffff, 0, {0x00} } +}; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c --- v2.4.0-test11/linux/drivers/usb/serial/mct_u232.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/mct_u232.c Thu Dec 7 16:13:38 2000 @@ -0,0 +1,774 @@ +/* + * MCT (Magic Control Technology Corp.) USB RS232 Converter Driver + * + * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is largely derived from the Belkin USB Serial Adapter Driver + * (see belkin_sa.[ch]). All of the information about the device was acquired + * by using SniffUSB on Windows98. For technical details see mct_u232.h. + * + * William G. Greathouse and Greg Kroah-Hartman provided great help on how to + * do the reverse engineering and how to write a USB serial device driver. + * + * TO BE DONE, TO BE CHECKED: + * DTR/RTS signal handling may be incomplete or incorrect. I have mainly + * implemented what I have seen with SniffUSB or found in belkin_sa.c. + * For further TODOs check also belkin_sa.c. + * + * TEST STATUS: + * Basic tests have been performed with minicom/zmodem transfers and + * modem dialing under Linux 2.4.0-test10 (for me it works fine). + * + * 29-Nov-2000 Greg Kroah-Hartman + * - Added device id table to fit with 2.4.0-test11 structure. + * - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed + * (lots of things will change if/when the usb-serial core changes to + * handle these issues. + * + * 27-Nov-2000 Wolfgang Grandegger + * A version for kernel 2.4.0-test10 released to the Linux community + * (via linux-usb-devel). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" +#include "mct_u232.h" + + +/* + * Some not properly written applications do not handle the return code of + * write() correctly. This can result in character losses. A work-a-round + * can be compiled in with the following definition. This work-a-round + * should _NOT_ be part of an 'official' kernel release, of course! + */ +#undef FIX_WRITE_RETURN_CODE_PROBLEM +#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +static int write_blocking = 0; /* disabled by default */ +#endif + +/* + * Function prototypes + */ +static int mct_u232_startup (struct usb_serial *serial); +static void mct_u232_shutdown (struct usb_serial *serial); +static int mct_u232_open (struct usb_serial_port *port, + struct file *filp); +static void mct_u232_close (struct usb_serial_port *port, + struct file *filp); +#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +static int mct_u232_write (struct usb_serial_port *port, + int from_user, + const unsigned char *buf, + int count); +static void mct_u232_write_bulk_callback (struct urb *urb); +#endif +static void mct_u232_read_int_callback (struct urb *urb); +static void mct_u232_set_termios (struct usb_serial_port *port, + struct termios * old); +static int mct_u232_ioctl (struct usb_serial_port *port, + struct file * file, + unsigned int cmd, + unsigned long arg); +static void mct_u232_break_ctl (struct usb_serial_port *port, + int break_state ); + +/* + * All of the device info needed for the MCT USB-RS232 converter. + */ +static __devinitdata struct usb_device_id id_table [] = { + { idVendor: MCT_U232_VID, idProduct: MCT_U232_PID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table); + + +struct usb_serial_device_type mct_u232_device = { + name: "Magic Control Technology USB-RS232", + id_table: id_table, + needs_interrupt_in: MUST_HAVE, /* 2 interrupt-in endpoints */ + needs_bulk_in: MUST_HAVE_NOT, /* no bulk-in endpoint */ + needs_bulk_out: MUST_HAVE, /* 1 bulk-out endpoint */ + num_interrupt_in: 2, + num_bulk_in: 0, + num_bulk_out: 1, + num_ports: 1, + open: mct_u232_open, + close: mct_u232_close, +#ifdef FIX_WRITE_RETURN_CODE_PROBLEM + write: mct_u232_write, + write_bulk_callback: mct_u232_write_bulk_callback, +#endif + read_int_callback: mct_u232_read_int_callback, + ioctl: mct_u232_ioctl, + set_termios: mct_u232_set_termios, + break_ctl: mct_u232_break_ctl, + startup: mct_u232_startup, + shutdown: mct_u232_shutdown, +}; + +struct mct_u232_private { + unsigned long control_state; /* Modem Line Setting (TIOCM) */ + unsigned char last_lcr; /* Line Control Register */ + unsigned char last_lsr; /* Line Status Register */ + unsigned char last_msr; /* Modem Status Register */ +}; + +/* + * Handle vendor specific USB requests + */ + +#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ + +static int mct_u232_set_baud_rate(struct usb_serial *serial, int value) +{ + unsigned int divisor; + int rc; + divisor = MCT_U232_BAUD_RATE(value); + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCT_U232_SET_BAUD_RATE_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &divisor, MCT_U232_SET_BAUD_RATE_SIZE, + WDR_TIMEOUT); + if (rc < 0) + err("Set BAUD RATE %d failed (error = %d)", value, rc); + dbg("set_baud_rate: 0x%x", divisor); + return rc; +} /* mct_u232_set_baud_rate */ + +static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) +{ + int rc; + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCT_U232_SET_LINE_CTRL_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &lcr, MCT_U232_SET_LINE_CTRL_SIZE, + WDR_TIMEOUT); + if (rc < 0) + err("Set LINE CTRL 0x%x failed (error = %d)", lcr, rc); + dbg("set_line_ctrl: 0x%x", lcr); + return rc; +} /* mct_u232_set_line_ctrl */ + +static int mct_u232_set_modem_ctrl(struct usb_serial *serial, + unsigned long control_state) +{ + int rc; + unsigned char mcr = MCT_U232_MCR_NONE; + + if (control_state & TIOCM_DTR) + mcr |= MCT_U232_MCR_DTR; + if (control_state & TIOCM_RTS) + mcr |= MCT_U232_MCR_RTS; + + rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + MCT_U232_SET_MODEM_CTRL_REQUEST, + MCT_U232_SET_REQUEST_TYPE, + 0, 0, &mcr, MCT_U232_SET_MODEM_CTRL_SIZE, + WDR_TIMEOUT); + if (rc < 0) + err("Set MODEM CTRL 0x%x failed (error = %d)", mcr, rc); + dbg("set_modem_ctrl: state=0x%lx ==> mcr=0x%x", control_state, mcr); + + return rc; +} /* mct_u232_set_modem_ctrl */ + +static int mct_u232_get_modem_stat(struct usb_serial *serial, unsigned char *msr) +{ + int rc; + rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + MCT_U232_GET_MODEM_STAT_REQUEST, + MCT_U232_GET_REQUEST_TYPE, + 0, 0, msr, MCT_U232_GET_MODEM_STAT_SIZE, + WDR_TIMEOUT); + if (rc < 0) { + err("Get MODEM STATus failed (error = %d)", rc); + *msr = 0; + } + dbg("get_modem_stat: 0x%x", *msr); + return rc; +} /* mct_u232_get_modem_stat */ + +static void mct_u232_msr_to_state(unsigned long *control_state, unsigned char msr) +{ + /* Translate Control Line states */ + if (msr & MCT_U232_MSR_DSR) + *control_state |= TIOCM_DSR; + else + *control_state &= ~TIOCM_DSR; + if (msr & MCT_U232_MSR_CTS) + *control_state |= TIOCM_CTS; + else + *control_state &= ~TIOCM_CTS; + if (msr & MCT_U232_MSR_RI) + *control_state |= TIOCM_RI; + else + *control_state &= ~TIOCM_RI; + if (msr & MCT_U232_MSR_CD) + *control_state |= TIOCM_CD; + else + *control_state &= ~TIOCM_CD; + dbg("msr_to_state: msr=0x%x ==> state=0x%lx", msr, *control_state); +} /* mct_u232_msr_to_state */ + +/* + * Driver's tty interface functions + */ + +static int mct_u232_startup (struct usb_serial *serial) +{ + struct mct_u232_private *priv; + + /* allocate the private data structure */ + serial->port->private = kmalloc(sizeof(struct mct_u232_private), + GFP_KERNEL); + if (!serial->port->private) + return (-1); /* error */ + priv = (struct mct_u232_private *)serial->port->private; + /* set initial values for control structures */ + priv->control_state = 0; + priv->last_lsr = 0; + priv->last_msr = 0; + + init_waitqueue_head(&serial->port->write_wait); + + return (0); +} /* mct_u232_startup */ + + +static void mct_u232_shutdown (struct usb_serial *serial) +{ + int i; + + dbg (__FUNCTION__); + + /* stop reads and writes on all ports */ + for (i=0; i < serial->num_ports; ++i) { + while (serial->port[i].open_count > 0) { + mct_u232_close (&serial->port[i], NULL); + } + /* My special items, the standard routines free my urbs */ + if (serial->port->private) + kfree(serial->port->private); + } +} /* mct_u232_shutdown */ + +static int mct_u232_open (struct usb_serial_port *port, struct file *filp) +{ + unsigned long flags; + struct usb_serial *serial = port->serial; + struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + + dbg(__FUNCTION__" port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + ++port->open_count; + MOD_INC_USE_COUNT; + + if (!port->active) { + port->active = 1; + + /* Do a defined restart: the normal serial device seems to + * always turn on DTR and RTS here, so do the same. I'm not + * sure if this is really necessary. But it should not harm + * either. + */ + if (port->tty->termios->c_cflag & CBAUD) + priv->control_state = TIOCM_DTR | TIOCM_RTS; + else + priv->control_state = 0; + mct_u232_set_modem_ctrl(serial, priv->control_state); + + priv->last_lcr = (MCT_U232_DATA_BITS_8 | + MCT_U232_PARITY_NONE | + MCT_U232_STOP_BITS_1); + mct_u232_set_line_ctrl(serial, priv->last_lcr); + + /* Read modem status and update control state */ + mct_u232_get_modem_stat(serial, &priv->last_msr); + mct_u232_msr_to_state(&priv->control_state, priv->last_msr); + + { + /* Puh, that's dirty */ + struct usb_serial_port *rport; + rport = &serial->port[1]; + rport->tty = port->tty; + rport->private = port->private; + port->read_urb = rport->interrupt_in_urb; + } + + port->read_urb->dev = port->serial->dev; + if (usb_submit_urb(port->read_urb)) + err("usb_submit_urb(read bulk) failed"); + + port->interrupt_in_urb->dev = port->serial->dev; + if (usb_submit_urb(port->interrupt_in_urb)) + err(" usb_submit_urb(read int) failed"); + + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + return 0; +} /* mct_u232_open */ + + +static void mct_u232_close (struct usb_serial_port *port, struct file *filp) +{ + unsigned long flags; + + dbg(__FUNCTION__" port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + --port->open_count; + MOD_DEC_USE_COUNT; + + if (port->open_count <= 0) { + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + /* wgg - do I need this? I think so. */ + usb_unlink_urb (port->interrupt_in_urb); + port->active = 0; + } + + spin_unlock_irqrestore (&port->port_lock, flags); + +} /* mct_u232_close */ + + +#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +/* The generic routines work fine otherwise */ + +static int mct_u232_write (struct usb_serial_port *port, int from_user, + const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + unsigned long flags; + int result, bytes_sent, size; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (count == 0) { + dbg(__FUNCTION__ " - write request of 0 bytes"); + return (0); + } + + /* only do something if we have a bulk out endpoint */ + if (!serial->num_bulk_out) + return(0);; + + /* another write is still pending? */ + if (port->write_urb->status == -EINPROGRESS) { + dbg (__FUNCTION__ " - already writing"); + return (0); + } + + bytes_sent = 0; + while (count > 0) { + + spin_lock_irqsave (&port->port_lock, flags); + + size = (count > port->bulk_out_size) ? port->bulk_out_size : count; + + usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf); + + if (from_user) { + copy_from_user(port->write_urb->transfer_buffer, buf, size); + } + else { + memcpy (port->write_urb->transfer_buffer, buf, size); + } + + /* set up our urb */ + FILL_BULK_URB(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, size, + ((serial->type->write_bulk_callback) ? + serial->type->write_bulk_callback : + mct_u232_write_bulk_callback), + port); + + /* send the data out the bulk port */ + result = usb_submit_urb(port->write_urb); + if (result) { + err(__FUNCTION__ + " - failed submitting write urb, error %d", result); + spin_unlock_irqrestore (&port->port_lock, flags); + return bytes_sent; + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + bytes_sent += size; + if (write_blocking) + interruptible_sleep_on(&port->write_wait); + else + break; + + buf += size; + count -= size; + } + + return bytes_sent; +} /* mct_u232_write */ + +static void mct_u232_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = port->serial; + struct tty_struct *tty = port->tty; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero write bulk status received: %d", + urb->status); + return; + } + + if (write_blocking) { + wake_up_interruptible(&port->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + + } else { + /* from generic_write_bulk_callback */ + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + + return; +} /* mct_u232_write_bulk_callback */ +#endif + +static void mct_u232_read_int_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + struct usb_serial *serial = port->serial; + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + + dbg(__FUNCTION__ " - port %d", port->number); + + /* The urb might have been killed. */ + if (urb->status) { + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", + urb->status); + return; + } + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); + return; + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + /* + * Work-a-round: handle the 'usual' bulk-in pipe here + */ + if (urb->transfer_buffer_length > 2) { + int i; + tty = port->tty; + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + tty_insert_flip_char(tty, data[i], 0); + } + tty_flip_buffer_push(tty); + } + /* INT urbs are automatically re-submitted */ + return; + } + + /* + * The interrupt-in pipe signals exceptional conditions (modem line + * signal changes and errors). data[0] holds MSR, data[1] holds LSR. + */ + priv->last_msr = data[MCT_U232_MSR_INDEX]; + + /* Record Control Line states */ + mct_u232_msr_to_state(&priv->control_state, priv->last_msr); + +#if 0 + /* Not yet handled. See belin_sa.c for further information */ + /* Now to report any errors */ + priv->last_lsr = data[MCT_U232_LSR_INDEX]; + /* + * fill in the flip buffer here, but I do not know the relation + * to the current/next receive buffer or characters. I need + * to look in to this before committing any code. + */ + if (priv->last_lsr & MCT_U232_LSR_ERR) { + tty = port->tty; + /* Overrun Error */ + if (priv->last_lsr & MCT_U232_LSR_OE) { + } + /* Parity Error */ + if (priv->last_lsr & MCT_U232_LSR_PE) { + } + /* Framing Error */ + if (priv->last_lsr & MCT_U232_LSR_FE) { + } + /* Break Indicator */ + if (priv->last_lsr & MCT_U232_LSR_BI) { + } + } +#endif + + /* INT urbs are automatically re-submitted */ +} /* mct_u232_read_int_callback */ + + +static void mct_u232_set_termios (struct usb_serial_port *port, + struct termios *old_termios) +{ + struct usb_serial *serial = port->serial; + struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + unsigned int iflag = port->tty->termios->c_iflag; + unsigned int old_iflag = old_termios->c_iflag; + unsigned int cflag = port->tty->termios->c_cflag; + unsigned int old_cflag = old_termios->c_cflag; + + /* + * Update baud rate + */ + if( (cflag & CBAUD) != (old_cflag & CBAUD) ) { + /* reassert DTR and (maybe) RTS on transition from B0 */ + if( (old_cflag & CBAUD) == B0 ) { + dbg(__FUNCTION__ ": baud was B0"); + priv->control_state |= TIOCM_DTR; + /* don't set RTS if using hardware flow control */ + if (!(old_cflag & CRTSCTS)) { + priv->control_state |= TIOCM_RTS; + } + mct_u232_set_modem_ctrl(serial, priv->control_state); + } + + switch(cflag & CBAUD) { + case B0: /* handled below */ + break; + case B300: mct_u232_set_baud_rate(serial, 300); + break; + case B600: mct_u232_set_baud_rate(serial, 600); + break; + case B1200: mct_u232_set_baud_rate(serial, 1200); + break; + case B2400: mct_u232_set_baud_rate(serial, 2400); + break; + case B4800: mct_u232_set_baud_rate(serial, 4800); + break; + case B9600: mct_u232_set_baud_rate(serial, 9600); + break; + case B19200: mct_u232_set_baud_rate(serial, 19200); + break; + case B38400: mct_u232_set_baud_rate(serial, 38400); + break; + case B57600: mct_u232_set_baud_rate(serial, 57600); + break; + case B115200: mct_u232_set_baud_rate(serial, 115200); + break; + default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600"); + mct_u232_set_baud_rate(serial, 9600); break; + } + if ((cflag & CBAUD) == B0 ) { + dbg(__FUNCTION__ ": baud is B0"); + /* Drop RTS and DTR */ + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + mct_u232_set_modem_ctrl(serial, priv->control_state); + } + } + + /* + * Update line control register (LCR) + */ + if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD)) + || (cflag & CSIZE) != (old_cflag & CSIZE) + || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) { + + + priv->last_lcr = 0; + + /* set the parity */ + if (cflag & PARENB) + priv->last_lcr |= (cflag & PARODD) ? + MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN; + else + priv->last_lcr |= MCT_U232_PARITY_NONE; + + /* set the number of data bits */ + switch (cflag & CSIZE) { + case CS5: + priv->last_lcr |= MCT_U232_DATA_BITS_5; break; + case CS6: + priv->last_lcr |= MCT_U232_DATA_BITS_6; break; + case CS7: + priv->last_lcr |= MCT_U232_DATA_BITS_7; break; + case CS8: + priv->last_lcr |= MCT_U232_DATA_BITS_8; break; + default: + err("CSIZE was not CS5-CS8, using default of 8"); + priv->last_lcr |= MCT_U232_DATA_BITS_8; + break; + } + + /* set the number of stop bits */ + priv->last_lcr |= (cflag & CSTOPB) ? + MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; + + mct_u232_set_line_ctrl(serial, priv->last_lcr); + } + + /* + * Set flow control: well, I do not really now how to handle DTR/RTS. + * Just do what we have seen with SniffUSB on Win98. + */ + if( (iflag & IXOFF) != (old_iflag & IXOFF) + || (iflag & IXON) != (old_iflag & IXON) + || (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) { + + /* Drop DTR/RTS if no flow control otherwise assert */ + if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) ) + priv->control_state |= TIOCM_DTR | TIOCM_RTS; + else + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + mct_u232_set_modem_ctrl(serial, priv->control_state); + } +} /* mct_u232_set_termios */ + + +static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ) +{ + struct usb_serial *serial = port->serial; + struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + unsigned char lcr = priv->last_lcr; + + dbg (__FUNCTION__ "state=%d", break_state); + + if (break_state) + lcr |= MCT_U232_SET_BREAK; + + mct_u232_set_line_ctrl(serial, lcr); +} /* mct_u232_break_ctl */ + + +static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial *serial = port->serial; + struct mct_u232_private *priv = (struct mct_u232_private *)port->private; + int ret, mask; + + dbg (__FUNCTION__ "cmd=0x%x", cmd); + + /* Based on code from acm.c and others */ + switch (cmd) { + case TIOCMGET: + return put_user(priv->control_state, (unsigned long *) arg); + break; + + case TIOCMSET: /* Turns on and off the lines as specified by the mask */ + case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ + case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ + if ((ret = get_user(mask, (unsigned long *) arg))) return ret; + + if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) { + /* RTS needs set */ + if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || + (cmd == TIOCMBIS) ) + priv->control_state |= TIOCM_RTS; + else + priv->control_state &= ~TIOCM_RTS; + } + + if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { + /* DTR needs set */ + if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || + (cmd == TIOCMBIS) ) + priv->control_state |= TIOCM_DTR; + else + priv->control_state &= ~TIOCM_DTR; + } + mct_u232_set_modem_ctrl(serial, priv->control_state); + break; + + case TIOCMIWAIT: + /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ + /* TODO */ + return( 0 ); + + case TIOCGICOUNT: + /* return count of modemline transitions */ + /* TODO */ + return 0; + + default: + dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd); + return(-ENOIOCTLCMD); + break; + } + return 0; +} /* mct_u232_ioctl */ + + +static int __init mct_u232_init (void) +{ + usb_serial_register (&mct_u232_device); + + return 0; +} + + +static void __exit mct_u232_exit (void) +{ + usb_serial_deregister (&mct_u232_device); +} + + +module_init (mct_u232_init); +module_exit(mct_u232_exit); + +MODULE_AUTHOR("Wolfgang Grandegger "); +MODULE_DESCRIPTION("Magic Control Technology USB-RS232 converter driver"); + +#ifdef FIX_WRITE_RETURN_CODE_PROBLEM +MODULE_PARM(write_blocking, "i"); +MODULE_PARM_DESC(write_blocking, + "The write function will block to write out all data"); +#endif diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/mct_u232.h linux/drivers/usb/serial/mct_u232.h --- v2.4.0-test11/linux/drivers/usb/serial/mct_u232.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/mct_u232.h Thu Dec 7 16:13:38 2000 @@ -0,0 +1,362 @@ +/* + * Definitions for MCT (Magic Control Technology) USB-RS232 Converter Driver + * + * Copyright (C) 2000 Wolfgang Grandegger (wolfgang@ces.ch) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This driver is for the device MCT USB-RS232 Converter (25 pin, Model No. + * U232-P25) from Magic Control Technology Corp. (there is also a 9 pin + * Model No. U232-P9). See http://www.mct.com.tw/p_u232.html for further + * information. The properties of this device are listed at the end of this + * file. This device is available from various distributors. I know Hana, + * http://www.hana.de and D-Link, http://www.dlink.com/products/usb/dsbs25. + * + * All of the information about the device was acquired by using SniffUSB + * on Windows98. The technical details of the reverse engineering are + * summarized at the end of this file. + */ + +#ifndef __LINUX_USB_SERIAL_MCT_U232_H +#define __LINUX_USB_SERIAL_MCT_U232_H + +#define MCT_U232_VID 0x0711 /* Vendor Id */ +#define MCT_U232_PID 0x0210 /* Product Id */ + +/* + * Vendor Request Interface + */ +#define MCT_U232_SET_REQUEST_TYPE 0x40 +#define MCT_U232_GET_REQUEST_TYPE 0xc0 + +#define MCT_U232_GET_MODEM_STAT_REQUEST 2 /* Get Modem Status Register (MSR) */ +#define MCT_U232_GET_MODEM_STAT_SIZE 1 + +#define MCT_U232_GET_LINE_CTRL_REQUEST 6 /* Get Line Control Register (LCR) */ +#define MCT_U232_GET_LINE_CTRL_SIZE 1 /* ... not used by this driver */ + +#define MCT_U232_SET_BAUD_RATE_REQUEST 5 /* Set Baud Rate Divisor */ +#define MCT_U232_SET_BAUD_RATE_SIZE 4 + +#define MCT_U232_SET_LINE_CTRL_REQUEST 7 /* Set Line Control Register (LCR) */ +#define MCT_U232_SET_LINE_CTRL_SIZE 1 + +#define MCT_U232_SET_MODEM_CTRL_REQUEST 10 /* Set Modem Control Register (MCR) */ +#define MCT_U232_SET_MODEM_CTRL_SIZE 1 + +/* + * Baud rate (divisor) + */ +#define MCT_U232_BAUD_RATE(b) (115200/b) + +/* + * Line Control Register (LCR) + */ +#define MCT_U232_SET_BREAK 0x40 + +#define MCT_U232_PARITY_SPACE 0x38 +#define MCT_U232_PARITY_MARK 0x28 +#define MCT_U232_PARITY_EVEN 0x18 +#define MCT_U232_PARITY_ODD 0x08 +#define MCT_U232_PARITY_NONE 0x00 + +#define MCT_U232_DATA_BITS_5 0x00 +#define MCT_U232_DATA_BITS_6 0x01 +#define MCT_U232_DATA_BITS_7 0x02 +#define MCT_U232_DATA_BITS_8 0x03 + +#define MCT_U232_STOP_BITS_2 0x04 +#define MCT_U232_STOP_BITS_1 0x00 + +/* + * Modem Control Register (MCR) + */ +#define MCT_U232_MCR_NONE 0x8 /* Deactivate DTR and RTS */ +#define MCT_U232_MCR_RTS 0xa /* Activate RTS */ +#define MCT_U232_MCR_DTR 0x9 /* Activate DTR */ + +/* + * Modem Status Register (MSR) + */ +#define MCT_U232_MSR_INDEX 0x0 /* data[index] */ +#define MCT_U232_MSR_CD 0x80 /* Current CD */ +#define MCT_U232_MSR_RI 0x40 /* Current RI */ +#define MCT_U232_MSR_DSR 0x20 /* Current DSR */ +#define MCT_U232_MSR_CTS 0x10 /* Current CTS */ +#define MCT_U232_MSR_DCD 0x08 /* Delta CD */ +#define MCT_U232_MSR_DRI 0x04 /* Delta RI */ +#define MCT_U232_MSR_DDSR 0x02 /* Delta DSR */ +#define MCT_U232_MSR_DCTS 0x01 /* Delta CTS */ + +/* + * Line Status Register (LSR) + */ +#define MCT_U232_LSR_INDEX 1 /* data[index] */ +#define MCT_U232_LSR_ERR 0x80 /* OE | PE | FE | BI */ +#define MCT_U232_LSR_TEMT 0x40 /* transmit register empty */ +#define MCT_U232_LSR_THRE 0x20 /* transmit holding register empty */ +#define MCT_U232_LSR_BI 0x10 /* break indicator */ +#define MCT_U232_LSR_FE 0x08 /* framing error */ +#define MCT_U232_LSR_OE 0x02 /* overrun error */ +#define MCT_U232_LSR_PE 0x04 /* parity error */ +#define MCT_U232_LSR_OE 0x02 /* overrun error */ +#define MCT_U232_LSR_DR 0x01 /* receive data ready */ + + +/* ----------------------------------------------------------------------------- + * Technical Specification reverse engineered with SniffUSB on Windows98 + * ===================================================================== + * + * The technical details of the device have been acquired be using "SniffUSB" + * and the vendor-supplied device driver (version 2.3A) under Windows98. To + * identify the USB vendor-specific requests and to assign them to terminal + * settings (flow control, baud rate, etc.) the program "SerialSettings" from + * William G. Greathouse has been proven to be very useful. I also used the + * Win98 "HyperTerminal" and "usb-robot" on Linux for testing. The results and + * observations are summarized below: + * + * The USB requests seem to be directly mapped to the registers of a 8250, + * 16450 or 16550 UART. The FreeBSD handbook (appendix F.4 "Input/Output + * devices") contains a comprehensive description of UARTs and its registers. + * The bit descriptions are actually taken from there. + * + * + * Baud rate (divisor) + * ------------------- + * + * BmRequestType: 0x4 (0100 0000B) + * bRequest: 0x5 + * wValue: 0x0 + * wIndex: 0x0 + * wLength: 0x4 + * Data: divisor = 115200 / baud_rate + * + * + * Line Control Register (LCR) + * --------------------------- + * + * BmRequestType: 0x4 (0100 0000B) 0xc (1100 0000B) + * bRequest: 0x7 0x6 + * wValue: 0x0 + * wIndex: 0x0 + * wLength: 0x1 + * Data: LCR (see below) + * + * Bit 7: Divisor Latch Access Bit (DLAB). When set, access to the data + * transmit/receive register (THR/RBR) and the Interrupt Enable Register + * (IER) is disabled. Any access to these ports is now redirected to the + * Divisor Latch Registers. Setting this bit, loading the Divisor + * Registers, and clearing DLAB should be done with interrupts disabled. + * Bit 6: Set Break. When set to "1", the transmitter begins to transmit + * continuous Spacing until this bit is set to "0". This overrides any + * bits of characters that are being transmitted. + * Bit 5: Stick Parity. When parity is enabled, setting this bit causes parity + * to always be "1" or "0", based on the value of Bit 4. + * Bit 4: Even Parity Select (EPS). When parity is enabled and Bit 5 is "0", + * setting this bit causes even parity to be transmitted and expected. + * Otherwise, odd parity is used. + * Bit 3: Parity Enable (PEN). When set to "1", a parity bit is inserted + * between the last bit of the data and the Stop Bit. The UART will also + * expect parity to be present in the received data. + * Bit 2: Number of Stop Bits (STB). If set to "1" and using 5-bit data words, + * 1.5 Stop Bits are transmitted and expected in each data word. For + * 6, 7 and 8-bit data words, 2 Stop Bits are transmitted and expected. + * When this bit is set to "0", one Stop Bit is used on each data word. + * Bit 1: Word Length Select Bit #1 (WLSB1) + * Bit 0: Word Length Select Bit #0 (WLSB0) + * Together these bits specify the number of bits in each data word. + * 1 0 Word Length + * 0 0 5 Data Bits + * 0 1 6 Data Bits + * 1 0 7 Data Bits + * 1 1 8 Data Bits + * + * SniffUSB observations: Bit 7 seems not to be used. There seem to be two bugs + * in the Win98 driver: the break does not work (bit 6 is not asserted) and the + * sticky parity bit is not cleared when set once. The LCR can also be read + * back with USB request 6 but this has never been observed with SniffUSB. + * + * + * Modem Control Register (MCR) + * ---------------------------- + * + * BmRequestType: 0x4 (0100 0000B) + * bRequest: 0xa + * wValue: 0x0 + * wIndex: 0x0 + * wLength: 0x1 + * Data: MCR (Bit 4..7, see below) + * + * Bit 7: Reserved, always 0. + * Bit 6: Reserved, always 0. + * Bit 5: Reserved, always 0. + * Bit 4: Loop-Back Enable. When set to "1", the UART transmitter and receiver + * are internally connected together to allow diagnostic operations. In + * addition, the UART modem control outputs are connected to the UART + * modem control inputs. CTS is connected to RTS, DTR is connected to + * DSR, OUT1 is connected to RI, and OUT 2 is connected to DCD. + * Bit 3: OUT 2. An auxiliary output that the host processor may set high or + * low. In the IBM PC serial adapter (and most clones), OUT 2 is used + * to tri-state (disable) the interrupt signal from the + * 8250/16450/16550 UART. + * Bit 2: OUT 1. An auxiliary output that the host processor may set high or + * low. This output is not used on the IBM PC serial adapter. + * Bit 1: Request to Send (RTS). When set to "1", the output of the UART -RTS + * line is Low (Active). + * Bit 0: Data Terminal Ready (DTR). When set to "1", the output of the UART + * -DTR line is Low (Active). + * + * SniffUSB observations: Bit 2 and 4 seem not to be used but bit 3 has been + * seen _always_ set. + * + * + * Modem Status Register (MSR) + * --------------------------- + * + * BmRequestType: 0xc (1100 0000B) + * bRequest: 0x2 + * wValue: 0x0 + * wIndex: 0x0 + * wLength: 0x1 + * Data: MSR (see below) + * + * Bit 7: Data Carrier Detect (CD). Reflects the state of the DCD line on the + * UART. + * Bit 6: Ring Indicator (RI). Reflects the state of the RI line on the UART. + * Bit 5: Data Set Ready (DSR). Reflects the state of the DSR line on the UART. + * Bit 4: Clear To Send (CTS). Reflects the state of the CTS line on the UART. + * Bit 3: Delta Data Carrier Detect (DDCD). Set to "1" if the -DCD line has + * changed state one more more times since the last time the MSR was + * read by the host. + * Bit 2: Trailing Edge Ring Indicator (TERI). Set to "1" if the -RI line has + * had a low to high transition since the last time the MSR was read by + * the host. + * Bit 1: Delta Data Set Ready (DDSR). Set to "1" if the -DSR line has changed + * state one more more times since the last time the MSR was read by the + * host. + * Bit 0: Delta Clear To Send (DCTS). Set to "1" if the -CTS line has changed + * state one more times since the last time the MSR was read by the + * host. + * + * SniffUSB observations: the MSR is also returned as first byte on the + * interrupt-in endpoint 0x83 to signal changes of modem status lines. The USB + * request to read MSR cannot be applied during normal device operation. + * + * + * Line Status Register (LSR) + * -------------------------- + * + * Bit 7 Error in Receiver FIFO. On the 8250/16450 UART, this bit is zero. + * This bit is set to "1" when any of the bytes in the FIFO have one or + * more of the following error conditions: PE, FE, or BI. + * Bit 6 Transmitter Empty (TEMT). When set to "1", there are no words + * remaining in the transmit FIFO or the transmit shift register. The + * transmitter is completely idle. + * Bit 5 Transmitter Holding Register Empty (THRE). When set to "1", the FIFO + * (or holding register) now has room for at least one additional word + * to transmit. The transmitter may still be transmitting when this bit + * is set to "1". + * Bit 4 Break Interrupt (BI). The receiver has detected a Break signal. + * Bit 3 Framing Error (FE). A Start Bit was detected but the Stop Bit did not + * appear at the expected time. The received word is probably garbled. + * Bit 2 Parity Error (PE). The parity bit was incorrect for the word received. + * Bit 1 Overrun Error (OE). A new word was received and there was no room in + * the receive buffer. The newly-arrived word in the shift register is + * discarded. On 8250/16450 UARTs, the word in the holding register is + * discarded and the newly- arrived word is put in the holding register. + * Bit 0 Data Ready (DR). One or more words are in the receive FIFO that the + * host may read. A word must be completely received and moved from the + * shift register into the FIFO (or holding register for 8250/16450 + * designs) before this bit is set. + * + * SniffUSB observations: the LSR is returned as second byte on the interrupt-in + * endpoint 0x83 to signal error conditions. Such errors have been seen with + * minicom/zmodem transfers (CRC errors). + * + * + * Flow control + * ------------ + * + * SniffUSB observations: no flow control specific requests have been realized + * apart from DTR/RTS settings. Both signals are dropped for no flow control + * but asserted for hardware or software flow control. + * + * + * Endpoint usage + * -------------- + * + * SniffUSB observations: the bulk-out endpoint 0x1 and interrupt-in endpoint + * 0x81 is used to transmit and receive characters. The second interrupt-in + * endpoint 0x83 signals exceptional conditions like modem line changes and + * errors. The first byte returned is the MSR and the second byte the LSR. + * + * + * Other observations + * ------------------ + * + * Queued bulk transfers like used in visor.c did not work. + * + * + * Properties of the USB device used (as found in /var/log/messages) + * ----------------------------------------------------------------- + * + * Manufacturer: MCT Corporation. + * Product: USB-232 Interfact Controller + * SerialNumber: U2S22050 + * + * Length = 18 + * DescriptorType = 01 + * USB version = 1.00 + * Vendor:Product = 0711:0210 + * MaxPacketSize0 = 8 + * NumConfigurations = 1 + * Device version = 1.02 + * Device Class:SubClass:Protocol = 00:00:00 + * Per-interface classes + * Configuration: + * bLength = 9 + * bDescriptorType = 02 + * wTotalLength = 0027 + * bNumInterfaces = 01 + * bConfigurationValue = 01 + * iConfiguration = 00 + * bmAttributes = c0 + * MaxPower = 100mA + * + * Interface: 0 + * Alternate Setting: 0 + * bLength = 9 + * bDescriptorType = 04 + * bInterfaceNumber = 00 + * bAlternateSetting = 00 + * bNumEndpoints = 03 + * bInterface Class:SubClass:Protocol = 00:00:00 + * iInterface = 00 + * Endpoint: + * bLength = 7 + * bDescriptorType = 05 + * bEndpointAddress = 81 (in) + * bmAttributes = 03 (Interrupt) + * wMaxPacketSize = 0040 + * bInterval = 02 + * Endpoint: + * bLength = 7 + * bDescriptorType = 05 + * bEndpointAddress = 01 (out) + * bmAttributes = 02 (Bulk) + * wMaxPacketSize = 0040 + * bInterval = 00 + * Endpoint: + * bLength = 7 + * bDescriptorType = 05 + * bEndpointAddress = 83 (in) + * bmAttributes = 03 (Interrupt) + * wMaxPacketSize = 0002 + * bInterval = 02 + */ + +#endif /* __LINUX_USB_SERIAL_MCT_U232_H */ + diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.4.0-test11/linux/drivers/usb/serial/usbserial.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/usbserial.c Fri Dec 1 12:17:24 2000 @@ -15,6 +15,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (12/29/2000) gkh + * Small NULL pointer initialization cleanup which saves a bit of disk image + * * (11/01/2000) Adam J. Richter * instead of using idVendor/idProduct pairs, usb serial drivers * now identify their hardware interest with usb_device_id tables, @@ -346,7 +349,7 @@ static struct tty_struct * serial_tty[SERIAL_TTY_MINORS]; static struct termios * serial_termios[SERIAL_TTY_MINORS]; static struct termios * serial_termios_locked[SERIAL_TTY_MINORS]; -static struct usb_serial *serial_table[SERIAL_TTY_MINORS] = {NULL, }; +static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ LIST_HEAD(usb_serial_driver_list); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.0-test11/linux/drivers/usb/serial/visor.c Sun Nov 19 18:44:16 2000 +++ linux/drivers/usb/serial/visor.c Mon Nov 27 18:10:35 2000 @@ -11,6 +11,10 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (11/12/2000) gkh + * Fixed bug with data being dropped on the floor by forcing tty->low_latency + * to be on. Hopefully this fixes the OHCI issue! + * * (11/01/2000) Adam J. Richter * usb_device_id table support * @@ -171,6 +175,11 @@ bytes_in = 0; bytes_out = 0; + /* force low_latency on so that our tty_push actually forces the data through, + otherwise it is scheduled, and with high data rates (like with OHCI) data + can get lost. */ + port->tty->low_latency = 1; + /* Start reading from the device */ FILL_BULK_URB(port->read_urb, serial->dev, usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), @@ -348,6 +357,11 @@ tty = port->tty; if (urb->actual_length) { for (i = 0; i < urb->actual_length ; ++i) { + /* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* this doesn't actually push the data through unless tty->low_latency is set */ tty_insert_flip_char(tty, data[i], 0); } tty_flip_buffer_push(tty); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/freecom.c linux/drivers/usb/storage/freecom.c --- v2.4.0-test11/linux/drivers/usb/storage/freecom.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/storage/freecom.c Tue Nov 28 21:50:07 2000 @@ -1,6 +1,6 @@ /* Driver for Freecom USB/IDE adaptor * - * $Id: freecom.c,v 1.13 2000/10/03 01:06:07 mdharm Exp $ + * $Id: freecom.c,v 1.14 2000/11/13 22:27:57 mdharm Exp $ * * Freecom v0.1: * @@ -425,7 +425,7 @@ /* Send it out. */ result = usb_stor_bulk_msg (us, fcb, opipe, FCM_PACKET_LENGTH, &partial); - + /* The Freecom device will only fail if there is something * wrong in USB land. It returns the status in its own * registers, which come back in the bulk pipe. @@ -433,13 +433,13 @@ if (result != 0) { US_DEBUGP ("freecom xport failure: r=%d, p=%d\n", result, partial); - + /* -ENOENT -- we canceled this transfer */ if (result == -ENOENT) { US_DEBUGP("freecom_transport(): transfer aborted\n"); return US_BULK_TRANSFER_ABORTED; } - + return USB_STOR_TRANSPORT_ERROR; } @@ -455,7 +455,7 @@ US_DEBUG(pdump ((void *) fst, partial)); } - + if (partial != 4 || result != 0) { return USB_STOR_TRANSPORT_ERROR; } @@ -647,7 +647,7 @@ unsigned char *buffer = (unsigned char *) ibuffer; int i, j; int from, base; - + offset = 0; for (i = 0; i < length; i++) { if ((i & 15) == 0) { @@ -670,17 +670,17 @@ } offset += sprintf (line+offset, " %02x", buffer[i] & 0xff); } - + /* Add the last "chunk" of data. */ from = (length - 1) % 16; base = ((length - 1) / 16) * 16; - + for (i = from + 1; i < 16; i++) offset += sprintf (line+offset, " "); if (from < 8) offset += sprintf (line+offset, " "); offset += sprintf (line+offset, " - "); - + for (i = 0; i <= from; i++) { if (buffer[base+i] >= 32 && buffer[base+i] <= 126) line[offset++] = buffer[base+i]; diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/protocol.c linux/drivers/usb/storage/protocol.c --- v2.4.0-test11/linux/drivers/usb/storage/protocol.c Sun Oct 8 10:50:30 2000 +++ linux/drivers/usb/storage/protocol.c Tue Nov 28 21:50:07 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: protocol.c,v 1.6 2000/09/01 22:03:55 mdharm Exp $ + * $Id: protocol.c,v 1.7 2000/11/13 22:28:33 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -161,7 +161,7 @@ srb->cmnd[0] = srb->cmnd[0] | 0x20; break; } /* end switch on cmnd[0] */ - + /* convert MODE_SELECT data here */ if (old_cmnd == MODE_SELECT) usb_stor_scsiSense6to10(srb); @@ -263,7 +263,7 @@ /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); - + /* Fix the MODE_SENSE data if we translated the command */ if ((old_cmnd == MODE_SENSE) && (status_byte(srb->result) == GOOD)) usb_stor_scsiSense10to6(srb); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c --- v2.4.0-test11/linux/drivers/usb/storage/scsiglue.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/usb/storage/scsiglue.c Tue Nov 28 21:50:07 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * SCSI layer glue code * - * $Id: scsiglue.c,v 1.17 2000/11/02 21:27:49 mdharm Exp $ + * $Id: scsiglue.c,v 1.19 2000/11/13 22:28:55 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -124,7 +124,7 @@ us->action = US_ACT_EXIT; wake_up(&(us->wqh)); down(&(us->notify)); - + /* remove the pointer to the data structure we were using */ (struct us_data*)psh->hostdata[0] = NULL; @@ -261,7 +261,7 @@ US_DEBUGPX("skipping ourselves.\n"); continue; } - + /* simulate a disconnect and reconnect for all interfaces */ US_DEBUGPX("simulating disconnect/reconnect.\n"); down(&intf->driver->serialize); @@ -330,7 +330,7 @@ if (!us) { return -ESRCH; } - + /* print the controler name */ SPRINTF(" Host scsi%d: usb-storage\n", hostno); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/sddr09.c linux/drivers/usb/storage/sddr09.c --- v2.4.0-test11/linux/drivers/usb/storage/sddr09.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/storage/sddr09.c Tue Nov 28 21:50:07 2000 @@ -1,6 +1,6 @@ /* Driver for SanDisk SDDR-09 SmartMedia reader * - * $Id: sddr09.c,v 1.12 2000/10/03 01:06:07 mdharm Exp $ + * $Id: sddr09.c,v 1.14 2000/11/21 02:58:26 mdharm Exp $ * * SDDR09 driver v0.1: * @@ -175,7 +175,7 @@ US_DEBUGP("us_transfer_partial(): unknown error\n"); return US_BULK_TRANSFER_FAILED; } - + if (act_len != len) { US_DEBUGP("Warning: Transferred only %d bytes\n", act_len); @@ -355,10 +355,10 @@ 0, command, 12); - + US_DEBUGP("Result for send_control in read_data %d\n", result); - + if (result != USB_STOR_TRANSPORT_GOOD) { if (use_sg) kfree(buffer); @@ -426,7 +426,7 @@ US_DEBUGP("Result for send_control in read_control %d\n", result); - + if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -461,7 +461,7 @@ US_DEBUGP("Result of send_control for device ID is %d\n", result); - + if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -491,7 +491,7 @@ 0, command, 12); - + if (result != USB_STOR_TRANSPORT_GOOD) return result; @@ -517,7 +517,7 @@ 0, command, 12); - + return result; } @@ -579,6 +579,10 @@ *blocksize = 32; return 0x02000000; + case 0x76: // 64MB + *blocksize = 32; + return 0x04000000; + default: // unknown return 0; @@ -656,7 +660,7 @@ return -1; } - + if (info->lba_to_pba) kfree(info->lba_to_pba); @@ -691,7 +695,7 @@ continue; if ((ptr[6]>>4)!=0x01) continue; - + /* ensure even parity */ lba = short_pack(ptr[7], ptr[6]); @@ -876,7 +880,7 @@ ptr[7] = LSB_of(info->pagesize&0xFFFF); sddr09_read_map(us); - + return USB_STOR_TRANSPORT_GOOD; } @@ -974,7 +978,7 @@ if (srb->request_bufflen == 0) return USB_STOR_TRANSPORT_GOOD; - + if (srb->sc_data_direction == SCSI_DATA_WRITE || srb->sc_data_direction == SCSI_DATA_READ) { diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/shuttle_usbat.c linux/drivers/usb/storage/shuttle_usbat.c --- v2.4.0-test11/linux/drivers/usb/storage/shuttle_usbat.c Sun Oct 8 10:50:30 2000 +++ linux/drivers/usb/storage/shuttle_usbat.c Tue Nov 28 21:50:07 2000 @@ -1,6 +1,6 @@ /* Driver for SCM Microsystems USB-ATAPI cable * - * $Id: shuttle_usbat.c,v 1.10 2000/09/24 00:03:08 groovyjava Exp $ + * $Id: shuttle_usbat.c,v 1.11 2000/11/13 22:29:36 mdharm Exp $ * * Current development and maintenance by: * (c) 2000 Robert Baruch (autophile@dol.net) @@ -169,7 +169,7 @@ US_DEBUGP("us_transfer_partial(): unknown error\n"); return US_BULK_TRANSFER_FAILED; } - + if (act_len != len) { US_DEBUGP("Warning: Transferred only %d bytes\n", act_len); @@ -241,7 +241,7 @@ 0, content, 1); - + return result; } @@ -260,7 +260,7 @@ 0, NULL, 0); - + return result; } @@ -286,7 +286,7 @@ 0, command, 8); - + return result; } @@ -317,7 +317,7 @@ result = usbat_bulk_transport(us, NULL, 0, SCSI_DATA_READ, content, len, use_sg); - + return result; } @@ -605,7 +605,7 @@ 0, data_flags, 1); - + return result; } @@ -623,7 +623,7 @@ 0, NULL, 0); - + return result; } @@ -676,7 +676,7 @@ srb->transfersize = srb->request_bufflen/len; } - + len = (65535/srb->transfersize) * srb->transfersize; US_DEBUGP("Max read is %d bytes\n", len); buffer = kmalloc(len, GFP_KERNEL); @@ -694,7 +694,7 @@ } while (transferred != srb->request_bufflen) { - + if (len > srb->request_bufflen - transferred) len = srb->request_bufflen - transferred; @@ -711,7 +711,7 @@ data[7+6] = 0; data[7+7] = MSB_of(len / srb->transfersize); // SCSI command data[7+8] = LSB_of(len / srb->transfersize); // num sectors - + result = usbat_rw_block_test(us, USBAT_ATA, registers, data, 19, 0x10, 0x17, 0xFD, 0x30, @@ -1048,7 +1048,7 @@ } else len = status; - + result = usbat_read_block(us, USBAT_ATA, 0x10, srb->request_buffer, len, srb->use_sg); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c --- v2.4.0-test11/linux/drivers/usb/storage/transport.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/usb/storage/transport.c Tue Nov 28 21:50:07 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: transport.c,v 1.32 2000/11/03 00:18:04 mdharm Exp $ + * $Id: transport.c,v 1.38 2000/11/21 00:52:10 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -90,9 +90,9 @@ */ static char *lengths = - + /* 0123456789ABCDEF 0123456789ABCDEF */ - + "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */ "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */ "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */ @@ -213,129 +213,129 @@ */ if (srb->sc_data_direction == SCSI_DATA_WRITE) { - doDefault = 1; + doDefault = 1; } else switch (lengths[srb->cmnd[0]]) { - case 'L': - len = srb->cmnd[4]; - break; - - case 'M': - len = srb->cmnd[8]; - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - len = lengths[srb->cmnd[0]]-'0'; - break; - - case 'G': - len = (((unsigned int)srb->cmnd[3])<<8) | - srb->cmnd[4]; - break; - - case 'H': - len = (((unsigned int)srb->cmnd[7])<<8) | - srb->cmnd[8]; - break; - - case 'I': - len = (((unsigned int)srb->cmnd[8])<<8) | - srb->cmnd[9]; - break; - - case 'R': - len = (((unsigned int)srb->cmnd[2])<<16) | - (((unsigned int)srb->cmnd[3])<<8) | - srb->cmnd[4]; - break; - - case 'S': - len = (((unsigned int)srb->cmnd[3])<<16) | - (((unsigned int)srb->cmnd[4])<<8) | - srb->cmnd[5]; - break; - - case 'T': - len = (((unsigned int)srb->cmnd[6])<<16) | - (((unsigned int)srb->cmnd[7])<<8) | - srb->cmnd[8]; - break; - - case 'U': - len = (((unsigned int)srb->cmnd[7])<<16) | - (((unsigned int)srb->cmnd[8])<<8) | - srb->cmnd[9]; - break; - - case 'C': - len = (((unsigned int)srb->cmnd[2])<<24) | - (((unsigned int)srb->cmnd[3])<<16) | - (((unsigned int)srb->cmnd[4])<<8) | - srb->cmnd[5]; - break; - - case 'D': - len = (((unsigned int)srb->cmnd[6])<<24) | - (((unsigned int)srb->cmnd[7])<<16) | - (((unsigned int)srb->cmnd[8])<<8) | - srb->cmnd[9]; - break; - - case 'V': - len = 20; - break; - - case 'W': - len = 24; - break; - - case 'B': - /* Use buffer size due to different block sizes */ - doDefault = 1; - break; - - case 'X': - US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", - srb->cmnd[0]); - doDefault = 1; - break; - - case 'Z': - /* Use buffer size due to mode dependence */ - doDefault = 1; - break; - - default: - US_DEBUGP("Error: COMMAND %02X out of range or table inconsistent (%c).\n", - srb->cmnd[0], lengths[srb->cmnd[0]] ); - doDefault = 1; + case 'L': + len = srb->cmnd[4]; + break; + + case 'M': + len = srb->cmnd[8]; + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + len = lengths[srb->cmnd[0]]-'0'; + break; + + case 'G': + len = (((unsigned int)srb->cmnd[3])<<8) | + srb->cmnd[4]; + break; + + case 'H': + len = (((unsigned int)srb->cmnd[7])<<8) | + srb->cmnd[8]; + break; + + case 'I': + len = (((unsigned int)srb->cmnd[8])<<8) | + srb->cmnd[9]; + break; + + case 'R': + len = (((unsigned int)srb->cmnd[2])<<16) | + (((unsigned int)srb->cmnd[3])<<8) | + srb->cmnd[4]; + break; + + case 'S': + len = (((unsigned int)srb->cmnd[3])<<16) | + (((unsigned int)srb->cmnd[4])<<8) | + srb->cmnd[5]; + break; + + case 'T': + len = (((unsigned int)srb->cmnd[6])<<16) | + (((unsigned int)srb->cmnd[7])<<8) | + srb->cmnd[8]; + break; + + case 'U': + len = (((unsigned int)srb->cmnd[7])<<16) | + (((unsigned int)srb->cmnd[8])<<8) | + srb->cmnd[9]; + break; + + case 'C': + len = (((unsigned int)srb->cmnd[2])<<24) | + (((unsigned int)srb->cmnd[3])<<16) | + (((unsigned int)srb->cmnd[4])<<8) | + srb->cmnd[5]; + break; + + case 'D': + len = (((unsigned int)srb->cmnd[6])<<24) | + (((unsigned int)srb->cmnd[7])<<16) | + (((unsigned int)srb->cmnd[8])<<8) | + srb->cmnd[9]; + break; + + case 'V': + len = 20; + break; + + case 'W': + len = 24; + break; + + case 'B': + /* Use buffer size due to different block sizes */ + doDefault = 1; + break; + + case 'X': + US_DEBUGP("Error: UNSUPPORTED COMMAND %02X\n", + srb->cmnd[0]); + doDefault = 1; + break; + + case 'Z': + /* Use buffer size due to mode dependence */ + doDefault = 1; + break; + + default: + US_DEBUGP("Error: COMMAND %02X out of range or table inconsistent (%c).\n", + srb->cmnd[0], lengths[srb->cmnd[0]] ); + doDefault = 1; } - if ( doDefault == 1 ) { - /* Are we going to scatter gather? */ - if (srb->use_sg) { - /* Add up the sizes of all the sg segments */ - sg = (struct scatterlist *) srb->request_buffer; - for (i = 0; i < srb->use_sg; i++) - total += sg[i].length; - len = total; - } - else - /* Just return the length of the buffer */ - len = srb->request_bufflen; - } + if ( doDefault == 1 ) { + /* Are we going to scatter gather? */ + if (srb->use_sg) { + /* Add up the sizes of all the sg segments */ + sg = (struct scatterlist *) srb->request_buffer; + for (i = 0; i < srb->use_sg; i++) + total += sg[i].length; + len = total; + } + else + /* Just return the length of the buffer */ + len = srb->request_bufflen; + } - return len; +return len; } /* This is a version of usb_clear_halt() that doesn't read the status from @@ -423,7 +423,7 @@ if (status) { /* something went wrong */ up(&(us->current_urb_sem)); - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&wqh, &wait); kfree(dr); return status; @@ -481,7 +481,7 @@ if (status) { /* something went wrong */ up(&(us->current_urb_sem)); - current->state = TASK_RUNNING; + set_current_state(TASK_RUNNING); remove_wait_queue(&wqh, &wait); return status; } @@ -538,7 +538,7 @@ US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe); clear_halt(us->pusb_dev, pipe); } - + /* did we send all the data? */ if (partial == length) { US_DEBUGP("usb_stor_transfer_partial(): transfer complete\n"); @@ -824,24 +824,44 @@ US_DEBUGP("USB IRQ recieved for device on host %d\n", us->host_no); US_DEBUGP("-- IRQ data length is %d\n", urb->actual_length); US_DEBUGP("-- IRQ state is %d\n", urb->status); + US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n", + us->irqbuf[0], us->irqbuf[1]); + + /* reject improper IRQs */ + if (urb->actual_length != 2) { + US_DEBUGP("-- IRQ too short\n"); + return; + } /* is the device removed? */ - if (urb->status != -ENOENT) { - /* save the data for interpretation later */ - US_DEBUGP("-- Interrupt Status (0x%x, 0x%x)\n", - ((unsigned char*)urb->transfer_buffer)[0], - ((unsigned char*)urb->transfer_buffer)[1]); + if (urb->status == -ENOENT) { + US_DEBUGP("-- device has been removed\n"); + return; + } + /* was this a command-completion interrupt? */ + if (us->irqbuf[0] && (us->subclass != US_SC_UFI)) { + US_DEBUGP("-- not a command-completion IRQ\n"); + return; + } - /* was this a wanted interrupt? */ - if (atomic_read(us->ip_wanted)) { - atomic_set(us->ip_wanted, 0); - US_DEBUGP("-- Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count)); - up(&(us->ip_waitq)); - } else - US_DEBUGP("ERROR: Unwanted interrupt received!\n"); - } else - US_DEBUGP("-- device has been removed\n"); + /* was this a wanted interrupt? */ + if (!atomic_read(us->ip_wanted)) { + US_DEBUGP("ERROR: Unwanted interrupt received!\n"); + return; + } + + /* adjust the flag */ + atomic_set(us->ip_wanted, 0); + + /* copy the valid data */ + us->irqdata[0] = us->irqbuf[0]; + us->irqdata[1] = us->irqbuf[1]; + + /* wake up the command thread */ + US_DEBUGP("-- Current value of ip_waitq is: %d\n", + atomic_read(&us->ip_waitq.count)); + up(&(us->ip_waitq)); } int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us) @@ -903,18 +923,17 @@ /* go to sleep until we get this interrupt */ US_DEBUGP("Current value of ip_waitq is: %d\n", atomic_read(&us->ip_waitq.count)); down(&(us->ip_waitq)); - + /* if we were woken up by an abort instead of the actual interrupt */ if (atomic_read(us->ip_wanted)) { US_DEBUGP("Did not get interrupt on CBI\n"); atomic_set(us->ip_wanted, 0); return USB_STOR_TRANSPORT_ABORTED; } - + US_DEBUGP("Got interrupt data (0x%x, 0x%x)\n", - ((unsigned char*)us->irq_urb->transfer_buffer)[0], - ((unsigned char*)us->irq_urb->transfer_buffer)[1]); - + us->irqdata[0], us->irqdata[1]); + /* UFI gives us ASC and ASCQ, like a request sense * * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI @@ -932,22 +951,24 @@ else return USB_STOR_TRANSPORT_GOOD; } - + /* If not UFI, we interpret the data as a result code * The first byte should always be a 0x0 * The second byte & 0x0F should be 0x0 for good, otherwise error */ - if (((unsigned char*)us->irq_urb->transfer_buffer)[0]) { - US_DEBUGP("CBI IRQ data showed reserved bType\n"); + if (us->irqdata[0]) { + US_DEBUGP("CBI IRQ data showed reserved bType %d\n", + us->irqdata[0]); return USB_STOR_TRANSPORT_ERROR; } - switch (((unsigned char*)us->irq_urb->transfer_buffer)[1] & 0x0F) { - case 0x00: - return USB_STOR_TRANSPORT_GOOD; - case 0x01: - return USB_STOR_TRANSPORT_FAILED; - default: - return USB_STOR_TRANSPORT_ERROR; + + switch (us->irqdata[1] & 0x0F) { + case 0x00: + return USB_STOR_TRANSPORT_GOOD; + case 0x01: + return USB_STOR_TRANSPORT_FAILED; + default: + return USB_STOR_TRANSPORT_ERROR; } /* we should never get here, but if we do, we're in trouble */ @@ -1056,7 +1077,7 @@ /* if the device was removed, then we're already reset */ if (!us->pusb_dev) return SUCCESS; - + /* set up the command wrapper */ bcb.Signature = cpu_to_le32(US_BULK_CB_SIGN); bcb.DataTransferLength = cpu_to_le32(usb_stor_transfer_length(srb)); @@ -1066,14 +1087,14 @@ if (us->flags & US_FL_SCM_MULT_TARG) bcb.Lun |= srb->target << 4; bcb.Length = srb->cmd_len; - + /* construct the pipe handle */ pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out); - + /* copy the command payload */ memset(bcb.CDB, 0, sizeof(bcb.CDB)); memcpy(bcb.CDB, srb->cmnd, bcb.Length); - + /* send it to out endpoint */ US_DEBUGP("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n", le32_to_cpu(bcb.Signature), bcb.Tag, @@ -1082,7 +1103,7 @@ result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, &partial); US_DEBUGP("Bulk command transfer result=%d\n", result); - + /* if the command was aborted, indicate that */ if (result == -ENOENT) return USB_STOR_TRANSPORT_ABORTED; @@ -1095,7 +1116,7 @@ /* unknown error -- we've got a problem */ return USB_STOR_TRANSPORT_ERROR; } - + /* if the command transfered well, then we go to the data stage */ if (result == 0) { /* send/receive data payload, if there is any */ @@ -1109,14 +1130,14 @@ return USB_STOR_TRANSPORT_ABORTED; } } - + /* See flow chart on pg 15 of the Bulk Only Transport spec for * an explanation of how this code works. */ - + /* construct the pipe handle */ pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in); - + /* get CSW for device status */ US_DEBUGP("Attempting to get CSW...\n"); result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, @@ -1139,7 +1160,7 @@ /* if the command was aborted, indicate that */ if (result == -ENOENT) return USB_STOR_TRANSPORT_ABORTED; - + /* if it fails again, we need a reset and return an error*/ if (result == -EPIPE) { US_DEBUGP("clearing halt for pipe 0x%x\n", pipe); @@ -1147,13 +1168,13 @@ return USB_STOR_TRANSPORT_ERROR; } } - + /* if we still have a failure at this point, we're in trouble */ US_DEBUGP("Bulk status result = %d\n", result); if (result) { return USB_STOR_TRANSPORT_ERROR; } - + /* check bulk status */ US_DEBUGP("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n", le32_to_cpu(bcs.Signature), bcs.Tag, @@ -1164,24 +1185,24 @@ US_DEBUGP("Bulk logical error\n"); return USB_STOR_TRANSPORT_ERROR; } - + /* based on the status code, we report good or bad */ switch (bcs.Status) { - case US_BULK_STAT_OK: - /* command good -- note that we could be short on data */ - return USB_STOR_TRANSPORT_GOOD; - - case US_BULK_STAT_FAIL: - /* command failed */ - return USB_STOR_TRANSPORT_FAILED; - - case US_BULK_STAT_PHASE: - /* phase error -- note that a transport reset will be - * invoked by the invoke_transport() function - */ - return USB_STOR_TRANSPORT_ERROR; + case US_BULK_STAT_OK: + /* command good -- note that data could be short */ + return USB_STOR_TRANSPORT_GOOD; + + case US_BULK_STAT_FAIL: + /* command failed */ + return USB_STOR_TRANSPORT_FAILED; + + case US_BULK_STAT_PHASE: + /* phase error -- note that a transport reset will be + * invoked by the invoke_transport() function + */ + return USB_STOR_TRANSPORT_ERROR; } - + /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; } diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c --- v2.4.0-test11/linux/drivers/usb/storage/usb.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/usb/storage/usb.c Tue Nov 28 21:50:07 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: usb.c,v 1.54 2000/10/31 21:32:10 mdharm Exp $ + * $Id: usb.c,v 1.57 2000/11/21 02:56:41 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -196,7 +196,7 @@ action = us->action; us->action = 0; us->srb = us->queue_srb; - + /* release the queue lock as fast as possible */ up(&(us->queue_exclusion)); @@ -213,7 +213,7 @@ us->srb = NULL; break; } - + /* reject if target != 0 or if LUN is higher than * the maximum known LUN */ @@ -312,15 +312,15 @@ US_DEBUGP("-- US_ACT_EXIT command recieved\n"); break; } - - set_current_state(TASK_INTERRUPTIBLE); } /* for (;;) */ + /* clean up after ourselves */ + set_current_state(TASK_INTERRUPTIBLE); + remove_wait_queue(&(us->wqh), &wait); + /* notify the exit routine that we're actually exiting now */ up(&(us->notify)); - remove_wait_queue(&(us->wqh), &wait); - return 0; } @@ -489,7 +489,7 @@ US_FL_SINGLE_LUN }, #ifdef CONFIG_USB_STORAGE_SDDR09 - { 0x0781, 0x0200, 0x0100, 0x0100, + { 0x0781, 0x0200, 0x0100, 0x0208, "Sandisk", "ImageMate SDDR-09", US_SC_SCSI, US_PR_EUSB_SDDR09, NULL, @@ -551,7 +551,7 @@ (ptr->bcdDeviceMin <= bcdDevice) && (ptr->bcdDeviceMax >= bcdDevice))) ptr++; - + /* if the search ended because we hit the end record, we failed */ if (ptr->idVendor == 0x0000) { US_DEBUGP("-- did not find a matching device\n"); @@ -577,7 +577,7 @@ int result; US_DEBUGP("Allocating IRQ for CBI transport\n"); - + /* lock access to the data structure */ down(&(ss->irq_urb_sem)); @@ -588,18 +588,18 @@ US_DEBUGP("couldn't allocate interrupt URB"); return 1; } - + /* calculate the pipe and max packet size */ pipe = usb_rcvintpipe(ss->pusb_dev, ss->ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); maxp = usb_maxpacket(ss->pusb_dev, pipe, usb_pipeout(pipe)); if (maxp > sizeof(ss->irqbuf)) maxp = sizeof(ss->irqbuf); - + /* fill in the URB with our data */ FILL_INT_URB(ss->irq_urb, ss->pusb_dev, pipe, ss->irqbuf, maxp, usb_stor_CBI_irq, ss, ss->ep_int->bInterval); - + /* submit the URB for processing */ result = usb_submit_urb(ss->irq_urb); US_DEBUGP("usb_submit_urb() returns %d\n", result); @@ -679,7 +679,7 @@ protocol = altsetting->bInterfaceProtocol; flags = 0; } - + /* * Find the endpoints we need * We are expecting a minimum of 2 endpoints - in and out (bulk). @@ -744,7 +744,7 @@ if (dev->descriptor.iSerialNumber && !(flags & US_FL_IGNORE_SER)) usb_string(dev, dev->descriptor.iSerialNumber, serial, sizeof(serial)); - + /* Create a GUID for this device */ if (dev->descriptor.iSerialNumber && serial[0]) { /* If we have a serial number, and it's a non-NULL string */ @@ -777,7 +777,7 @@ /* establish the connection to the new device upon reconnect */ ss->ifnum = ifnum; ss->pusb_dev = dev; - + /* copy over the endpoint data */ if (ep_in) ss->ep_in = ep_in->bEndpointAddress & @@ -810,7 +810,7 @@ } else { /* New device -- allocate memory and initialize */ US_DEBUGP("New GUID " GUID_FORMAT "\n", GUID_ARGS(guid)); - + if ((ss = (struct us_data *)kmalloc(sizeof(struct us_data), GFP_KERNEL)) == NULL) { printk(KERN_WARNING USB_STORAGE "Out of memory\n"); @@ -879,7 +879,7 @@ /* copy the GUID we created before */ memcpy(ss->guid, guid, sizeof(guid)); - + /* * Set the handler pointers based on the protocol * Again, this data is persistant across reattachments @@ -891,21 +891,21 @@ ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 7; break; - + case US_PR_CBI: ss->transport_name = "Control/Bulk/Interrupt"; ss->transport = usb_stor_CBI_transport; ss->transport_reset = usb_stor_CB_reset; ss->max_lun = 7; break; - + case US_PR_BULK: ss->transport_name = "Bulk"; ss->transport = usb_stor_Bulk_transport; ss->transport_reset = usb_stor_Bulk_reset; ss->max_lun = usb_stor_Bulk_max_lun(ss); break; - + #ifdef CONFIG_USB_STORAGE_HP8200e case US_PR_SCM_ATAPI: ss->transport_name = "SCM/ATAPI"; @@ -941,7 +941,7 @@ ss->max_lun = 0; break; #endif - + default: ss->transport_name = "Unknown"; kfree(ss->current_urb); @@ -1004,7 +1004,7 @@ usb_dec_dev_use(dev); return NULL; } - + /* * Since this is a new device, we need to generate a scsi * host definition, and register with the higher SCSI layers @@ -1016,7 +1016,7 @@ /* Grab the next host number */ ss->host_number = my_host_number++; - + /* We abuse this pointer so we can pass the ss pointer to * the host controler thread in us_detect. But how else are * we to do it? @@ -1027,7 +1027,7 @@ * the device if it needs initialization */ if (unusual_dev && unusual_dev->initFunction) unusual_dev->initFunction(ss); - + /* start up our control thread */ ss->pid = kernel_thread(usb_stor_control_thread, ss, CLONE_VM); @@ -1039,14 +1039,14 @@ usb_dec_dev_use(dev); return NULL; } - + /* wait for the thread to start */ down(&(ss->notify)); - + /* now register - our detect function will be called */ ss->htmplt.module = THIS_MODULE; scsi_register_module(MODULE_SCSI_HA, &(ss->htmplt)); - + /* lock access to the data structures */ down(&us_list_semaphore); @@ -1133,7 +1133,7 @@ void __exit usb_stor_exit(void) { struct us_data *next; - + US_DEBUGP("usb_stor_exit() called\n"); /* Deregister the driver @@ -1141,7 +1141,7 @@ */ US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; - + /* While there are still virtual hosts, unregister them * Note that it's important to do this completely before removing * the structures because of possible races with the /proc @@ -1151,7 +1151,7 @@ US_DEBUGP("-- calling scsi_unregister_module()\n"); scsi_unregister_module(MODULE_SCSI_HA, &(next->htmplt)); } - + /* While there are still structures, free them. Note that we are * now race-free, since these structures can no longer be accessed * from either the SCSI command layer or the /proc interface diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/storage/usb.h linux/drivers/usb/storage/usb.h --- v2.4.0-test11/linux/drivers/usb/storage/usb.h Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/storage/usb.h Mon Dec 11 16:27:57 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * Main Header File * - * $Id: usb.h,v 1.10 2000/10/19 18:44:11 mdharm Exp $ + * $Id: usb.h,v 1.11 2000/11/13 22:38:55 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -152,7 +152,7 @@ int host_number; /* to find us */ int host_no; /* allocated by scsi */ Scsi_Cmnd *srb; /* current srb */ - + /* thread information */ Scsi_Cmnd *queue_srb; /* the single queue slot */ int action; /* what to do */ @@ -166,6 +166,7 @@ struct semaphore irq_urb_sem; /* to protect irq_urb */ struct urb *irq_urb; /* for USB int requests */ unsigned char irqbuf[2]; /* buffer for USB IRQ */ + unsigned char irqdata[2]; /* data from USB IRQ */ /* control and bulk communications data */ struct semaphore current_urb_sem; /* to protect irq_urb */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c --- v2.4.0-test11/linux/drivers/usb/uhci.c Sun Oct 8 10:50:31 2000 +++ linux/drivers/usb/uhci.c Thu Dec 7 16:42:28 2000 @@ -2,12 +2,16 @@ * Universal Host Controller Interface driver for USB. * * (C) Copyright 1999 Linus Torvalds - * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@sventech.com + * (C) Copyright 1999-2000 Johannes Erdfelt, johannes@erdfelt.com * (C) Copyright 1999 Randy Dunlap * (C) Copyright 1999 Georg Acher, acher@in.tum.de * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at + * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface + * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) + * * * Intel documents this fairly well, and as far as I know there * are no royalties or anything like that, but even so there are @@ -21,6 +25,7 @@ * - working around the horridness of the rest */ +#include #include #include #include @@ -46,7 +51,6 @@ #include "uhci-debug.h" #include -static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data); static int debug = 1; MODULE_PARM(debug, "i"); @@ -56,8 +60,6 @@ static kmem_cache_t *uhci_qh_cachep; static kmem_cache_t *uhci_up_cachep; /* urb_priv */ -static LIST_HEAD(uhci_list); - static int rh_submit_urb(struct urb *urb); static int rh_unlink_urb(struct urb *urb); static int uhci_get_current_frame_number(struct usb_device *dev); @@ -1753,11 +1755,11 @@ urbp = (struct urb_priv *)u->hcpriv; if (urbp) { /* Check if the FSBR timed out */ - if (urbp->fsbr && time_after(urbp->inserttime + IDLE_TIMEOUT, jiffies)) + if (urbp->fsbr && time_after_eq(jiffies, urbp->inserttime + IDLE_TIMEOUT)) uhci_fsbr_timeout(uhci, u); /* Check if the URB timed out */ - if (u->timeout && time_after(u->timeout, jiffies)) { + if (u->timeout && time_after_eq(jiffies, u->timeout)) { u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED; uhci_unlink_urb(u); } @@ -2343,9 +2345,7 @@ uhci = alloc_uhci(io_addr, io_size); if (!uhci) return -ENOMEM; - - INIT_LIST_HEAD(&uhci->uhci_list); - list_add(&uhci->uhci_list, &uhci_list); + dev->driver_data = uhci; request_region(uhci->io_addr, io_size, "usb-uhci"); @@ -2358,21 +2358,13 @@ if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci) == 0) { uhci->irq = irq; - if (!uhci_start_root_hub(uhci)) { - struct pm_dev *pmdev; + pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); - pmdev = pm_register(PM_PCI_DEV, - PM_PCI_ID(dev), - handle_pm_event); - if (pmdev) - pmdev->data = uhci; + if (!uhci_start_root_hub(uhci)) return 0; - } } /* Couldn't allocate IRQ if we got here */ - list_del(&uhci->uhci_list); - INIT_LIST_HEAD(&uhci->uhci_list); reset_hc(uhci); release_region(uhci->io_addr, uhci->io_size); @@ -2381,19 +2373,19 @@ return retval; } -static int found_uhci(struct pci_dev *dev) +static int __devinit uhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) { int i; /* disable legacy emulation */ - pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT); + pci_write_config_word(dev, USBLEGSUP, 0); if (pci_enable_device(dev) < 0) - return -1; + return -ENODEV; if (!dev->irq) { err("found UHCI device with no IRQ assigned. check BIOS settings!"); - return -1; + return -ENODEV; } /* Search for the IO base address.. */ @@ -2409,32 +2401,77 @@ if (check_region(io_addr, io_size)) break; + pci_set_master(dev); return setup_uhci(dev, dev->irq, io_addr, io_size); } - return -1; + return -ENODEV; } -static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data) +static void __devexit uhci_pci_remove(struct pci_dev *dev) { - struct uhci *uhci = dev->data; - switch (rqst) { - case PM_SUSPEND: - reset_hc(uhci); - break; - case PM_RESUME: - reset_hc(uhci); - start_hc(uhci); - break; - } - return 0; + struct uhci *uhci = dev->driver_data; + + if (uhci->bus->root_hub) + usb_disconnect(&uhci->bus->root_hub); + + usb_deregister_bus(uhci->bus); + + reset_hc(uhci); + release_region(uhci->io_addr, uhci->io_size); + + uhci_free_pending_qhs(uhci); + + release_uhci(uhci); } -static int __init uhci_init(void) +static void uhci_pci_suspend(struct pci_dev *dev) +{ + reset_hc((struct uhci *) dev->driver_data); +} + +static void uhci_pci_resume(struct pci_dev *dev) +{ + reset_hc((struct uhci *) dev->driver_data); + start_hc((struct uhci *) dev->driver_data); +} + +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata uhci_pci_ids [] = { { + + /* handle any USB UHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), + class_mask: ~0, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE (pci, uhci_pci_ids); + +static struct pci_driver uhci_pci_driver = { + name: "usb-uhci", + id_table: &uhci_pci_ids [0], + + probe: uhci_pci_probe, + remove: uhci_pci_remove, + +#ifdef CONFIG_PM + suspend: uhci_pci_suspend, + resume: uhci_pci_resume, +#endif /* PM */ +}; + + +static int __init uhci_hcd_init(void) { int retval; - struct pci_dev *dev; - u8 type; retval = -ENOMEM; @@ -2461,25 +2498,8 @@ if (!uhci_up_cachep) goto up_failed; - retval = -ENODEV; - dev = NULL; - for (;;) { - dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev); - if (!dev) - break; - - /* Is it the UHCI programming interface? */ - pci_read_config_byte(dev, PCI_CLASS_PROG, &type); - if (type != 0) - continue; - - /* Ok set it up */ - retval = found_uhci(dev); - } - - /* We only want to return an error code if ther was an error */ - /* and we didn't find a UHCI controller */ - if (retval && list_empty(&uhci_list)) + retval = pci_module_init (&uhci_pci_driver); + if (retval) goto init_failed; return 0; @@ -2500,32 +2520,10 @@ return retval; } -void uhci_cleanup(void) +static void __exit uhci_hcd_cleanup (void) { - struct list_head *tmp, *head = &uhci_list; - - tmp = head->next; - while (tmp != head) { - struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list); - - tmp = tmp->next; - - list_del(&uhci->uhci_list); - INIT_LIST_HEAD(&uhci->uhci_list); - - if (uhci->bus->root_hub) - usb_disconnect(&uhci->bus->root_hub); - - usb_deregister_bus(uhci->bus); - - reset_hc(uhci); - release_region(uhci->io_addr, uhci->io_size); - - uhci_free_pending_qhs(uhci); - - release_uhci(uhci); - } - + pci_unregister_driver (&uhci_pci_driver); + if (kmem_cache_destroy(uhci_up_cachep)) printk(KERN_INFO "uhci: not all urb_priv's were freed\n"); @@ -2536,14 +2534,8 @@ printk(KERN_INFO "uhci: not all TD's were freed\n"); } -static void __exit uhci_exit(void) -{ - pm_unregister_all(handle_pm_event); - uhci_cleanup(); -} - -module_init(uhci_init); -module_exit(uhci_exit); +module_init(uhci_hcd_init); +module_exit(uhci_hcd_cleanup); MODULE_AUTHOR("Linus Torvalds, Johannes Erdfelt, Randy Dunlap, Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"); MODULE_DESCRIPTION("USB Universal Host Controller Interface driver"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c --- v2.4.0-test11/linux/drivers/usb/usb-uhci.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/usb-uhci.c Sat Dec 9 10:14:11 2000 @@ -5,14 +5,18 @@ * Deti Fliegl, deti@fliegl.de (executive slave) (lead voice) * Thomas Sailer, sailer@ife.ee.ethz.ch (chief consultant) (cheer leader) * Roman Weissgaerber, weissg@vienna.at (virt root hub) (studio porter) + * (c) 2000 Yggdrasil Computing, Inc. (port of new PCI interface support + * from usb-ohci.c by Adam Richter, adam@yggdrasil.com). + * (C) 2000 David Brownell, david-b@pacbell.net (usb-ohci.c) * * HW-initalization based on material of * * (C) Copyright 1999 Linus Torvalds * (C) Copyright 1999 Johannes Erdfelt * (C) Copyright 1999 Randy Dunlap + * (C) Copyright 1999 Gregory P. Smith * - * $Id: usb-uhci.c,v 1.242 2000/10/05 21:19:49 acher Exp $ + * $Id: usb-uhci.c,v 1.251 2000/11/30 09:47:54 acher Exp $ */ #include @@ -48,7 +52,7 @@ /* This enables an extra UHCI slab for memory debugging */ #define DEBUG_SLAB -#define VERSTR "$Revision: 1.242 $ time " __TIME__ " " __DATE__ +#define VERSTR "$Revision: 1.251 $ time " __TIME__ " " __DATE__ #include #include "usb-uhci.h" @@ -92,27 +96,31 @@ _static int process_interrupt (uhci_t *s, urb_t *urb); _static int process_iso (uhci_t *s, urb_t *urb, int force); +// How much URBs with ->next are walked +#define MAX_NEXT_COUNT 2048 + static uhci_t *devs = NULL; /* used by userspace UHCI data structure dumper */ uhci_t **uhci_devices = &devs; /*-------------------------------------------------------------------*/ -// Cleans up collected QHs +// Cleans up collected QHs, but not more than 100 in one go void clean_descs(uhci_t *s, int force) { struct list_head *q; uhci_desc_t *qh; - int now=UHCI_GET_CURRENT_FRAME(s); + int now=UHCI_GET_CURRENT_FRAME(s), n=0; q=s->free_desc.prev; - while (q != &s->free_desc) { - qh = list_entry (q, uhci_desc_t, horizontal); + while (q != &s->free_desc && (force || n<100)) { + qh = list_entry (q, uhci_desc_t, horizontal); q=qh->horizontal.prev; if ((qh->last_used!=now) || force) delete_qh(s,qh); + n++; } } /*-------------------------------------------------------------------*/ @@ -264,7 +272,7 @@ if (qh == prev ) { // virgin qh without any tds - qh->hw.qh.element = virt_to_bus (new); + qh->hw.qh.element = virt_to_bus (new) | UHCI_PTR_TERM; } else { // already tds inserted, implicitely remove TERM bit of prev @@ -409,6 +417,9 @@ prev = list_entry (element->horizontal.prev, uhci_desc_t, horizontal); prev->hw.qh.head = element->hw.qh.head; + dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, + list_entry (element->horizontal.next, uhci_desc_t, horizontal),element->hw.qh.head &~15); + list_del(&element->horizontal); mb (); @@ -571,6 +582,7 @@ fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand) insert_td (s, qh, td, 0); + qh->hw.qh.element &= ~UHCI_PTR_TERM; // remove TERM bit s->td1ms=td; dbg("allocating qh: bulk_chain"); @@ -791,14 +803,14 @@ { uhci_t *s = (uhci_t*) urb->dev->bus->hcpriv; urb_priv_t *urb_priv = urb->hcpriv; - uhci_desc_t *qh, *td, *nqh, *bqh; + uhci_desc_t *qh, *td, *nqh, *bqh, *first_td=NULL; unsigned long destination, status; char *data; unsigned int pipe = urb->pipe; int maxsze = usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)); int info, len, last; int depth_first=USE_BULK_DEPTH_FIRST; // UHCI descriptor chasing method - urb_priv_t *upriv, *bpriv; + urb_priv_t *upriv, *bpriv=NULL; if (usb_endpoint_halted (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) return -EPIPE; @@ -814,7 +826,7 @@ queue_dbg("uhci_submit_bulk_urb: urb %p, old %p, pipe %08x, len %i", urb,bulk_urb,urb->pipe,urb->transfer_buffer_length); - upriv=(urb_priv_t*)urb->hcpriv; + upriv = (urb_priv_t*)urb->hcpriv; if (!bulk_urb) { alloc_qh (&qh); // get qh for this request @@ -836,13 +848,10 @@ bpriv = (urb_priv_t*)bulk_urb->hcpriv; qh = bpriv->bottom_qh; // re-use bottom qh and next qh nqh = bpriv->next_qh; - upriv->next_qh=nqh; - bpriv->next_queued_urb=urb; + upriv->next_qh=nqh; upriv->prev_queued_urb=bulk_urb; } - queue_dbg("uhci_submit_bulk: qh=%p, nqh=%p\n",bqh,nqh); - if (urb->transfer_flags & USB_QUEUE_BULK) { alloc_qh (&bqh); // "bottom" QH, @@ -854,11 +863,10 @@ return -ENOMEM; } bqh->hw.qh.element = UHCI_PTR_TERM; - bqh->hw.qh.element = virt_to_bus(nqh)|UHCI_PTR_QH; + bqh->hw.qh.head = virt_to_bus(nqh) | UHCI_PTR_QH; // element upriv->bottom_qh = bqh; - queue_dbg("uhci_submit_bulk: new bqh %p\n",bqh); } - + queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh); /* The "pipe" thing contains the destination in bits 8--18. */ destination = (pipe & PIPE_DEVEP_MASK) | usb_packetid (pipe); @@ -899,25 +907,31 @@ td->hw.td.status |= TD_CTRL_IOC; // last one generates INT insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first); + if (!first_td) + first_td=td; usb_dotoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)); } while (!last); + if (bulk_urb && bpriv) // everything went OK, link with old bulk URB + bpriv->next_queued_urb=urb; + list_add (&qh->desc_list, &urb_priv->desc_list); - if (urb->transfer_flags & USB_QUEUE_BULK) { - qh->hw.qh.element&=~UHCI_PTR_TERM; + if (urb->transfer_flags & USB_QUEUE_BULK) append_qh(s, td, bqh, UHCI_PTR_DEPTH * depth_first); - } urb->status = -EINPROGRESS; queue_urb_unlocked (s, urb); - qh->hw.qh.element &= ~UHCI_PTR_TERM; + if (urb->transfer_flags & USB_QUEUE_BULK) + qh->hw.qh.element = virt_to_bus (first_td); + else + qh->hw.qh.element &= ~UHCI_PTR_TERM; // arm QH - if (!bulk_urb) { + if (!bulk_urb) { // new bulk queue if (urb->transfer_flags & USB_QUEUE_BULK) { - spin_lock (&s->td_lock); // both QHs in one go + spin_lock (&s->td_lock); // both QHs in one go insert_qh (s, s->chain_end, qh, 0); // Main QH insert_qh (s, s->chain_end, nqh, 0); // Helper QH spin_unlock (&s->td_lock); @@ -954,83 +968,102 @@ } } /*-------------------------------------------------------------------*/ -// mode: 0: unlink + no deletion mark, 1: regular (unlink/delete-mark), 2: don't unlink +// mode: 0: unlink but no deletion mark (step 1 of async_unlink) +// 1: regular (unlink/delete-mark) +// 2: deletion mark for QH (step 2 of async_unlink) // looks a bit complicated because of all the bulk queueing goodies _static void uhci_clean_transfer (uhci_t *s, urb_t *urb, uhci_desc_t *qh, int mode) { - uhci_desc_t *bqh, *nqh, *prevqh; + uhci_desc_t *bqh, *nqh, *prevqh, *prevtd; int now; urb_priv_t *priv=(urb_priv_t*)urb->hcpriv; now=UHCI_GET_CURRENT_FRAME(s); - dbg("clean transfer urb %p, qh %p, mode %i",urb,qh,mode); bqh=priv->bottom_qh; - + if (!priv->next_queued_urb) { // no more appended bulk queues - if (mode != 2) - unlink_qh (s, qh); + queue_dbg("uhci_clean_transfer: No more bulks for urb %p, qh %p, bqh %p, nqh %p",urb, qh, bqh, priv->next_qh); - if (priv->prev_queued_urb) { + if (priv->prev_queued_urb) { // qh not top of the queue urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; - ppriv->bottom_qh = priv->bottom_qh; - ppriv->next_queued_urb = NULL; + if (mode != 2) { + unsigned long flags; + + spin_lock_irqsave (&s->qh_lock, flags); + prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); + prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical); + prevtd->hw.td.link = virt_to_bus(priv->bottom_qh) | UHCI_PTR_QH; // skip current qh + mb(); + queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd); + spin_unlock_irqrestore (&s->qh_lock, flags); + + ppriv->bottom_qh = priv->bottom_qh; + ppriv->next_queued_urb = NULL; + } } - else if (bqh) { // queue dead - nqh=priv->next_qh; + else { // queue is dead, qh is top of the queue - if (mode != 2) - unlink_qh(s, nqh); + if (mode!=2) + unlink_qh(s, qh); // remove qh from horizontal chain + + if (bqh) { // remove remainings of bulk queue + nqh=priv->next_qh; - if (mode) { - nqh->last_used = bqh->last_used = now; - list_add_tail (&nqh->horizontal, &s->free_desc); - list_add_tail (&bqh->horizontal, &s->free_desc); - } + if (mode != 2) + unlink_qh(s, nqh); // remove nqh from horizontal chain + + if (mode) { + nqh->last_used = bqh->last_used = now; + list_add_tail (&nqh->horizontal, &s->free_desc); + list_add_tail (&bqh->horizontal, &s->free_desc); + } + } } } else { // there are queued urbs following - urb_t *nurb; - unsigned long flags; - - nurb=priv->next_queued_urb; - spin_lock_irqsave (&s->qh_lock, flags); - - if (!priv->prev_queued_urb) { // top - if (mode !=2) { + + queue_dbg("uhci_clean_transfer: urb %p, prevurb %p, nexturb %p, qh %p, bqh %p, nqh %p", + urb, priv->prev_queued_urb, priv->next_queued_urb, qh, bqh, priv->next_qh); + + if (mode !=2) { // no work for cleanup at unlink-completion + urb_t *nurb; + unsigned long flags; + + nurb = priv->next_queued_urb; + spin_lock_irqsave (&s->qh_lock, flags); + + if (!priv->prev_queued_urb) { // top QH + prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal); prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH; - queue_dbg ("TOP relink of %p to %p-%p",qh,prevqh,bqh); - - list_del (&qh->horizontal); - list_add (&bqh->horizontal, &prevqh->horizontal); - } - } - else { //intermediate - urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; - uhci_desc_t * bnqh; - - bnqh=list_entry (&((urb_priv_t*)(nurb->hcpriv))->desc_list.next, uhci_desc_t, desc_list); - ppriv->bottom_qh=bnqh; - ppriv->next_queued_urb=nurb; - - if (mode!=2) { + list_del (&qh->horizontal); // remove this qh form horizontal chain + list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain + } + else { // intermediate QH + urb_priv_t* ppriv=(urb_priv_t*)priv->prev_queued_urb->hcpriv; + urb_priv_t* npriv=(urb_priv_t*)nurb->hcpriv; + uhci_desc_t * bnqh; + + bnqh = list_entry (npriv->desc_list.next, uhci_desc_t, desc_list); + ppriv->bottom_qh = bnqh; + ppriv->next_queued_urb = nurb; prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list); prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH; - queue_dbg ("IM relink of %p to %p-%p",qh,prevqh,bqh); } - } - mb(); - spin_unlock_irqrestore (&s->qh_lock, flags); - ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb; + + mb(); + spin_unlock_irqrestore (&s->qh_lock, flags); + ((urb_priv_t*)nurb->hcpriv)->prev_queued_urb=priv->prev_queued_urb; + } } if (mode) { - qh->last_used = now; - list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion + qh->last_used = now; + list_add_tail (&qh->horizontal, &s->free_desc); // mark for later deletion/kfree } } /*-------------------------------------------------------------------*/ @@ -1070,13 +1103,14 @@ uhci_switch_timer_int(s); s->unlink_urb_done=1; + uhci_release_bandwidth(urb); + urb->status = -ENOENT; // mark urb as killed + if (!in_interrupt()) spin_unlock(&urb->lock); - uhci_release_bandwidth(urb); spin_unlock_irqrestore (&s->urb_list_lock, flags); - urb->status = -ENOENT; // mark urb as killed urb_priv = urb->hcpriv; switch (usb_pipetype (urb->pipe)) { @@ -1092,8 +1126,8 @@ case PIPE_BULK: case PIPE_CONTROL: - qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); spin_lock_irqsave (&s->urb_list_lock, flags); + qh = list_entry (urb_priv->desc_list.next, uhci_desc_t, desc_list); uhci_clean_transfer(s, urb, qh, 1); spin_unlock_irqrestore (&s->urb_list_lock, flags); uhci_wait_ms(1); @@ -1149,7 +1183,7 @@ async_dbg("async cleanup %p",urb); switch (usb_pipetype (urb->pipe)) { // process descriptors case PIPE_CONTROL: - process_transfer (s, urb, 2); + process_transfer (s, urb, 2); // 2: don't unlink (already done) break; case PIPE_BULK: if (!s->avoid_bulk.counter) @@ -1201,6 +1235,7 @@ } /*-------------------------------------------------------------------*/ +// needs urb_list_lock! _static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb) { uhci_desc_t *qh; @@ -1570,7 +1605,7 @@ urb_priv_t *urb_priv; int ret = 0; unsigned long flags; - urb_t *bulk_urb=NULL; + urb_t *queued_urb=NULL; int bustime; if (!urb->dev || !urb->dev->bus) @@ -1589,18 +1624,18 @@ spin_lock_irqsave (&s->urb_list_lock, flags); - bulk_urb = search_dev_ep (s, urb); + queued_urb = search_dev_ep (s, urb); // returns already queued urb for that pipe - if (bulk_urb) { + if (queued_urb) { - queue_dbg("found bulk urb %p\n",bulk_urb); + queue_dbg("found bulk urb %p\n", queued_urb); if ((usb_pipetype (urb->pipe) != PIPE_BULK) || ((usb_pipetype (urb->pipe) == PIPE_BULK) && - (!(urb->transfer_flags & USB_QUEUE_BULK) || !(bulk_urb->transfer_flags & USB_QUEUE_BULK)))) { + (!(urb->transfer_flags & USB_QUEUE_BULK) || !(queued_urb->transfer_flags & USB_QUEUE_BULK)))) { spin_unlock_irqrestore (&s->urb_list_lock, flags); usb_dec_dev_use (urb->dev); - err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,bulk_urb); + err("ENXIO %08x, flags %x, urb %p, burb %p",urb->pipe,urb->transfer_flags,urb,queued_urb); return -ENXIO; // urb already queued } } @@ -1627,14 +1662,14 @@ if (usb_pipetype (urb->pipe) == PIPE_BULK) { - if (bulk_urb) { - while (((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb) // find last queued bulk - bulk_urb=((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb; + if (queued_urb) { + while (((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb) // find last queued bulk + queued_urb=((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb; - ((urb_priv_t*)bulk_urb->hcpriv)->next_queued_urb=urb; + ((urb_priv_t*)queued_urb->hcpriv)->next_queued_urb=urb; } atomic_inc (&s->avoid_bulk); - ret = uhci_submit_bulk_urb (urb, bulk_urb); + ret = uhci_submit_bulk_urb (urb, queued_urb); atomic_dec (&s->avoid_bulk); spin_unlock_irqrestore (&s->urb_list_lock, flags); } @@ -2214,7 +2249,7 @@ * have announced. This leads to a queue abort due to the short packet, * the status stage is not executed. If this happens, the status stage * is manually re-executed. - * mode: 0: QHs already unlinked + * mode: 1: regular (unlink QH), 2: QHs already unlinked (for async unlink_urb) */ _static int process_transfer (uhci_t *s, urb_t *urb, int mode) @@ -2231,7 +2266,7 @@ int actual_length; int status = 0; - //dbg("process_transfer: urb contains bulk/control request"); + //dbg("process_transfer: urb %p, urb_priv %p, qh %p last_desc %p\n",urb,urb_priv, qh, last_desc); /* if the status phase has been retriggered and the queue is empty or the last status-TD is inactive, the retriggered @@ -2305,7 +2340,7 @@ transfer_finished: - uhci_clean_transfer(s, urb, qh, (mode==0?2:1)); + uhci_clean_transfer(s, urb, qh, mode); urb->status = status; @@ -2511,7 +2546,6 @@ } if (urb->status != -EINPROGRESS) { - int proceed = 0; struct usb_device *usb_dev; usb_dev=urb->dev; @@ -2533,64 +2567,77 @@ kfree (urb->hcpriv); #endif - if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) { - urb_t *tmp = urb->next; // pointer to first urb + if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) { // process_interrupt does completion on its own + urb_t *next_urb = urb->next; int is_ring = 0; + int contains_killed = 0; + int loop_count=0; - if (urb->next) { - do { - if (tmp->status != -EINPROGRESS) { - proceed = 1; + if (next_urb) { + // Find out if the URBs are linked to a ring + while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) { + if (next_urb->status == -ENOENT) {// killed URBs break ring structure & resubmission + contains_killed = 1; break; - } - tmp = tmp->next; + } + next_urb = next_urb->next; + loop_count++; } - while (tmp != NULL && tmp != urb->next); - if (tmp == urb->next) - is_ring = 1; - } + + if (loop_count == MAX_NEXT_COUNT) + err("process_urb: Too much linked URBs in ring detection!"); + if (next_urb == urb) + is_ring=1; + } + spin_lock(&urb->lock); - spin_unlock(&s->urb_list_lock); - // In case you need the current URB status for your completion handler (before resubmit) - if (urb->complete && (!proceed )) { - dbg("process_transfer: calling early completion"); + // Submit idle/non-killed URBs linked with urb->next + // Stop before the current URB + + next_urb = urb->next; + if (next_urb && !contains_killed) { + int ret_submit; + next_urb = urb->next; + + loop_count=0; + while (next_urb != NULL && next_urb != urb && loop_count < MAX_NEXT_COUNT) { + if (next_urb->status != -EINPROGRESS) { + + if (next_urb->status == -ENOENT) + break; + + spin_unlock(&s->urb_list_lock); + + ret_submit=uhci_submit_urb(next_urb); + spin_lock(&s->urb_list_lock); + + if (ret_submit) + break; + } + loop_count++; + next_urb = next_urb->next; + } + if (loop_count == MAX_NEXT_COUNT) + err("process_urb: Too much linked URBs in resubmission!"); + } + + // Completion + if (urb->complete) { urb->dev = NULL; + spin_unlock(&s->urb_list_lock); urb->complete ((struct urb *) urb); - if (!proceed && is_ring && (urb->status != -ENOENT)) { + // Re-submit the URB if ring-linked + if (is_ring && (urb->status != -ENOENT) && !contains_killed) { urb->dev=usb_dev; uhci_submit_urb (urb); } - } - else if (!urb->complete) - urb->dev = NULL; - - if (proceed && urb->next) { - // if there are linked urbs - handle submitting of them right now. - tmp = urb->next; // pointer to first urb - - do { - if ((tmp->status != -EINPROGRESS) && (tmp->status != -ENOENT) && uhci_submit_urb (tmp) != 0) - break; - tmp = tmp->next; - } - while (tmp != NULL && tmp != urb->next); // submit until we reach NULL or our own pointer or submit fails - - if (urb->complete) { - dbg("process_transfer: calling completion"); - if (urb->status!=-EINPROGRESS) - urb->dev=NULL; - urb->complete ((struct urb *) urb); - } - else - if (urb->status!=-EINPROGRESS) - urb->dev=NULL; + spin_lock(&s->urb_list_lock); } usb_dec_dev_use (usb_dev); spin_unlock(&urb->lock); - spin_lock(&s->urb_list_lock); } } @@ -2603,7 +2650,8 @@ unsigned int io_addr = s->io_addr; unsigned short status; struct list_head *p, *p2; - + int restarts, work_done; + /* * Read the interrupt status, and write it back to clear the * interrupt cause @@ -2631,20 +2679,34 @@ * may be added at the end. * also, because process_urb may unlink the current urb, * we need to advance the list before + * New: check for max. workload and restart count */ spin_lock (&s->urb_list_lock); + + restarts=0; + work_done=0; + restart: s->unlink_urb_done=0; p = s->urb_list.prev; - while (p != &s->urb_list) { + while (p != &s->urb_list && (work_done < 1024)) { p2 = p; p = p->prev; + process_urb (s, p2); + + work_done++; + if (s->unlink_urb_done) { s->unlink_urb_done=0; - goto restart; + restarts++; + + if (restarts<16) // avoid endless restarts + goto restart; + else + break; } } if ((jiffies - s->timeout_check) > (HZ/30)) @@ -2706,8 +2768,10 @@ s->running = 1; } -_static void uhci_cleanup_dev(uhci_t *s) +_static void __devexit +uhci_pci_remove (struct pci_dev *dev) { + uhci_t *s = (uhci_t*) dev->driver_data; struct usb_device *root_hub = s->bus->root_hub; s->running = 0; // Don't allow submit_urb @@ -2750,28 +2814,23 @@ return 0; } -_static int handle_pm_event (struct pm_dev *dev, pm_request_t rqst, void *data) +_static void +uhci_pci_suspend (struct pci_dev *dev) { - uhci_t *s = (uhci_t*) dev->data; - dbg("handle_apm_event(%d)", rqst); - if (s) { - switch (rqst) { - case PM_SUSPEND: - reset_hc (s); - break; - case PM_RESUME: - start_hc (s); - break; - } - } - return 0; + reset_hc((uhci_t *) dev->driver_data); } -_static int __init alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size) +_static void +uhci_pci_resume (struct pci_dev *dev) +{ + start_hc((uhci_t *) dev->driver_data); +} + + +_static int __devinit alloc_uhci (struct pci_dev *dev, int irq, unsigned int io_addr, unsigned int io_size) { uhci_t *s; struct usb_bus *bus; - struct pm_dev *pmdev; char buf[8], *bufp = buf; #ifndef __sparc__ @@ -2798,7 +2857,6 @@ s->irq = -1; s->io_addr = io_addr; s->io_size = io_size; - s->next = devs; //chain new uhci device into global list s->timeout_check = 0; s->uhci_pci=dev; @@ -2859,53 +2917,90 @@ return -1; } + /* Enable PIRQ */ + pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); + s->irq = irq; if(uhci_start_usb (s) < 0) { - uhci_cleanup_dev(s); + uhci_pci_remove(dev); return -1; } //chain new uhci device into global list - devs = s; - - pmdev = pm_register(PM_PCI_DEV, PM_PCI_ID(dev), handle_pm_event); - if (pmdev) - pmdev->data = s; + dev->driver_data = s; + devs=s; return 0; } -_static int __init start_uhci (struct pci_dev *dev) +_static int __devinit +uhci_pci_probe (struct pci_dev *dev, const struct pci_device_id *id) { int i; + if (pci_enable_device(dev) < 0) + return -ENODEV; + /* Search for the IO base address.. */ for (i = 0; i < 6; i++) { unsigned int io_addr = dev->resource[i].start; unsigned int io_size = dev->resource[i].end - dev->resource[i].start + 1; - if (!(dev->resource[i].flags & 1)) + if (!(dev->resource[i].flags & IORESOURCE_IO)) continue; /* Is it already in use? */ if (check_region (io_addr, io_size)) break; /* disable legacy emulation */ - pci_write_config_word (dev, USBLEGSUP, USBLEGSUP_DEFAULT); - + pci_write_config_word (dev, USBLEGSUP, 0); + + pci_set_master(dev); return alloc_uhci(dev, dev->irq, io_addr, io_size); } - return -1; + return -ENODEV; } -static int __init uhci_init (void) +/*-------------------------------------------------------------------------*/ + +static const struct pci_device_id __devinitdata uhci_pci_ids [] = { { + + /* handle any USB UHCI controller */ + class: ((PCI_CLASS_SERIAL_USB << 8) | 0x00), + class_mask: ~0, + + /* no matter who makes it */ + vendor: PCI_ANY_ID, + device: PCI_ANY_ID, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + + }, { /* end: all zeroes */ } +}; + +MODULE_DEVICE_TABLE (pci, uhci_pci_ids); + +static struct pci_driver uhci_pci_driver = { + name: "usb-uhci", + id_table: &uhci_pci_ids [0], + + probe: uhci_pci_probe, + remove: uhci_pci_remove, + +#ifdef CONFIG_PM + suspend: uhci_pci_suspend, + resume: uhci_pci_resume, +#endif /* PM */ + +}; + +/*-------------------------------------------------------------------------*/ + +static int __init uhci_hcd_init (void) { - int retval = -ENODEV; - struct pci_dev *dev = NULL; - u8 type; - int i=0; + int retval; #ifdef DEBUG_SLAB @@ -2929,31 +3024,8 @@ #ifdef CONFIG_USB_UHCI_HIGH_BANDWIDTH info("High bandwidth mode enabled"); #endif - for (;;) { - dev = pci_find_class (PCI_CLASS_SERIAL_USB << 8, dev); - if (!dev) - break; - /* Is it UHCI */ - pci_read_config_byte (dev, PCI_CLASS_PROG, &type); - if (type != 0) - continue; - - if (pci_enable_device (dev) < 0) - continue; - - if(!dev->irq) - { - err("Found UHCI device with no IRQ assigned. Check BIOS settings!"); - continue; - } - - /* Ok set it up */ - retval = start_uhci (dev); - - if (!retval) - i++; - } + retval = pci_module_init (&uhci_pci_driver); #ifdef DEBUG_SLAB if (retval < 0 ) { @@ -2967,13 +3039,10 @@ return retval; } -static void __exit uhci_cleanup (void) -{ - uhci_t *s; - while ((s = devs)) { - devs = devs->next; - uhci_cleanup_dev(s); - } +static void __exit uhci_hcd_cleanup (void) +{ + pci_unregister_driver (&uhci_pci_driver); + #ifdef DEBUG_SLAB if(kmem_cache_destroy(uhci_desc_kmem)) err("uhci_desc_kmem remained"); @@ -2983,14 +3052,9 @@ #endif } -static void __exit uhci_exit (void) -{ - pm_unregister_all (handle_pm_event); - uhci_cleanup (); -} +module_init (uhci_hcd_init); +module_exit (uhci_hcd_cleanup); -module_init(uhci_init); -module_exit(uhci_exit); MODULE_AUTHOR("Georg Acher, Deti Fliegl, Thomas Sailer, Roman Weissgaerber"); MODULE_DESCRIPTION("USB Universal Host Controller Interface driver"); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.0-test11/linux/drivers/usb/usb.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/usb/usb.c Thu Dec 7 16:13:38 2000 @@ -30,7 +30,7 @@ #include /* for in_interrupt() */ #include #include - +#include #ifdef CONFIG_USB_DEBUG #define DEBUG @@ -67,6 +67,8 @@ LIST_HEAD(usb_driver_list); LIST_HEAD(usb_bus_list); +devfs_handle_t usb_devfs_handle; /* /dev/usb dir. */ + static struct usb_busmap busmap; static struct usb_driver *usb_minors[16]; @@ -86,7 +88,7 @@ init_MUTEX(&new_driver->serialize); /* Add it to the list of known drivers */ - list_add(&new_driver->driver_list, &usb_driver_list); + list_add_tail(&new_driver->driver_list, &usb_driver_list); usb_scan_devices(); @@ -296,11 +298,13 @@ else dev->bus->bandwidth_int_reqs++; urb->bandwidth = bustime; - + +#ifdef USB_BANDWIDTH_MESSAGES dbg("bandwidth alloc increased by %d to %d for %d requesters", bustime, dev->bus->bandwidth_allocated, dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif } /* @@ -316,10 +320,12 @@ else dev->bus->bandwidth_int_reqs--; +#ifdef USB_BANDWIDTH_MESSAGES dbg("bandwidth alloc reduced by %d to %d for %d requesters", urb->bandwidth, dev->bus->bandwidth_allocated, dev->bus->bandwidth_int_reqs + dev->bus->bandwidth_isoc_reqs); +#endif urb->bandwidth = 0; } @@ -554,7 +560,7 @@ continue; if (id->bDeviceSubClass && - id->bDeviceSubClass!= dev->descriptor.bDeviceClass) + id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass) continue; if (id->bDeviceProtocol && @@ -2047,9 +2053,9 @@ if (err < 0) { err("unable to get device %d configuration (error=%d)", dev->devnum, err); - usb_destroy_configuration(dev); clear_bit(dev->devnum, &dev->bus->devmap.devicemap); dev->devnum = -1; + usb_free_dev(dev); return 1; } @@ -2119,16 +2125,20 @@ int usb_major_init(void) { - if (register_chrdev(USB_MAJOR,"usb",&usb_fops)) { + if (devfs_register_chrdev(USB_MAJOR, "usb", &usb_fops)) { err("unable to get major %d for usb devices", USB_MAJOR); return -EBUSY; } + + usb_devfs_handle = devfs_mk_dir(NULL, "usb", NULL); + return 0; } void usb_major_cleanup(void) { - unregister_chrdev(USB_MAJOR, "usb"); + devfs_unregister(usb_devfs_handle); + devfs_unregister_chrdev(USB_MAJOR, "usb"); } @@ -2231,3 +2241,5 @@ EXPORT_SYMBOL(usb_control_msg); EXPORT_SYMBOL(usb_bulk_msg); + +EXPORT_SYMBOL(usb_devfs_handle); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c --- v2.4.0-test11/linux/drivers/usb/wacom.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/usb/wacom.c Tue Nov 28 21:51:17 2000 @@ -1,11 +1,12 @@ /* - * $Id: wacom.c,v 1.11 2000/10/18 12:12:26 vojtech Exp $ + * $Id: wacom.c,v 1.14 2000/11/23 09:34:32 vojtech Exp $ * * Copyright (c) 2000 Vojtech Pavlik * Copyright (c) 2000 Andreas Bach Aaen * Copyright (c) 2000 Clifford Wolf * Copyright (c) 2000 Sam Mosel * Copyright (c) 2000 James E. Blair + * Copyright (c) 2000 Daniel Egger * * USB Wacom Graphire and Wacom Intuos tablet support * @@ -24,6 +25,9 @@ * other cleanups * v1.11 (vp) - Add URB ->dev setting for new kernels * v1.11 (jb) - Add support for the 4D Mouse & Lens + * v1.12 (de) - Add support for two more inking pen IDs + * v1.14 (vp) - Use new USB device id probing scheme. + * Fix Wacom Graphire mouse wheel */ /* @@ -129,7 +133,6 @@ struct wacom_features { char *name; - int idProduct; int pktlen; int x_max; int y_max; @@ -211,6 +214,8 @@ if (((data[1] >> 5) & 0x3) == 0x2) { /* Enter report */ switch (((__u32)data[2] << 4) | (data[3] >> 4)) { + case 0x832: + case 0x812: case 0x012: wacom->tool = BTN_TOOL_PENCIL; break; /* Inking pen */ case 0x822: case 0x022: wacom->tool = BTN_TOOL_PEN; break; /* Pen */ @@ -279,21 +284,33 @@ #define WACOM_INTUOS_ABS (BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE)) struct wacom_features wacom_features[] = { - { "Wacom Graphire", 0x10, 8, 10206, 7422, 511, 32, wacom_graphire_irq, - BIT(EV_REL), 0, 0, 0 }, - { "Wacom Intuos 4x5", 0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq, + { "Wacom Graphire", 8, 10206, 7422, 511, 32, wacom_graphire_irq, + BIT(EV_REL), 0, REL_WHEEL, 0 }, + { "Wacom Intuos 4x5", 10, 12700, 10360, 1023, 15, wacom_intuos_irq, 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, - { "Wacom Intuos 6x8", 0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 6x8", 10, 20320, 15040, 1023, 15, wacom_intuos_irq, 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, - { "Wacom Intuos 9x12", 0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 9x12", 10, 30480, 23060, 1023, 15, wacom_intuos_irq, 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, - { "Wacom Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 12x12", 10, 30480, 30480, 1023, 15, wacom_intuos_irq, 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, - { "Wacom Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq, + { "Wacom Intuos 12x18", 10, 47720, 30480, 1023, 15, wacom_intuos_irq, 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { NULL , 0 } }; +struct usb_device_id wacom_ids[] = { + { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x10, driver_info: 0 }, + { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x20, driver_info: 1 }, + { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x21, driver_info: 2 }, + { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x22, driver_info: 3 }, + { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x23, driver_info: 4 }, + { idVendor: USB_VENDOR_ID_WACOM, idProduct: 0x24, driver_info: 5 }, + { } +}; + +MODULE_DEVICE_TABLE(usb, wacom_ids); + static int wacom_open(struct input_dev *dev) { struct wacom *wacom = dev->private; @@ -316,22 +333,15 @@ usb_unlink_urb(&wacom->irq); } -static void *wacom_probe(struct usb_device *dev, unsigned int ifnum) +static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id) { struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; - int i; - - if (dev->descriptor.idVendor != USB_VENDOR_ID_WACOM) return NULL; - for (i = 0; wacom_features[i].idProduct && wacom_features[i].idProduct != dev->descriptor.idProduct; i++); - if (!wacom_features[i].idProduct) return NULL; - - endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL; memset(wacom, 0, sizeof(struct wacom)); - wacom->features = wacom_features + i; + wacom->features = wacom_features + id->driver_info; wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | wacom->features->evbit; wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | wacom->features->absbit; @@ -366,6 +376,8 @@ wacom->dev.idversion = dev->descriptor.bcdDevice; wacom->usbdev = dev; + endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; + FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress), wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval); @@ -389,6 +401,7 @@ name: "wacom", probe: wacom_probe, disconnect: wacom_disconnect, + id_table: wacom_ids, }; static int __init wacom_init(void) diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.4.0-test11/linux/drivers/video/Makefile Sun Nov 19 18:44:17 2000 +++ linux/drivers/video/Makefile Mon Nov 27 17:11:26 2000 @@ -68,7 +68,7 @@ obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o obj-$(CONFIG_FB_SGIVW) += sgivwfb.o obj-$(CONFIG_FB_3DFX) += tdfxfb.o -obj-$(CONFIG_FB_MAC) += macfb.o +obj-$(CONFIG_FB_MAC) += macfb.o macmodes.o obj-$(CONFIG_FB_HP300) += hpfb.o obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_IMSTT) += imsttfb.o diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/amifb.c linux/drivers/video/amifb.c --- v2.4.0-test11/linux/drivers/video/amifb.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/video/amifb.c Mon Nov 27 17:57:34 2000 @@ -750,13 +750,6 @@ /* - * The minimum period for audio depends on htotal (for OCS/ECS/AGA) - * (Imported from arch/m68k/amiga/amisound.c) - */ - -extern volatile u_short amiga_audio_min_period; - - /* * Since we can't read the palette on OCS/ECS, and since reading one * single color palette entry requires 5 expensive custom chip bus accesses * on AGA, we keep a copy of the current palette. @@ -1206,6 +1199,8 @@ if (!strcmp(this_opt, "inverse")) { amifb_inverse = 1; fb_invert_cmaps(); + } else if (!strcmp(this_opt, "off")) { + amifb_video_off(); } else if (!strcmp(this_opt, "ilbm")) amifb_ilbm = 1; else if (!strncmp(this_opt, "monitorcap:", 11)) @@ -1771,7 +1766,7 @@ * access the videomem with writethrough cache */ videomemory_phys = (u_long)ZTWO_PADDR(videomemory); - videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize); + //videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize); if (!videomemory) { printk("amifb: WARNING! unable to map videomem cached writethrough\n"); videomemory = ZTWO_VADDR(videomemory_phys); @@ -1792,15 +1787,11 @@ ami_init_copper(); - if (request_irq(IRQ_AMIGA_AUTO_3, amifb_interrupt, 0, - "fb vertb handler", NULL)) { + if (request_irq(IRQ_AMIGA_VERTB, amifb_interrupt, 0, + "fb vertb handler", ¤tpar)) { err = -EBUSY; goto amifb_error; } - amiga_intena_vals[IRQ_AMIGA_VERTB] = IF_COPER; - amiga_intena_vals[IRQ_AMIGA_COPPER] = 0; - custom.intena = IF_VERTB; - custom.intena = IF_SETCLR | IF_COPER; amifb_set_var(&var, -1, &fb_info); @@ -1895,57 +1886,33 @@ static void amifb_interrupt(int irq, void *dev_id, struct pt_regs *fp) { - u_short ints = custom.intreqr & custom.intenar; - static struct irq_server server = {0, 0}; - unsigned long flags; - - if (ints & IF_BLIT) { - custom.intreq = IF_BLIT; - amiga_do_irq(IRQ_AMIGA_BLIT, fp); - } - - if (ints & IF_COPER) { - custom.intreq = IF_COPER; - if (do_vmode_pan || do_vmode_full) - ami_update_display(); - - if (do_vmode_full) - ami_init_display(); - - if (do_vmode_pan) { - flash_cursor(); - ami_rebuild_copper(); - do_cursor = do_vmode_pan = 0; - } else if (do_cursor) { - flash_cursor(); - ami_set_sprite(); - do_cursor = 0; - } else { - if (flash_cursor()) - ami_set_sprite(); - } + if (do_vmode_pan || do_vmode_full) + ami_update_display(); - save_flags(flags); - cli(); - if (get_vbpos() < down2(currentpar.diwstrt_v - 6)) - custom.copjmp2 = 0; - restore_flags(flags); + if (do_vmode_full) + ami_init_display(); - if (do_blank) { - ami_do_blank(); - do_blank = 0; - } + if (do_vmode_pan) { + flash_cursor(); + ami_rebuild_copper(); + do_cursor = do_vmode_pan = 0; + } else if (do_cursor) { + flash_cursor(); + ami_set_sprite(); + do_cursor = 0; + } else { + if (flash_cursor()) + ami_set_sprite(); + } - if (do_vmode_full) { - ami_reinit_copper(); - do_vmode_full = 0; - } - amiga_do_irq_list(IRQ_AMIGA_VERTB, fp, &server); + if (do_blank) { + ami_do_blank(); + do_blank = 0; } - if (ints & IF_VERTB) { - printk("%s: Warning: IF_VERTB was enabled\n", __FUNCTION__); - custom.intena = IF_VERTB; + if (do_vmode_full) { + ami_reinit_copper(); + do_vmode_full = 0; } } @@ -3379,5 +3346,6 @@ { unregister_framebuffer(&fb_info); amifb_deinit(); + amifb_video_off(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/atafb.c linux/drivers/video/atafb.c --- v2.4.0-test11/linux/drivers/video/atafb.c Sun Nov 19 18:44:17 2000 +++ linux/drivers/video/atafb.c Mon Nov 27 18:00:49 2000 @@ -2425,6 +2425,21 @@ } static int +atafb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) +{ + struct atafb_par par; + if (con == -1) + atafb_get_par(&par); + else { + int err; + if ((err=fbhw->decode_var(&fb_display[con].var,&par))) + return err; + } + memset(fix, 0, sizeof(struct fb_fix_screeninfo)); + return fbhw->encode_fix(fix, &par); +} + +static int atafb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) { struct atafb_par par; @@ -2776,7 +2791,7 @@ #endif /* ATAFB_EXT */ mem_req = default_mem_req + ovsc_offset + ovsc_addlen; mem_req = PAGE_ALIGN(mem_req) + PAGE_SIZE; - screen_base = atari_stram_alloc(mem_req, NULL, "atafb"); + screen_base = atari_stram_alloc(mem_req, "atafb"); if (!screen_base) panic("Cannot allocate screen memory"); memset(screen_base, 0, mem_req); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c --- v2.4.0-test11/linux/drivers/video/aty128fb.c Sun Oct 8 10:50:31 2000 +++ linux/drivers/video/aty128fb.c Sun Dec 3 17:45:23 2000 @@ -283,7 +283,6 @@ const struct aty128_meminfo *mem; /* onboard mem info */ struct aty128fb_par default_par, current_par; struct display disp; - struct display_switch dispsw; /* for cursor and font */ struct { u8 red, green, blue, pad; } palette[256]; union { #ifdef FBCON_HAS_CFB16 @@ -347,7 +346,7 @@ static void aty128_encode_fix(struct fb_fix_screeninfo *fix, struct aty128fb_par *par, const struct fb_info_aty128 *info); -static void aty128_set_disp(struct display *disp, +static void aty128_set_dispsw(struct display *disp, struct fb_info_aty128 *info, int bpp, int accel); static int aty128_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info); @@ -1392,7 +1391,7 @@ display->inverse = 0; accel = var->accel_flags & FB_ACCELF_TEXT; - aty128_set_disp(display, info, par.crtc.bpp, accel); + aty128_set_dispsw(display, info, par.crtc.bpp, accel); if (accel) display->scrollmode = SCROLL_YNOMOVE; @@ -1417,35 +1416,31 @@ static void -aty128_set_disp(struct display *disp, +aty128_set_dispsw(struct display *disp, struct fb_info_aty128 *info, int bpp, int accel) { switch (bpp) { #ifdef FBCON_HAS_CFB8 case 8: - info->dispsw = accel ? fbcon_aty128_8 : fbcon_cfb8; - disp->dispsw = &info->dispsw; + disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8; break; #endif #ifdef FBCON_HAS_CFB16 case 15: case 16: - info->dispsw = accel ? fbcon_aty128_16 : fbcon_cfb16; - disp->dispsw = &info->dispsw; + disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16; disp->dispsw_data = info->fbcon_cmap.cfb16; break; #endif #ifdef FBCON_HAS_CFB24 case 24: - info->dispsw = accel ? fbcon_aty128_24 : fbcon_cfb24; - disp->dispsw = &info->dispsw; + disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24; disp->dispsw_data = info->fbcon_cmap.cfb24; break; #endif #ifdef FBCON_HAS_CFB32 case 32: - info->dispsw = accel ? fbcon_aty128_32 : fbcon_cfb32; - disp->dispsw = &info->dispsw; + disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32; disp->dispsw_data = info->fbcon_cmap.cfb32; break; #endif @@ -2135,7 +2130,7 @@ aty128_decode_var(&fb_display[con].var, &par, info); aty128_set_par(&par, info); - aty128_set_disp(&fb_display[con], info, par.crtc.bpp, + aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp, par.accel_flags & FB_ACCELF_TEXT); do_install_cmap(con, fb); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c --- v2.4.0-test11/linux/drivers/video/atyfb.c Sun Oct 8 10:50:31 2000 +++ linux/drivers/video/atyfb.c Sun Dec 3 17:45:23 2000 @@ -466,8 +466,8 @@ static int encode_fix(struct fb_fix_screeninfo *fix, const struct atyfb_par *par, const struct fb_info_aty *info); -static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info, - int bpp, int accel); +static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, + int bpp, int accel); static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *fb); static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, @@ -2826,8 +2826,8 @@ } -static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info, - int bpp, int accel) +static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, + int bpp, int accel) { switch (bpp) { #ifdef FBCON_HAS_CFB8 @@ -2898,6 +2898,7 @@ oldbpp = display->var.bits_per_pixel; oldaccel = display->var.accel_flags; display->var = *var; + accel = var->accel_flags & FB_ACCELF_TEXT; if (oldxres != var->xres || oldyres != var->yres || oldvxres != var->xres_virtual || oldvyres != var->yres_virtual || oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) { @@ -2913,8 +2914,6 @@ display->line_length = fix.line_length; display->can_soft_blank = 1; display->inverse = 0; - accel = var->accel_flags & FB_ACCELF_TEXT; - atyfb_set_disp(display, info, par.crtc.bpp, accel); if (accel) display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0; else @@ -2923,8 +2922,10 @@ (*info->fb_info.changevar)(con); } if (!info->fb_info.display_fg || - info->fb_info.display_fg->vc_num == con) + info->fb_info.display_fg->vc_num == con) { atyfb_set_par(&par, info); + atyfb_set_dispsw(display, info, par.crtc.bpp, accel); + } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; @@ -4241,8 +4242,8 @@ atyfb_decode_var(&fb_display[con].var, &par, info); atyfb_set_par(&par, info); - atyfb_set_disp(&fb_display[con], info, par.crtc.bpp, - par.accel_flags & FB_ACCELF_TEXT); + atyfb_set_dispsw(&fb_display[con], info, par.crtc.bpp, + par.accel_flags & FB_ACCELF_TEXT); /* Install new colormap */ do_install_cmap(con, fb); diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/dummycon.c linux/drivers/video/dummycon.c --- v2.4.0-test11/linux/drivers/video/dummycon.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/video/dummycon.c Tue Dec 5 12:29:39 2000 @@ -20,6 +20,9 @@ #if defined(__arm__) #define DUMMY_COLUMNS ORIG_VIDEO_COLS #define DUMMY_ROWS ORIG_VIDEO_LINES +#elif defined(__hppa__) +#define DUMMY_COLUMNS 80 /* fixme ! (mine uses 160x64 at 1280x1024) */ +#define DUMMY_ROWS 25 #else #define DUMMY_COLUMNS 80 #define DUMMY_ROWS 25 diff -u --recursive --new-file v2.4.0-test11/linux/drivers/video/fbcon-sti.c linux/drivers/video/fbcon-sti.c --- v2.4.0-test11/linux/drivers/video/fbcon-sti.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/video/fbcon-sti.c Tue Dec 5 12:29:39 2000 @@ -0,0 +1,330 @@ +/* + * linux/drivers/video/fbcon-sti.c -- Low level frame buffer + * operations for generic HP video boards using STI (standard + * text interface) firmware + * + * Based on linux/drivers/video/fbcon-artist.c + * Created 5 Apr 1997 by Geert Uytterhoeven + * Copyright (C) 2000 Philipp Rumpf + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. */ + +#include +#include +#include +#include +#include +#include +#include + +#include