diff -u --recursive --new-file v2.4.0-test10/linux/CREDITS linux/CREDITS --- v2.4.0-test10/linux/CREDITS Tue Oct 31 12:42:25 2000 +++ linux/CREDITS Fri Nov 17 16:45:23 2000 @@ -765,11 +765,10 @@ S: Germany N: Rik Faith -E: faith@cs.unc.edu E: faith@acm.org -D: Author: Future Domain TMC-16x0 SCSI driver -D: Debugging: SCSI code; Cyclades serial driver; APM driver -D: Debugging: XFree86 Mach 32 server, accelerated server code +D: Future Domain TMC-16x0 SCSI driver (author) +D: APM driver (early port) +D: DRM drivers (author of several) N: János Farkas E: chexum@shadow.banki.hu @@ -912,6 +911,15 @@ S: Sterling Heights, Michigan 48313 S: USA +N: William Greathouse +E: wgreathouse@smva.com +E: wgreathouse@myfavoritei.com +D: Current Belkin USB Serial Adapter F5U103 hacker +D: Kernel hacker, embedded systems +S: 7802 Fitzwater Road +S: Brecksville, OH 44141-1334 +S: USA + N: Tristan Greaves E: Tristan.Greaves@icl.com E: tmg296@ecs.soton.ac.uk @@ -1425,9 +1433,10 @@ N: Russell Kroll E: rkroll@exploits.org W: http://www.exploits.org/ -D: V4L Aztech radio card driver, mods to Aimslab driver -S: Post Office Box 49458 -S: Colorado Springs, Colorado 80949-9458 +D: V4L radio cards: radio-aztech (new), others (bugfixes/features) +D: Loopback block device: dynamic sizing ("max_loop" as module) +S: Post Office Box 691886 +S: San Antonio, Texas 78269-1886 S: USA N: Andrzej M. Krzysztofowicz @@ -1590,7 +1599,8 @@ E: rml@tech9.net E: rml@ufl.edu D: misc. kernel hacking and debugging -S: FL, USA +S: Gainesville, Florida 32608 +S: USA N: Martin von Löwis E: loewis@informatik.hu-berlin.de @@ -2239,11 +2249,12 @@ S: Germany N: Stephen Rothwell -E: sfr@linuxcare.com +E: sfr@linuxcare.com.au W: http://linuxcare.com.au/sfr P: 1024/BD8C7805 CD A4 9D 01 10 6E 7E 3B 91 88 FA D9 C8 40 AA 02 D: Boot/setup/build work for setup > 2K D: Author, APM driver +D: Directory notification S: 66 Maltby Circuit S: Wanniassa ACT 2903 S: Australia @@ -2624,17 +2635,14 @@ S: USA N: Stephen Tweedie -E: sct@dcs.ed.ac.uk +E: sct@redhat.com P: 1024/E7A417AD E2 FE A4 20 34 EC ED FC 7D 7E 67 8D E0 31 D1 69 +P: 1024D/43BE7544 D2A4 8556 08E6 90E7 076C BA3F 243F 20A4 43BE 7544 D: Second extended file system developer D: General filesystem hacker D: kswap vm management code -S: Dept. of Computer Science -S: University of Edinburgh -S: JCMB, The King's Buildings -S: Mayfield Road -S: Edinburgh -S: EH9 3JZ +S: 44 Campbell Park Crescent +S: Edinburgh EH13 0HT S: United Kingdom N: Thomas Uhl diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/00-INDEX linux/Documentation/00-INDEX --- v2.4.0-test10/linux/Documentation/00-INDEX Tue Feb 8 11:28:31 2000 +++ linux/Documentation/00-INDEX Tue Nov 14 10:54:07 2000 @@ -43,6 +43,8 @@ - info on the Digiboard PC/X{i,e,eve} multiport boards. digiepca.txt - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. +dnotify.txt + - info about directory notification in Linux. exception.txt - how Linux v2.2 handles exceptions without verify_area etc. fb/ diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/Configure.help linux/Documentation/Configure.help --- v2.4.0-test10/linux/Documentation/Configure.help Tue Oct 31 12:42:25 2000 +++ linux/Documentation/Configure.help Fri Nov 17 16:43:42 2000 @@ -77,7 +77,7 @@ in some special cases. Detailed bug reports from people familiar with the kernel internals are usually welcomed by the developers (before submitting bug reports, please read the documents README, - MAINTAINERS, REPORTING_BUGS, Documentation/BUG-HUNTING, and + MAINTAINERS, REPORTING-BUGS, Documentation/BUG-HUNTING, and Documentation/oops-tracing.txt in the kernel source). This option will also make obsoleted drivers available. These are @@ -113,7 +113,7 @@ Management" code will be disabled if you say Y here. See also the files Documentation/smp.tex, Documentation/smp.txt, - Documentation/IO-APIC.txt, Documentation/nmi_watchdog.txt and the + Documentation/i386/IO-APIC.txt, Documentation/nmi_watchdog.txt and the SMP-FAQ on the WWW at http://www.irisa.fr/prive/mentre/smp-faq/ . If you don't know what to do here, say N. @@ -2052,6 +2052,23 @@ If you want to compile it as a module, say M here and read Documentation/modules.txt. If unsure, say `N'. +TCP Explicit Congestion Notification support +CONFIG_INET_ECN + Explicit Congestion Notification (ECN) allows routers to notify + clients about network congestion, resulting in fewer dropped packets + and increased network performance. This option adds ECN support to the + Linux kernel, as well as a sysctl (/proc/sys/net/ipv4/tcp_ecn) which + allows ECN support to be disabled at runtime. + + Note that, on the Internet, there are many broken firewalls which + refuse connections from ECN-enabled machines, and it may be a while + before these firewalls are fixed. Until then, to access a site behind + such a firewall (some of which are major sites, at the time of this + writing) you will have to disable this option, either by saying N now + or by using the sysctl. + + If in doubt, say N. + SYN flood protection CONFIG_SYN_COOKIES Normal TCP/IP networking is open to an attack known as "SYN @@ -2338,7 +2355,7 @@ Intel 440LX/BX/GX support CONFIG_AGP_INTEL This option gives you AGP support for the GLX component of the - XFree86 4.x on Intel 440LX/BX/GX chipsets. + XFree86 4.x on Intel 440LX/BX/GX, 815, and 840 chipsets. For the moment, you should probably say N, unless you want to test the GLX component for XFree86 3.3.6, which can be downloaded from @@ -2346,9 +2363,9 @@ Intel I810/I810 DC100/I810e support CONFIG_AGP_I810 - This option gives you AGP support for the Xserver for the Intel - 810 chipset boards. This is required to do any useful video - modes. + This option gives you AGP support for the Xserver on the Intel 810 + and 815 chipset boards for their on-board integrated graphics. This + is required to do any useful video modes with these boards. VIA chipset support CONFIG_AGP_VIA @@ -2465,6 +2482,20 @@ Documentation/mca.txt (and especially the web page given there) before attempting to build an MCA bus kernel. +EISA support +CONFIG_EISA + The Extended Industry Standard Architecture (EISA) bus was + developed as an open alternative to the IBM MicroChannel bus. + + The EISA bus provided some of the features of the IBM MicroChannel + bus while maintaining backward compatibility with cards made for + the older ISA bus. The EISA bus saw limited use between 1988 and 1995 + when it was made obsolete by the PCI bus. + + Say Y here if you are building a kernel for an EISA-based machine. + + Otherwise, say N. + SGI Visual Workstation support CONFIG_VISWS The SGI Visual Workstation series is an IA32-based workstation @@ -2838,6 +2869,7 @@ - "Pentium-MMX" for the Intel Pentium MMX. - "Pentium-Pro" for the Intel Pentium Pro/Celeron/Pentium II. - "Pentium-III" for the Intel Pentium III. + - "Pentium-4" for the Intel Pentium 4 - "K6" for the AMD K6, K6-II and K6-III (aka K6-3D). - "Athlon" for the AMD Athlon (K7). - "Crusoe" for the Transmeta Crusoe series. @@ -3471,7 +3503,7 @@ The module will be called parport.o. If you have more than one parallel port and want to specify which port and IRQ to be used by this driver at module load time, take a look at - Documentation/networking/parport.txt. + Documentation/parport.txt. If unsure, say Y. @@ -3614,7 +3646,7 @@ "Sysctl support" below, you can change various aspects of the behavior of the TCP/IP code by writing to the (virtual) files in /proc/sys/net/ipv4/*; the options are explained in the file - Documentation/Networking/ip-sysctl.txt. + Documentation/networking/ip-sysctl.txt. Short answer: say Y. @@ -4995,7 +5027,7 @@ CONFIG_BLK_CPQ_CISS_DA This is the driver for Compaq Smart Array controllers. Everyone using these boards should say Y here. - See "linux/Documentation/cciss.txt" for the current list of + See Documentation/cciss.txt for the current list of boards supported by this driver, and for further information on the use of this driver. @@ -13995,7 +14027,7 @@ SGI Visual Workstation on-board audio CONFIG_SOUND_VWSND Say Y or M if you have an SGI Visual Workstation and you want to - be able to use its on-board audio. Read Documentation/sound/visws + be able to use its on-board audio. Read Documentation/sound/vwsnd for more info on this driver's capabilities. Ensoniq Soundscape support @@ -14028,8 +14060,7 @@ Support for OPTi MAD16 and/or Mozart based cards CONFIG_SOUND_MAD16 Answer Y if your card has a Mozart (OAK OTI-601) or MAD16 (OPTi - 82C928 or 82C929 or 82C931) audio interface chip. For the 82C931, - please read drivers/sound/README.C931. These chips are currently + 82C928 or 82C929 or 82C931) audio interface chip. These chips are quite common so it's possible that many no-name cards have one of them. In addition the MAD16 chip is used in some cards made by known manufacturers such as Turtle Beach (Tropez), Reveal (some models) diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/cachetlb.txt linux/Documentation/cachetlb.txt --- v2.4.0-test10/linux/Documentation/cachetlb.txt Tue Oct 31 12:42:25 2000 +++ linux/Documentation/cachetlb.txt Thu Nov 9 15:57:40 2000 @@ -305,19 +305,23 @@ If D-cache aliasing is not an issue, this routine may simply be defined as a nop on that architecture. - TODO: If we set aside a few bits in page->flags as - "architecture private", these interfaces could - be implemented much more efficiently. This would - allow one to "defer" (perhaps indefinitely) the - actual flush if there are currently no user processes - mapping this page. + There is a bit set aside in page->flags (PG_arch_1) as + "architecture private". The kernel guarentees that, + for pagecache pages, it will clear this bit when such + a page first enters the pagecache. - The idea is, first at flush_dcache_page() time, if - page->mapping->i_mmap is an empty list, just mark - one of the architecture private page flag bits. - Later, in update_mmu_cache(), a check could be made - of this flag bit, and if set the flush is done - and the flag bit is cleared. + This allows these interfaces to be implemented much more + efficiently. It allows one to "defer" (perhaps indefinitely) + the actual flush if there are currently no user processes + mapping this page. See sparc64's flush_dcache_page and + update_mmu_cache implementations for an example of how to go + about doing this. + + The idea is, first at flush_dcache_page() time, if + page->mapping->i_mmap{,_shared} are empty lists, just mark the + architecture private page flag bit. Later, in + update_mmu_cache(), a check is made of this flag bit, and if + set the flush is done and the flag bit is cleared. XXX Not documented: flush_icache_page(), need to talk to Paul Mackerras, David Mosberger-Tang, et al. diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/dnotify.txt linux/Documentation/dnotify.txt --- v2.4.0-test10/linux/Documentation/dnotify.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/dnotify.txt Tue Nov 14 10:54:07 2000 @@ -0,0 +1,92 @@ + Linux Directory Notification + ============================ + + Stephen Rothwell + +The intention of directory notification is to allow user applications +to be notified when a directory, or any of the files in it, are changed. +The basic mechanism involves the application registering for notification +on a directory using a fcntl(2) call and the notifications themselves +being delivered using signals. + +The application decides which "events" it wants to be notified about. +The currently defined events are: + + DN_ACCESS A file in the directory was accessed (read) + DN_MODIFY A file in the directory was modified (write,truncate) + DN_CREATE A file was created in the directory + DN_DELETE A file was unlinked from directory + DN_RENAME A file in the directory was renamed + DN_ATTRIB A file in the directory had its attributes + changed (chmod,chown) + +Usually, the application must reregister after each notification, but +if DN_MULTISHOT is or'ed with the event mask, then the registration will +remain until explicitly removed (by registering for no events). + +By default, SIGIO will be delivered to the process and no other useful +information. However, if the F_SETSIG fcntl(2) call is used to let the +kernel know which signal to deliver, a siginfo structure will be passed to +the signal handler and the si_fd member of that structure will contain the +file descriptor associated with the direcory in which the event occured. + +Preferably the application will choose one of the real time signals +(SIGRTMIN + ) so that the notifications may be queued. This is +especially important if DN_MULTISHOT is specified. + +Implementation expectations (features and bugs :-)) +--------------------------- + +The notification should work for any local access to files even if the +actual file system is on a remote server. This implies that remote +access to files served by local user mode servers should be notified. +Also, remote accesses to files served by a local kernel NFS server should +be notified. + +In order to make the impact on the file system code as small as possible, +the problem of hard links to files has been ignored. So if a file (x) +exists in two directories (a and b) then a change to the file using the +name "a/x" should be notified to a program expecting notifications on +directory "a", but will not be notified to one expecting notifications on +directory "b". + +Also, files that are unlinked, will still cause notifications in the +last directory that they were linked to. + +Example +------- + + #define _GNU_SOURCE /* needed to get the defines */ + #include /* in glibc 2.2 this has the needed + values defined */ + #include + #include + #include + + static volatile int event_fd; + + static void handler(int sig, siginfo_t *si, void *data) + { + event_fd = si->si_fd; + } + + int main(void) + { + struct sigaction act; + int fd; + + act.sa_sigaction = handler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGRTMIN, &act, NULL); + + fd = open(".", O_RDONLY); + fcntl(fd, F_SETSIG, SIGRTMIN); + fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT); + /* we will now be notified if any of the files + in "." is modified or new files are created */ + while (1) { + pause(); + printf("Got event on fd=%d\n", event_fd); + } + } diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt --- v2.4.0-test10/linux/Documentation/fb/matroxfb.txt Thu Aug 10 12:34:31 2000 +++ linux/Documentation/fb/matroxfb.txt Sat Nov 11 18:47:40 2000 @@ -253,7 +253,7 @@ `vesa'. If you know capabilities of your monitor, you can specify some (or all) of -`pixclk', `fh' and `fv'. In this case, `pixclock' is computed so that +`maxclk', `fh' and `fv'. In this case, `pixclock' is computed so that pixclock <= maxclk, real_fh <= fh and real_fv <= fv. maxclk:X - maximum dotclock. X can be specified in MHz, kHz or Hz. Default is diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/isdn/README.act2000 linux/Documentation/isdn/README.act2000 --- v2.4.0-test10/linux/Documentation/isdn/README.act2000 Fri Jul 28 12:50:51 2000 +++ linux/Documentation/isdn/README.act2000 Sat Nov 11 18:58:02 2000 @@ -1,4 +1,4 @@ -$Id: README.act2000,v 1.2 1998/04/29 19:49:06 he Exp $ +$Id: README.act2000,v 1.3 2000/08/06 09:22:51 armin Exp $ This document describes the ACT2000 driver for the IBM Active 2000 ISDN card. diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/isdn/README.eicon linux/Documentation/isdn/README.eicon --- v2.4.0-test10/linux/Documentation/isdn/README.eicon Sun Aug 13 10:05:32 2000 +++ linux/Documentation/isdn/README.eicon Sat Nov 11 18:58:02 2000 @@ -1,4 +1,4 @@ -$Id: README.eicon,v 1.9 2000/06/08 08:50:25 armin Exp $ +$Id: README.eicon,v 1.10 2000/08/13 12:19:15 armin Exp $ (c) 1999,2000 Armin Schindler (mac@melware.de) (c) 1999,2000 Cytronics & Melware (info@melware.de) diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/isdn/README.icn linux/Documentation/isdn/README.icn --- v2.4.0-test10/linux/Documentation/isdn/README.icn Fri Jul 28 12:50:51 2000 +++ linux/Documentation/isdn/README.icn Sat Nov 11 18:58:03 2000 @@ -1,4 +1,4 @@ -$Id: README.icn,v 1.6 1998/04/29 19:49:08 he Exp $ +$Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $ You can get the ICN-ISDN-card from: diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/kbuild/makefiles.txt linux/Documentation/kbuild/makefiles.txt --- v2.4.0-test10/linux/Documentation/kbuild/makefiles.txt Tue Oct 31 12:42:25 2000 +++ linux/Documentation/kbuild/makefiles.txt Tue Nov 7 10:46:04 2000 @@ -640,6 +640,12 @@ but then you will notice a lot of extra compiles when you edit any source file. Blame CONFIG_MODVERSIONS for this.] + Data that is passed to other objects via registration functions + (e.g. pci_register_driver, pm_register) does not need to be marked + as EXPORT_SYMBOL. The objects that pass data via registration + functions do not need to be marked as OX_OBJS, unless they also have + exported symbols. + Rules.make compiles all the $(O_OBJS) and $(OX_OBJS) files. It then calls "$(LD) -r" to merge these files into one .o file with the name $(O_TARGET). This $(O_TARGET) name also appears diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/bridge.txt linux/Documentation/networking/bridge.txt --- v2.4.0-test10/linux/Documentation/networking/bridge.txt Fri Feb 18 14:51:22 2000 +++ linux/Documentation/networking/bridge.txt Thu Nov 9 15:57:53 2000 @@ -1,11 +1,11 @@ In order to use the ethernet bridging functionality you'll need the -userspace tools available at ftp://openrock.net/bridge. The tarball -available there contains extensive documentation, but if you still have -questions, don't hesitate to post to the mailing list (more info at -http://openrock.net/mailman/listinfo/bridge). You can also mail me at -buytenh@openrock.net. +userspace tools available at http://www.math.leidenuniv.nl/~buytenh/bridge. +The tarball available there contains extensive documentation, but if you +still have questions, don't hesitate to post to the mailing list (more info +at http://www.math.leidenuniv.nl/mailman/listinfo/bridge). You can also +mail me at buytenh@gnu.org. Lennert Buytenhek - + diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt --- v2.4.0-test10/linux/Documentation/networking/ip-sysctl.txt Fri Aug 18 10:26:25 2000 +++ linux/Documentation/networking/ip-sysctl.txt Thu Nov 9 15:57:53 2000 @@ -203,7 +203,7 @@ tcp_dsack - BOOLEAN Allows TCP to send "duplicate" SACKs. -tcp_ecn - BOOLEN +tcp_ecn - BOOLEAN Enable Explicit Congestion Notification in TCP. tcp_reordering - INTEGER @@ -376,4 +376,4 @@ Updated by: Andi Kleen ak@muc.de -$Id: ip-sysctl.txt,v 1.16 2000/08/13 18:24:11 davem Exp $ +$Id: ip-sysctl.txt,v 1.17 2000/11/06 07:15:36 davem Exp $ diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/lapb-module.txt linux/Documentation/networking/lapb-module.txt --- v2.4.0-test10/linux/Documentation/networking/lapb-module.txt Mon May 10 13:00:10 1999 +++ linux/Documentation/networking/lapb-module.txt Sat Nov 11 19:02:39 2000 @@ -2,6 +2,8 @@ Jonathan Naylor 29.12.96 +Changed (Henner Eisen, 2000-10-29): int return value for data_indication() + The LAPB module will be a separately compiled module for use by any parts of the Linux operating system that require a LAPB service. This document defines the interfaces to, and the services provided by this module. The @@ -37,7 +39,7 @@ void (*connect_indication)(int token, int reason); void (*disconnect_confirmation)(int token, int reason); void (*disconnect_indication)(int token, int reason); - void (*data_indication)(int token, struct sk_buff *skb); + int (*data_indication)(int token, struct sk_buff *skb); void (*data_transmit)(int token, struct sk_buff *skb); }; @@ -240,13 +242,17 @@ system. -void (*data_indication)(void *token, struct sk_buff *skb); +int (*data_indication)(void *token, struct sk_buff *skb); This is called by the LAPB module when data has been received from the remote system that should be passed onto the next layer in the protocol stack. The skbuff becomes the property of the device driver and the LAPB module will not perform any more actions on it. The skb->data pointer will be pointing to the first byte of data after the LAPB header. + +This method should return NET_RX_DROP (as defined in the header +file include/linux/netdevice.h) if and only if the frame was dropped +before it could be delivered to the upper layer. void (*data_transmit)(void *token, struct sk_buff *skb); diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/netdevices.txt linux/Documentation/networking/netdevices.txt --- v2.4.0-test10/linux/Documentation/networking/netdevices.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/networking/netdevices.txt Wed Nov 8 19:09:49 2000 @@ -0,0 +1,42 @@ + +Network Devices, the Kernel, and You! + + +Introduction +============ +The following is a random collection of documentation regarding +network devices. + + + +struct net_device synchronization rules +======================================= +dev->open: + Locking: Inside rtnl_lock() semaphore. + Sleeping: OK + +dev->stop: + Locking: Inside rtnl_lock() semaphore. + Sleeping: OK + +dev->do_ioctl: + Locking: Inside rtnl_lock() semaphore. + Sleeping: OK + +dev->get_stats: + Locking: Inside dev_base_lock spinlock. + Sleeping: NO + +dev->hard_start_xmit: + Locking: Inside dev->xmit_lock spinlock. + Sleeping: NO + +dev->tx_timeout: + Locking: Inside dev->xmit_lock spinlock. + Sleeping: NO + +dev->set_multicast_list: + Locking: Inside dev->xmit_lock spinlock. + Sleeping: NO + + diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/sis900.txt linux/Documentation/networking/sis900.txt --- v2.4.0-test10/linux/Documentation/networking/sis900.txt Fri Jul 28 12:50:52 2000 +++ linux/Documentation/networking/sis900.txt Thu Nov 16 18:09:16 2000 @@ -1,468 +1,245 @@ - SiS 900/7016 Fast Ethernet Device Driver - by Ollie Lho (ollie@sis.com.tw) - November 4, 1999. Document Revision: 0.2 - - This document gives some information on installation and usage of SiS - 900/7016 device driver under Linux. - ______________________________________________________________________ - - Table of Contents - - - 1. Introduction - - 2. License - - 3. Changes - - 4. Tested Environment - - 5. Files in This Package - - 6. Installation - - 6.1 Kernel version later than 2.2.11 and 2.3.15 - 6.1.1 Building the driver as loadable module - 6.1.2 Building the driver into kernel - 6.2 Earlier Kernel Version in 2.2.x and 2.3.x Series - - 7. Known Problems and Bugs - - 8. Revision History - - 9. Acknowledgements - - - - ______________________________________________________________________ - - 1. Introduction - - This document describes the revision 1.06 of SiS 900/7016 Fast - Ethernet device driver under Linux. The driver is developed by Silicon - Integrated System Corp. and distributed freely under the GNU General - Public License (GPL). The driver can be compiled as a loadable module - and used under Linux kernel version 2.2.x. With minimal changes, the - driver can also be used under 2.3.x kernel, please see section - ``Installation''. If you are intended to use the driver for earlier - kernels, you are on your own. - - The driver is tested with usual TCP/IP applications including FTP, - Telnet, Netscape etc. and is used constantly by the developers. - - Please send all comments/fixes/questions to Ollie Lho. - - - 2. License - - - - - - - - - - - Copyright (C) 1999 Silicon Integrated System Corp. - - 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 - - - - - - 3. Changes - - Changes made in Revision 1.06 - - 1. Separation of sis900.c and sis900.h in order to move most constant - definition to sis900.h (many of those constants were corrected) - - 2. Clean up PCI detection, the pci-scan from Donald Becker were not - used, just simple pci_find_*. - - 3. MII detection is modified to support multiple mii transceiver. - - 4. Bugs in read_eeprom, mdio_* were removed. - - 5. Lot of sis900 irrelevant comments were removed/changed and more - comments were added to reflect the real situation. - - 6. Clean up of physical/virtual address space mess in buffer - descriptors. - - 7. Better transmit/receive error handling. - - 8. The driver now uses zero-copy single buffer management scheme to - improve performance. - - 9. Names of variables were changed to be more consistent. - - 10. - Clean up of auo-negotiation and timer code. - - 11. - Automatic detection and change of PHY on the fly. - - - 4. Tested Environment - - This driver is developed on the following hardware - - o Intel Celeron 336 with SiS 620 (rev 02) chipset - - o SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card - - and tested with these software environments - - o Red Hat Linux version 6.0 - - o Linux kernel version 2.2.13 - - o Netscape version 4.6 - - o NcFTP 3.0.0 beta 18 - - o Samba version 2.0.3 - - - 5. Files in This Package - - In the package you can find these files: - - - sis900-2.2.x.c - Driver source for kernel 2.2.x - - sis900-2.3.x.c - Driver source for kernel 2.3.x - - sis900.h - Header file for both 2.2.x and 2.3.x kernel - - sis900.sgml - Linux-Doc SGML source of the document - - - 6. Installation - - Silicon Integrated System Corp. is cooperating closely with core Linux - Kernel developers. The revisions of SiS 900 driver are distributed by - the usual channels for kernel tar files and patches. Those kernel tar - files for official kernel and patches for kernel pre-release can be - download at official kernel ftp site - and its mirrors. The 1.06 - revision can be found in kernel version later than 2.3.15 and - pre-2.2.14. If you have no prior experience in networking under - Linux, please read Ethernet HOWTO and Networking HOWTO available from - Linux Documentation Project (LDP). - - The installation procedure are different according to your kernel - versions. - - - 6.1. Kernel version later than 2.2.11 and 2.3.15 - - The driver is bundled in release later than 2.2.11 and 2.3.15 so this - is the most easy case. Be sure you have the appropriate packages for - compiling kernel source. Those packages are listed in - Document/Changes in kernel source distribution. There are two - alternative ways to install the driver - - - 6.1.1. Building the driver as loadable module - - To build the driver as a loadable kernel module you have to - reconfigure the kernel to activate network support by - - - - make config - - - - - Choose "Network Device Support" to "Y" and "Ethernet Support" to "Y". - Then you have to choose "SiS 900 Fast Ethernet Adapter Support" to - "M". - - After reconfiguring the kernel, you can make the driver module by - - - make modules - - - - - The driver should be compiled with no errors. After compiling the - driver, the driver can be installed to proper place by - - - - make modules_install - - - - - Load the driver into kernel by - - - - insmod sis900 - - - - - When loading the driver into memory, some information message can be - view by - - - - dmesg - - - - - or - - - cat /var/log/message - - - - - If the driver is loaded properly you will have messages similar to - this: - - - - sis900.c: v1.06 11/04/99 - eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4. - eth0: SiS 900 Internal MII PHY transceiver found at address 1. - eth0: Using SiS 900 Internal MII PHY as default - - - - - showing the version of the driver and the results of probing routine. - - Once the driver is loaded, network can be brought up by - - - - /sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK - - - - - - where IPADDR, BROADCAST, NETMASK are your IP address, broadcast - address and netmask respectively. For more information on how to - configure network interface, please refer to Networking HOWTO. - - The link status is also shown by kernel messages. For example, after - the network interface is activated, you may have the message: - - - - eth0: Media Link On 100mbps full-duplex - - - - - If you try to unplug the twist pair (TP) cable you will get - - - - eth0: Media Link Off - - - - - indicating that the link is failed. - - - 6.1.2. Building the driver into kernel - - If you want to make the driver into kernel, choose "Y" rather than "M" - on "SiS 900 Fast Ethernet Adapter Support" when configuring the - kernel. Build the kernel image in the usual way - - - - make dep - - make clean - - make bzlilo - - - - - Next time the system reboot, you have the driver in memory. - - - 6.2. Earlier Kernel Version in 2.2.x and 2.3.x Series - - Installing the driver for earlier kernels in 2.2.x and 2.3.x series - requires a little bit more work. First you have to copy sis900-2.x.x.c - to /usr/src/linux/drivers/net/ and you have to modify some files - manually (sorry !! no patch available !!) - - in Space.c, add - - - extern int sis900_probe(struct device *dev); - - ... - - #ifdef CONFIG_SIS900 - {sis900_probe,0}, - #endif - - - in Config.in add - - - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - ... //other adapter drivers - tristate 'SiS 900 PCI Fast Ethernet Adapter Support' CONFIG_SIS900 - ... //other adapter drivers - fi - - - - - in Makefile add - - - ifeq ($(CONFIG_SIS900),y) - L_OBJS += sis900.o - else - ifeq ($(CONFIG_SIS900),m) - M_OBJS += sis900.o - endif - endif - - - - - After modifying these files, the driver can be build as described in - the previous section. - - - 7. Known Problems and Bugs - - There are some known problems and bugs. If you find any other bugs - please mail to ollie@sis.com.tw - - 1. AM79C901 HomePNA PHY is not thoroughly tested, there may be some - bugs in the "on the fly" change of transceiver. - - 2. A bug is hidden somewhere in the receive buffer management code, - the bug causes NULL pointer reference in the kernel. This fault is - caught before bad things happen and reported with the message: - - - eth0: NULL pointer encountered in Rx ring, skipping - - - - - which can be viewed with dmesg or cat /var/log/message. - - - 8. Revision History - - - o November 4, 1999, Revision 1.06, Second release, lots of clean up - and optimization. - - o August 8, 1999, Revision 1.05, Initial Public Release - - - 9. Acknowledgements - - This driver was originally derived form Donald Becker's pci-skeleton - and rtl8139 drivers. Donald also provided various suggestion regarded - with improvements made in revision 1.06. - - The 1.05 revision was created by Jim Huang, AMD 79c901 support was - added by Chin-Shan Li. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +SiS 900/7016 Fast Ethernet Device Driver +Ollie Lho +Lei Chun Chang + November 16, 2000. Document Revision: 0.3 + + This document gives some information on installation and usage of SiS + 900/7016 device driver under Linux. + _________________________________________________________________ + _________________________________________________________________ + +Introduction + + This document describes the revision 1.06 and 1.07 of SiS 900/7016 + Fast Ethernet device driver under Linux. The driver is developed by + Silicon Integrated System Corp. and distributed freely under the GNU + General Public License (GPL). The driver can be compiled as a loadable + module and used under Linux kernel version 2.2.x. (rev. 1.06) With + minimal changes, the driver can also be used under 2.3.x and 2.4.x + kernel (rev. 1.07), please see the section called Installation. If you + are intended to use the driver for earlier kernels, you are on your + own. + + The driver is tested with usual TCP/IP applications including FTP, + Telnet, Netscape etc. and is used constantly by the developers. + + Please send all comments/fixes/questions to Lei-Chun Chang. + _________________________________________________________________ + +License + + Copyright (C) 1999 Silicon Integrated System Corp. + + 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 U +SA + _________________________________________________________________ + +Changes + + Changes made in Revision 1.07 + + 1. Separation of sis900.c and sis900.h in order to move most constant + definition to sis900.h (many of those constants were corrected) + 2. Clean up PCI detection, the pci-scan from Donald Becker were not + used, just simple pci_find_*. + 3. MII detection is modified to support multiple mii transceiver. + 4. Bugs in read_eeprom, mdio_* were removed. + 5. Lot of sis900 irrelevant comments were removed/changed and more + comments were added to reflect the real situation. + 6. Clean up of physical/virtual address space mess in buffer + descriptors. + 7. Better transmit/receive error handling. + 8. The driver now uses zero-copy single buffer management scheme to + improve performance. + 9. Names of variables were changed to be more consistent. + 10. Clean up of auo-negotiation and timer code. + 11. Automatic detection and change of PHY on the fly. + 12. Bug in mac probing fixed. + 13. Fix 630E equalier problem by modifying the equalizer workaround + rule. + 14. Support for ICS1893 10/100 Interated PHYceiver. + 15. Support for media select by ifconfig. + _________________________________________________________________ + +Tested Environment + + This driver is developed on the following hardware + + * Intel Celeron 500 with SiS 630 (rev 02) chipset + * SiS 900 (rev 01) and SiS 7016/7014 Fast Ethernet Card + + and tested with these software environments + + * Red Hat Linux version 6.2 + * Linux kernel version 2.4.0 + * Netscape version 4.6 + * NcFTP 3.0.0 beta 18 + * Samba version 2.0.3 + _________________________________________________________________ + +Files in This Package + + In the package you can find these files: + + sis900.c + Driver source file in C + + sis900.h + Header file for sis900.c + + sis900.sgml + DocBook SGML source of the document + + sis900.txt + Driver document in plain text + _________________________________________________________________ + +Installation + + Silicon Integrated System Corp. is cooperating closely with core Linux + Kernel developers. The revisions of SiS 900 driver are distributed by + the usuall channels for kernel tar files and patches. Those kernel tar + files for official kernel and patches for kernel pre-release can be + download at official kernel ftp site and its mirrors. The 1.06 + revision can be found in kernel version later than 2.3.15 and + pre-2.2.14, and 1.07 revision can be found in kernel version 2.4.0. If + you have no prior experience in networking under Linux, please read + Ethernet HOWTO and Networking HOWTO available from Linux Documentation + Project (LDP). + + The driver is bundled in release later than 2.2.11 and 2.3.15 so this + is the most easy case. Be sure you have the appropriate packages for + compiling kernel source. Those packages are listed in Document/Changes + in kernel source distribution. If you have to install the driver other + than those bundled in kernel release, you should have your driver file + sis900.c and sis900.h copied into /usr/src/linux/drivers/net/ first. + There are two alternative ways to install the driver + _________________________________________________________________ + +Building the driver as loadable module + + To build the driver as a loadable kernel module you have to + reconfigure the kernel to activate network support by + +make menuconfig + + Choose "Loadable module support --->", then select "Enable loadable + module support". + + Choose "Network Device Support --->", select "Ethernet (10 or + 100Mbit)". Then select "EISA, VLB, PCI and on board controllers", and + choose "SiS 900/7016 PCI Fast Ethernet Adapter support" to "M". + + After reconfiguring the kernel, you can make the driver module by + +make modules + + The driver should be compiled with no errors. After compiling the + driver, the driver can be installed to proper place by + +make modules_install + + Load the driver into kernel by + +insmod sis900 + + When loading the driver into memory, some information message can be + view by + +dmesg + + or +cat /var/log/message + + If the driver is loaded properly you will have messages similar to + this: + +sis900.c: v1.07.06 11/07/2000 +eth0: SiS 900 PCI Fast Ethernet at 0xd000, IRQ 10, 00:00:e8:83:7f:a4. +eth0: SiS 900 Internal MII PHY transceiver found at address 1. +eth0: Using SiS 900 Internal MII PHY as default + + showing the version of the driver and the results of probing routine. + + Once the driver is loaded, network can be brought up by + +/sbin/ifconfig eth0 IPADDR broadcast BROADCAST netmask NETMASK + + where IPADDR, BROADCAST, NETMASK are your IP address, broadcast + address and netmask respectively. For more information on how to + configure network interface, please refer to Networking HOWTO. + + The link status is also shown by kernel messages. For example, after + the network interface is activated, you may have the message: + +eth0: Media Link On 100mbps full-duplex + + If you try to unplug the twist pair (TP) cable you will get + +eth0: Media Link Off + + indicating that the link is failed. + _________________________________________________________________ + +Building the driver into kernel + + If you want to make the driver into kernel, choose "Y" rather than "M" + on "SiS 900/7016 PCI Fast Ethernet Adapter support" when configuring + the kernel. Build the kernel image in the usual way + +make dep + +make clean + +make bzlilo + + Next time the system reboot, you have the driver in memory. + _________________________________________________________________ + +Known Problems and Bugs + + There are some known problems and bugs. If you find any other bugs + please mail to lcchang@sis.com.tw + + 1. AM79C901 HomePNA PHY is not thoroughly tested, there may be some + bugs in the "on the fly" change of transceiver. + 2. A bug is hidden somewhere in the receive buffer management code, + the bug causes NULL pointer reference in the kernel. This fault is + caught before bad things happen and reported with the message: + eth0: NULL pointer encountered in Rx ring, skipping which can be + viewed with dmesg or cat /var/log/message. + _________________________________________________________________ + +Revision History + + * November 13, 2000, Revision 1.07, seventh release, 630E problem + fixed and furthur clean up. + * November 4, 1999, Revision 1.06, Second release, lots of clean up + and optimization. + * August 8, 1999, Revision 1.05, Initial Public Release + _________________________________________________________________ + +Acknowledgements + + This driver was originally derived form Donald Becker's pci-skeleton + and rtl8139 drivers. Donald also provided various suggestion regarded + with improvements made in revision 1.06. + + The 1.05 revision was created by Jim Huang, AMD 79c901 support was + added by Chin-Shan Li. diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/tulip.txt linux/Documentation/networking/tulip.txt --- v2.4.0-test10/linux/Documentation/networking/tulip.txt Fri Sep 8 12:34:58 2000 +++ linux/Documentation/networking/tulip.txt Tue Nov 7 11:08:09 2000 @@ -1,20 +1,26 @@ Tulip Ethernet Card Driver Maintained by Jeff Garzik -The Tulip driver is developed by Donald Becker and changed by +The Tulip driver was developed by Donald Becker and changed by Takashi Manabe and a cast of thousands. +For 2.4.x and later kernels, the Linux Tulip driver is available at +http://sourceforge.net/projects/tulip/ + This driver is for the Digital "Tulip" Ethernet adapter interface. It should work with most DEC 21*4*-based chips/ethercards, as well as with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX. - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O + The author may be reached as becker@scyld.com, or C/O Center of Excellence in Space Data and Information Sciences Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - Additional information available at - http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html - + Additional information on Donald Becker's tulip.c + is available at http://www.scyld.com/network/tulip.html + + + + Theory of Operation Board Compatibility @@ -24,7 +30,7 @@ single-chip ethernet controllers for PCI. Supported members of the family are the 21040, 21041, 21140, 21140A, 21142, and 21143. Similar work-alike chips from Lite-On, Macronics, ASIX, Compex and other listed below are also -supported. +supported. These chips are used on at least 140 unique PCI board designs. The great number of chips and board designs supported is the reason for the @@ -43,7 +49,7 @@ is usually "autoselect". This should only be overridden when using transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!) for forcing full-duplex when used with old link partners that do not do -autonegotiation. +autonegotiation. Driver operation ================ @@ -142,6 +148,15 @@ Version history =============== +0.9.11 (November 3, 2000): +* Eliminate extra bus accesses when sharing interrupts (prumpf) +* Barrier following ownership descriptor bit flip (prumpf) +* Endianness fixes for >14 addresses in setup frames (prumpf) +* Report link beat to kernel/userspace via netif_carrier_*. (kuznet) +* Better spinlocking in set_rx_mode. +* Fix I/O resource request failure error messages (DaveM catch) +* Handle DMA allocation failure. + 0.9.10 (September 6, 2000): * Simple interrupt mitigation (via jamal) * More PCI ids diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/networking/x25-iface.txt linux/Documentation/networking/x25-iface.txt --- v2.4.0-test10/linux/Documentation/networking/x25-iface.txt Tue Apr 28 14:22:04 1998 +++ linux/Documentation/networking/x25-iface.txt Sat Nov 11 19:02:39 2000 @@ -62,3 +62,62 @@ First Byte = 0x03 LAPB parameters. To be defined. + + + +Possible Problems +================= + +(Henner Eisen, 2000-10-28) + +The X.25 packet layer protocol depends on a reliable datalink service. +The LAPB protocol provides such reliable service. But this reliability +is not preserved by the Linux network device driver interface: + +- With Linux 2.4.x (and above) SMP kernels, packet ordering is not + preserved. Even if a device driver calls netif_rx(skb1) and later + netif_rx(skb2), skb2 might be delivered to the network layer + earlier that skb1. +- Data passed upstream by means of netif_rx() might be dropped by the + kernel if the backlog queue is congested. + +The X.25 packet layer protocol will detect this and reset the virtual +call in question. But many upper layer protocols are not designed to +handle such N-Reset events gracefully. And frequent N-Reset events +will always degrade performance. + +Thus, driver authors should make netif_rx() as reliable as possible: + +SMP re-ordering will not occur if the driver's interrupt handler is +always executed on the same CPU. Thus, + +- Driver authors should use irq affinity for the interrupt handler. + +The probability of packet loss due to backlog congestion can be +reduced by the following measures or a combination thereof: + +(1) Drivers for kernel versions 2.4.x and above should always check the + return value of netif_rx(). If it returns NET_RX_DROP, the + driver's LAPB protocol must not confirm reception of the frame + to the peer. + This will reliably suppress packet loss. The LAPB protocol will + automatically cause the peer to re-transmit the dropped packet + later. + The lapb module interface was modified to support this. Its + data_indication() method should now transparently pass the + netif_rx() return value to the (lapb mopdule) caller. +(2) Drivers for kernel versions 2.2.x should always check the global + variable netdev_dropping when a new frame is received. The driver + should only call netif_rx() if netdev_dropping is zero. Otherwise + the driver should not confirm delivery of the frame and drop it. + Alternatively, the driver can queue the frame internally and call + netif_rx() later when netif_dropping is 0 again. In that case, delivery + confirmation should also be deferred such that the internal queue + cannot grow to much. + This will not reliably avoid packet loss, but the probability + of packet loss in netif_rx() path will be significantly reduced. +(3) Additionally, driver authors might consider to support + CONFIG_NET_HW_FLOWCONTROL. This allows the driver to be woken up + when a previously congested backlog queue becomes empty again. + The driver could uses this for flow-controlling the peer by means + of the LAPB protocol's flow-control service. diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/usb/hotplug.txt linux/Documentation/usb/hotplug.txt --- v2.4.0-test10/linux/Documentation/usb/hotplug.txt Wed Dec 31 16:00:00 1969 +++ linux/Documentation/usb/hotplug.txt Sun Nov 12 20:45:19 2000 @@ -0,0 +1,124 @@ +USB HOTPLUGGING + +In hotpluggable busses like USB (and Cardbus PCI), end-users plug devices +into the bus with power on. In most cases, users expect the devices to become +immediately usable. That means the system must do many things, including: + + - Find a driver that can handle the device. That may involve + loading a kernel module; newer drivers can use modutils to + publish their device (and class) support to user utilities. + + - Bind a driver to that device. That's done using the USB + device driver's probe() routine. + + - Tell other subsystems to configure the new device. Print + queues may need to be enabled, networks brought up, disk + partitions mounted, and so on. In some cases these will + be driver-specific actions. + +This involves a mix of kernel mode and user mode actions. Making devices +be immediately usable means that any user mode actions can't wait for an +administrator to do them: the kernel must trigger them, either passively +(triggering some monitoring daemon to invoke a helper program) or +actively (calling such a user mode helper program directly). + +Those triggered actions must support a system's administrative policies; +such programs are called "policy agents" here. Typically they involve +shell scripts that dispatch to more familiar administration tools. + + +KERNEL HOTPLUG HELPER (/sbin/hotplug) + +When you compile with CONFIG_HOTPLUG, you get a new kernel parameter: +/proc/sys/kernel/hotplug, which normally holds the pathname "/sbin/hotplug". +That parameter names a program which the kernel may invoke at various times. + +The /sbin/hotplug program can be invoked by any subsystem as part of its +reaction to a configuration change, from a thread in that subsystem. +Only one parameter is required: the name of a subsystem being notified of +some kernel event. That name is used as the first key for further event +dispatch; any other argument and environment parameters are specified by +the subsystem making that invocation. + +A reference implementation of a /sbin/hotplug script is available at the +http://www.linux-usb.org website, which works USB for but also knows how to +delegate to any /etc/hotplug/$TYPE.agent policy agent present. + + +USB POLICY AGENT + +The USB subsystem currently invokes /sbin/hotplug when USB devices +are added or removed from system. The invocation is done by the kernel +hub daemon thread [khubd], or else as part of root hub initialization +(done by init, modprobe, kapmd, etc). Its single command line parameter +is the string "usb", and it passes these environment variables: + + ACTION ... "add", "remove" + PRODUCT ... USB vendor, product, and version codes (hex) + TYPE ... device class codes (decimal) + INTERFACE ... interface 0 class codes (decimal) + +If "usbdevfs" is configured, DEVICE and DEVFS are also passed. DEVICE is +the pathname of the device, and is useful for devices with multiple and/or +alternate interfaces that complicate driver selection. + +Currently available policy agent implementations can load drivers for +modules, and can invoke driver-specific setup scripts. The newest ones +leverage USB modutils support. Later agents might unload drivers. + + +USB MODUTILS SUPPORT + +Current versions of modutils will create a "modules.usbmap" file which +contains the entries from each driver's MODULE_DEVICE_TABLE. Such files +can be used by various user mode policy agents to make sure all the right +driver modules get loaded, either at boot time or later. + +See for full information about such table entries; or look +at existing drivers. Each table entry describes one or more criteria to +be used when matching a driver to a device or class of devices. + +A short example, for a driver that supports several specific USB devices +and their quirks, might have a MODULE_DEVICE_TABLE like this: + + static const struct usb_device_id mydriver_id_table = { + { idVendor: 0x9999, idProduct 0xaaaa, driver_info: QUIRK_X }, + { idVendor: 0xbbbb, idProduct 0x8888, driver_info: QUIRK_Y|QUIRK_Z }, + ... + { } /* end with an all-zeroes entry */ + } + MODULE_DEVICE_TABLE (usb, mydriver_id_table); + +Most USB device drivers should pass these tables to the USB subsystem as +well as to the module management subsystem. Not all, though: some driver +frameworks connect using interfaces layered over USB, and so they won't +need such a "struct usb_driver". + +Drivers that connect directly to the USB subsystem should be declared +something like this: + + static struct usb_driver mydriver = { + name: "mydriver", + id_table: mydriver_id_table, + probe: my_probe, + disconnect: my_disconnect, + + /* + if using the usb chardev framework: + minor: MY_USB_MINOR_START, + fops: my_file_ops, + if exposing any operations through usbdevfs: + ioctl: my_ioctl, + */ + } + +When the USB subsystem knows about a driver's device ID table, it's used when +choosing drivers to probe(). The thread doing new device processing checks +drivers' device ID entries from the MODULE_DEVICE_TABLE against interface and +device descriptors for the device. It will only call probe() if there is a +match, and the third argument to probe() will be the entry that matched. + +If you don't provide an id_table for your driver, then your driver may get +probed for each new device; the third parameter to probe() will be null. + + diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt --- v2.4.0-test10/linux/Documentation/usb/ov511.txt Sun Oct 8 10:50:04 2000 +++ linux/Documentation/usb/ov511.txt Sun Nov 12 20:45:18 2000 @@ -5,22 +5,17 @@ Author: Mark McClelland Homepage: http://alpha.dyndns.org/ov511 -NEW IN THIS VERSION: - o Stability improvements - o Support for hue control - o 160x120 mostly working - o OV6620 color problems fixed - o More WebCam 3 detection improvements - INTRODUCTION: This is a driver for the OV511, a USB-only chip used in many "webcam" devices. Any camera using the OV511/OV511+ and the OV7610/20/20AE CCD should work. It supports streaming and capture of color or monochrome video via the Video4Linux -API. Most V4L apps are compatible with it, but a few videoconferencing programs +API. Most V4L apps are compatible with it, but a few video-conferencing programs do not work yet. The following resolutions are supported: 640x480, 448x336, 384x288, 352x288, and 320x240. +If you need more information, please visit the OV511 homepage at the above URL. + WHAT YOU NEED: - If you want to help with the development, get the chip's specification docs at @@ -81,29 +76,6 @@ you get a scrambled image it is likely that you made a mistake in Xawtv.ad. Try setting the size to 320x240 if all else fails. -FAQ: -Q: "Why does the picture have noise and look grainy" -A: This is a problem at low light levels, and may be also due to subtle bugs in - the code. The cause is most likely the OV7610 settings we are currently - using. I am looking into this problem. - -Q: "The driver sometimes says `Failed to read OV7610 ID.' What is the deal?" -A: The I2C code that allows the OV511 to communicate with the camera chip is a - bit flaky right now. This message means that the I2C bus never got - initialized properly, and the camera will most likely not work even if you - disable this warning. Try unloading/reloading the driver or unplugging/re- - plugging the camera if this happens. Also try increasing the i2c_detect_tries - parameter (see below). - -Q: "Why do you bother with this phony camera detection crap? It doesn't do - anything useful!" -A: The main purpose of only supporting known camera models is to force people - with new camera models to tell me about them, so I can assemble the list - above, and so the code can know what CCD chip you have. Right now, nearly all - of the cameras use the OV7610 and consequently I have not put support for - other ones in, so the value of the detection code is questionable. Eventually - though, new CCDs might appear and we will be fortunate to have the detection. - MODULE PARAMETERS: You can set these with: insmod ov511 NAME=VALUE @@ -136,7 +108,7 @@ or so lines higher than the red component. This is only apparent in images with white objects on black backgrounds at 640x480. Setting this to 1 will realign the color planes correctly. NOTE: This is still - experimental and very buggy. You will likely need a fast (500 Mhz) CPU. + experimental and very buggy. You will likely need a fast (500 MHz) CPU. NAME: snapshot TYPE: integer (boolean) @@ -203,15 +175,21 @@ DESC: Prevent apps from timing out if frame is not done in time. This is useful if you are having problems with Xawtv getting "stuck" on a frame when your system is under heavy load. - + + NAME: sensor_gbr + TYPE: boolean + DEFAULT: 0 + DESC: This makes the sensor output GBR422 instead of YUV420. This saves the + driver the trouble of converting YUV to RGB, but it currently does not + work very well (the colors are not quite right) + WORKING FEATURES: - o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, 320x240, and - 160x120 - o RGB24, YUV420, YUV422, YUYV, and YUV422P color + o Color streaming/capture at 640x480, 448x336, 384x288, 352x288, and 320x240 + o RGB24, RGB565, YUV420, YUV422, YUYV, and YUV422P color o Monochrome o Setting/getting of saturation, contrast, brightness, and hue (only some of them work the OV7620 and OV7620AE) - o proc status reporting + o /proc status reporting EXPERIMENTAL FEATURES: o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and @@ -219,6 +197,7 @@ o Snapshot mode (only works with some read() based apps; see below for more) o OV6620 sensor support o GBR422 parsing + o 160x120 TODO: o Fix the noise / grainy image problem. @@ -227,18 +206,19 @@ so we can't really work on that yet. Please kindly inform OmniVision that you would like them to release their specifications to the Linux community. o YUV422 - o Get snapshot mode working with mmap(). o Fix fixFrameRGBoffset(). It is not stable yet with streaming video. - o Get autoadjust disable working o V4L2 support (Probably not until it goes into the kernel) - o Creative WebCam III has problems initializing its sensor. This should be - fixed now, but if you still have problems let me know. o Get rid of the memory management functions (put them in videodev.c??) o Setting of contrast and brightness not working with 7620/7620AE o Driver/camera state save/restore for when USB supports suspend/resume o Unstable on SMP systems o OV7620/OV6620 experience frame corruption with moving objects o OV6620 is too dark + o 176x144 support + o Driver sometimes hangs upon close() with OHCI + o The image should always be written properly to the mmap'ed buffer as long as + the requested image size is at least the minimum size. This will likely + require a rewrite of all the parsing code. HOW TO CONTACT ME: diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt --- v2.4.0-test10/linux/Documentation/usb/usb-serial.txt Sun Aug 13 19:23:19 2000 +++ linux/Documentation/usb/usb-serial.txt Sat Nov 11 18:51:18 2000 @@ -151,6 +151,37 @@ driver. +Belkin USB Serial Adapter F5U103 + + Single port DB-9/PS-2 serial adapter from Belkin with firmware by eTEK Labs. + +Current status: + The following have been tested and work: + Baud rate 300-230400 + Data bits 5-8 + Stop bits 1-2 + Parity N,E,O,M,S + Handshake None, Software (XON/XOFF), Hardware (CTSRTS,CTSDTR)* + Break Set and clear + Line contrl Input/Output query and control ** + + * Hardware input flow control is only enabled for firmware + levels above 2.06. Read source code comments describing Belkin + firmware errata. Hardware output flow control is working for all + firmware versions. + ** Queries of inputs (CTS,DSR,CD,RI) show the last + reported state. Queries of outputs (DTR,RTS) show the last + requested state and may not reflect current state as set by + automatic hardware flow control. + +TO DO List: + -- Add true modem contol line query capability. Currently tracks the + states reported by the interrupt and the states requested. + -- Add error reporting back to application for UART error conditions. + -- Add support for flush ioctls. + -- Add everything else that is missing :) + + Generic Serial driver If your device is not one of the above listed devices, compatible with diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST --- v2.4.0-test10/linux/Documentation/video4linux/bttv/CARDLIST Tue Jul 18 22:35:33 2000 +++ linux/Documentation/video4linux/bttv/CARDLIST Sun Nov 12 20:47:19 2000 @@ -48,6 +48,11 @@ card=46 - Zoltrix Genie TV card=47 - Terratec TV/Radio+ card=48 - Dynalink Magic TView + card=49 - GV-BCTV3 + card=50 - Prolink PV-BT878P+4E (PixelView PlayTV PAK) + card=51 - Eagle Wireless Capricorn2 (bt878A) + card=52 - Pinnacle Studio PCTV Pro + card=53 - Typhoon TView RDS tuner.o type=0 - Temic PAL @@ -65,3 +70,4 @@ type=12 - Alps TSBE5 type=13 - Alps TSBC5 type=14 - Temic 4006FH5 + type=15 - Alps TSCH6 diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/video4linux/bttv/Insmod-options linux/Documentation/video4linux/bttv/Insmod-options --- v2.4.0-test10/linux/Documentation/video4linux/bttv/Insmod-options Tue Jul 18 22:35:33 2000 +++ linux/Documentation/video4linux/bttv/Insmod-options Sun Nov 12 20:47:19 2000 @@ -23,11 +23,19 @@ at the hardware). default is 1. bttv_debug=0/1 debug messages (for capture). default is 0 (off). + irq_debug=0/1 irq handler debug messages. + default is 0 (off). gbuffers=2-64 number of capture buffers for mmap'ed capture. default is 2. gbufsize= size of capture buffers. default and maximum value is 0x208000 (~2MB) + bttv_gpio=0/1 + gpiomask= + audioall= + audiomux= + See Sound-FAQ for a detailed description. + remap, card, radio and pll accept up to four comma-separated arguments (for multiple boards). @@ -54,6 +62,19 @@ new, experimental module which is supported to provide a single driver for all simple i2c audio control chips (tda/tea*). + insmod args: + tda8425 = 1 enable/disable the support for the + tda9840 = 1 various chips. + tda9850 = 1 The tea6300 can't be autodetected and is + tda9855 = 1 therefore off by default, if you have + tda9873 = 1 this one on your card (STB uses these) + tea6300 = 0 you have to enable it explicitly. + tea6420 = 1 The two tda985x chips use the same i2c + pic16c54 = 1 address and can't be disturgished from + each other, you might have to disable + the wrong one. + debug = 1 print debug messages + msp3400.o The driver for the msp34xx sound processor chips. If you have a stereo card, you probably want to insmod this one. @@ -72,7 +93,7 @@ should improve things for french people, the carrier autoscan seems to work with FM only... -tea6300.o +tea6300.o - OBSOLETE (use tvaudio instead) The driver for the tea6300 fader chip. If you have a stereo card and the msp3400.o doesn't work, you might want to try this one. This chip is seen on most STB TV/FM cards (usually from @@ -81,7 +102,7 @@ insmod args: debug=1 print some debug info to the syslog. -tda8425.o +tda8425.o - OBSOLETE (use tvaudio instead) The driver for the tda8425 fader chip. This driver used to be part of bttv.c, so if your sound used to work but does not anymore, try loading this module. @@ -89,7 +110,7 @@ insmod args: debug=1 print some debug info to the syslog. -tda985x.o +tda985x.o - OBSOLETE (use tvaudio instead) The driver for the tda9850/55 audio chips. insmod args: diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/video4linux/bttv/README linux/Documentation/video4linux/bttv/README --- v2.4.0-test10/linux/Documentation/video4linux/bttv/README Sun Mar 19 19:11:37 2000 +++ linux/Documentation/video4linux/bttv/README Sun Nov 12 20:47:19 2000 @@ -1,4 +1,8 @@ +IMPORTANT: Don't send me mails with images attached unless I ask you +to do so. Mails with images attached will go to /dev/null unseen. + + Release notes for bttv-0.7.x ============================ @@ -17,7 +21,7 @@ CONFIG_I2C_ALGOBIT=m The latest bttv version is available here: - http://me.in-berlin.de/~kraxel/bttv.html + http://www.strusel007.de/linux/bttv/ You'll find Ralphs original (mostly outdated) documentation in the ralphs-doc subdirectory. @@ -38,6 +42,8 @@ not, go to /usr/src/linux and run at least "make config". Even better, compile your own kernel, you'll never become a real hacker else ;-) +Note that you have to turn on video4linux support (CONFIG_VIDEO_DEV) +in the kernel to get the videodev.o module which is required by bttv. Make bttv work with your card @@ -66,7 +72,8 @@ specified the wrong (or no) card type. A list of supported cards is in CARDLIST. -If your card isn't listed in CARDLIST, you should read the Sound-FAQ. +If your card isn't listed in CARDLIST or if you have trouble making +audio work, you should read the Sound-FAQ. Still doesn't work? diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/video4linux/bttv/Sound-FAQ linux/Documentation/video4linux/bttv/Sound-FAQ --- v2.4.0-test10/linux/Documentation/video4linux/bttv/Sound-FAQ Thu Jan 6 14:46:18 2000 +++ linux/Documentation/video4linux/bttv/Sound-FAQ Sun Nov 12 20:47:19 2000 @@ -8,12 +8,12 @@ sound is handled in slightly different ways on each board. To handle the grabber boards correctly, there is a array tvcards[] in -bttv.c, which holds the informations required for each board. Sound -will work only, if the correct entry is used (for video it often makes -no difference). The bttv driver prints a line to the kernel log, -telling which card type is used. Like this one: +bttv-cards.c, which holds the informations required for each board. +Sound will work only, if the correct entry is used (for video it often +makes no difference). The bttv driver prints a line to the kernel +log, telling which card type is used. Like this one: - bttv0: model: BT848(Hauppauge old) + bttv0: model: BT848(Hauppauge old) [autodetected] You should verify this is correct. If it is'nt, you have to pass the correct board type as insmod argument, "insmod bttv card=2" for @@ -32,7 +32,7 @@ Of course you need a correctly installed soundcard unless you have the speakers connected directly to the grabber board. Hint: check the -mixer settings too... +mixer settings too. ALSA for example has everything muted by default. How sound works in detail @@ -48,42 +48,64 @@ you can get/set the status if these pins. They can be used for input and output. -All grabber board vendors use these pins to control an external chip +Most grabber board vendors use these pins to control an external chip which does the sound routing. But every board is a little different. These pins are also used by some companies to drive remote control -receiver chips. +receiver chips. Some boards use the i2c bus instead of the gpio pins +to connect the mux chip. As mentioned above, there is a array which holds the required informations for each known board. You basically have to create a new -line for your board. What is in there: +line for your board. The important fields are these two: struct tvcard { - char *name; - int inputs; /* number of video inputs */ - int tuner; /* which of them is the tuner */ - int svhs; /* which of them is the svhs input */ + [ ... ] u32 gpiomask; - u32 muxsel[8]; /* video mux */ - u32 audiomux[6]; /* audio mux: Tuner, Radio, external, internal, mute, stereo */ - u32 gpiomask2; /* GPIO MUX mask (this is video) */ + u32 audiomux[5]; /* audio mux: tuner, radio, external, internal, mute */ }; -gpiomask has all bits set which are used to control the audio mux. -This value basically goes to the gpio output enable register. It is -also used to mask bits when switching the audio mux (which is done by -read-modify-write on the gpio data register). +gpiomask specifies which pins are used to control the audio mux chip. +The corresponding bits in the output enable register +(BT848_GPIO_OUT_EN) will be set as these pins must be driven by the +bt848 chip. + +The audiomux[] array holds the data values for the different inputs +(i.e. which pins must be high/low for tuner/mute/...). This will be +written to the data register (BT848_GPIO_DATA) to switch the audio +mux. + What you have to do is figure out the correct values for gpiomask and the audiomux array. If you have Windows and the drivers four your card installed, you might to check out if you can read these registers values used by the windows driver. A tool to do this is available -from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil. There is -some #ifdef'ed code in bttv.c (search for "new card") which prints -these values before board initialization, this might help too: boot -win, start tv app, softboot (loadlin) into linux and load bttv with -this enabled. If you hav'nt Windows installed, this is a trial and -error game... +from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil (doesn't +work with bt878 boards according to some reports I received). You +might also dig around in the *.ini files of the Windows applications. +You can have a look at the board to see which of the gpio pins are +connected at all and then start trial-and-error ... + + +Starting with release 0.7.41 bttv has a number of insmod options to +make the gpio debugging easier: + +bttv_gpio=0/1 enable/disable gpio debug messages +gpiomask=n set the gpiomask value +audiomux=i,j,... set the values of the audiomux array +audioall=a set the values of the audiomux array (one + value for all array elements, useful to check + out which effect the particular value has). + +The messages printed with bttv_gpio=1 look like this: + + bttv0: gpio: en=00000027, out=00000024 in=00ffffd8 [audio: off] + +en = output _en_able register (BT848_GPIO_OUT_EN) +out = _out_put bits of the data register (BT848_GPIO_DATA), + i.e. BT848_GPIO_DATA & BT848_GPIO_OUT_EN +in = _in_put bits of the data register, + i.e. BT848_GPIO_DATA & ~BT848_GPIO_OUT_EN Good luck, diff -u --recursive --new-file v2.4.0-test10/linux/Documentation/video4linux/bttv/Specs linux/Documentation/video4linux/bttv/Specs --- v2.4.0-test10/linux/Documentation/video4linux/bttv/Specs Wed Dec 31 16:00:00 1969 +++ linux/Documentation/video4linux/bttv/Specs Sun Nov 12 20:47:19 2000 @@ -0,0 +1,3 @@ +Philips http://www.Semiconductors.COM/pip/ +Conexant http://www.conexant.com/techinfo/default.asp +Micronas http://www.micronas.de/pages/product_documentation/index.html diff -u --recursive --new-file v2.4.0-test10/linux/MAINTAINERS linux/MAINTAINERS --- v2.4.0-test10/linux/MAINTAINERS Tue Oct 31 12:42:25 2000 +++ linux/MAINTAINERS Fri Nov 17 16:45:23 2000 @@ -353,6 +353,12 @@ L: digilnux@dgii.com S: Maintained +DIRECTORY NOTIFICATION +P: Stephen Rothwell +M: sfr@linuxcare.com.au +L: linux-kernel@vger.kernel.org +S: Supported + DISK GEOMETRY AND PARTITION HANDLING P: Andries Brouwer M: aeb@veritas.com @@ -373,6 +379,12 @@ L: blinux-list@redhat.com S: Maintained +DRM DRIVERS +P: Rik Faith +M: faith@valinux.com +L: dri-devel@lists.sourceforge.net +S: Supported + EATA-DMA SCSI DRIVER P: Michael Neuffer M: mike@i-Connect.Net @@ -411,9 +423,9 @@ ETHERNET BRIDGE P: Lennert Buytenhek -M: buytenh@openrock.net -L: bridge@openrock.net -W: http://openrock.net/bridge +M: buytenh@gnu.org +L: bridge@math.leidenuniv.nl +W: http://www.math.leidenuniv.nl/~buytenh/bridge S: Maintained ETHERTEAM 16I DRIVER @@ -1239,8 +1251,9 @@ S: Maintained USB SUBSYSTEM -P: Randy Dunlap -M: randy.dunlap@intel.com +P: Johannes Erdfelt +M: jerdfelt@valinux.com +M: johannes@erdfelt.com L: linux-usb-users@lists.sourceforge.net L: linux-usb-devel@lists.sourceforge.net W: http://www.linux-usb.org @@ -1329,6 +1342,14 @@ L: linux-usb-devel@lists.sourceforge.net S: Maintained W: http://www.kroah.com/linux-usb/ + +USB SERIAL BELKIN F5U103 DRIVER +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 MASS STORAGE DRIVER P: Matthew Dharm diff -u --recursive --new-file v2.4.0-test10/linux/Makefile linux/Makefile --- v2.4.0-test10/linux/Makefile Tue Oct 31 12:42:25 2000 +++ linux/Makefile Fri Nov 17 09:47:41 2000 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -test10 +EXTRAVERSION = -test11 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -180,6 +180,52 @@ DRIVERS += $(DRIVERS-y) + +# files removed with 'make clean' +CLEAN_FILES = \ + kernel/ksyms.lst include/linux/compile.h \ + vmlinux System.map \ + .tmp* \ + drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c \ + drivers/char/conmakehash \ + drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist \ + drivers/zorro/devlist.h drivers/zorro/gen-devlist \ + drivers/sound/bin2hex drivers/sound/hex2hex \ + drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} \ + net/khttpd/make_times_h \ + net/khttpd/times.h \ + submenu* +# directories removed with 'make clean' +CLEAN_DIRS = \ + modules + +# files removed with 'make mrproper' +MRPROPER_FILES = \ + include/linux/autoconf.h include/linux/version.h \ + drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h \ + 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 \ + drivers/sound/pndsperm.c \ + drivers/sound/pndspini.c \ + drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw \ + .version .config* config.in config.old \ + scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp \ + scripts/lxdialog/*.o scripts/lxdialog/lxdialog \ + .menuconfig.log \ + include/asm \ + .hdepend scripts/mkdep scripts/split-include scripts/docproc \ + $(TOPDIR)/include/linux/modversions.h +# directories removed with 'make mrproper' +MRPROPER_DIRS = \ + include/config \ + $(TOPDIR)/include/linux/modules + + include arch/$(ARCH)/Makefile export CPPFLAGS CFLAGS AFLAGS @@ -206,7 +252,7 @@ $(LIBS) \ --end-group \ -o vmlinux - $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map + $(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aUw] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map symlinks: rm -f include/asm @@ -355,49 +401,18 @@ endif clean: archclean - rm -f kernel/ksyms.lst include/linux/compile.h - find . -name '*.[oas]' -type f -print | grep -v lxdialog/ | xargs rm -f - rm -f core `find . -type f -name 'core' -print` - rm -f core `find . -type f -name '.*.flags' -print` - rm -f vmlinux System.map - rm -f .tmp* - rm -f drivers/char/consolemap_deftbl.c drivers/video/promcon_tbl.c - rm -f drivers/char/conmakehash - rm -f drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist - rm -f drivers/zorro/devlist.h drivers/zorro/gen-devlist - rm -f drivers/sound/bin2hex drivers/sound/hex2hex - rm -f drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} - rm -f net/khttpd/make_times_h - rm -f net/khttpd/times.h - rm -f submenu* - rm -rf modules + find . \( -name '*.[oas]' -o -name core -o -name '.*.flags' \) -type f -print \ + | grep -v lxdialog/ | xargs rm -f + rm -f $(CLEAN_FILES) + rm -rf $(CLEAN_DIRS) $(MAKE) -C Documentation/DocBook clean mrproper: clean archmrproper - rm -f include/linux/autoconf.h include/linux/version.h - rm -f drivers/net/hamradio/soundmodem/sm_tbl_{afsk1200,afsk2666,fsk9600}.h - rm -f drivers/net/hamradio/soundmodem/sm_tbl_{hapn4800,psk4800}.h - rm -f drivers/net/hamradio/soundmodem/sm_tbl_{afsk2400_7,afsk2400_8}.h - rm -f drivers/net/hamradio/soundmodem/gentbl - rm -f drivers/char/hfmodem/gentbl drivers/char/hfmodem/tables.h - rm -f drivers/sound/*_boot.h drivers/sound/.*.boot - rm -f drivers/sound/msndinit.c - rm -f drivers/sound/msndperm.c - rm -f drivers/sound/pndsperm.c - rm -f drivers/sound/pndspini.c - rm -f drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw - rm -f .version .config* config.in config.old - rm -f scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp - rm -f scripts/lxdialog/*.o scripts/lxdialog/lxdialog - rm -f .menuconfig.log - rm -f include/asm - rm -rf include/config - rm -f .depend `find . -type f -name .depend -print` - rm -f core `find . -type f -size 0 -print` - rm -f .hdepend scripts/mkdep scripts/split-include scripts/docproc - rm -f $(TOPDIR)/include/linux/modversions.h - rm -rf $(TOPDIR)/include/linux/modules + find . \( -size 0 -o -name .depend \) -type f -print | xargs rm -f + rm -f $(MRPROPER_FILES) + rm -rf $(MRPROPER_DIRS) $(MAKE) -C Documentation/DocBook mrproper + distclean: mrproper rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \ -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \ diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/config.in linux/arch/alpha/config.in --- v2.4.0-test10/linux/arch/alpha/config.in Tue Oct 31 12:42:25 2000 +++ linux/arch/alpha/config.in Thu Nov 16 12:51:28 2000 @@ -63,12 +63,13 @@ unset CONFIG_ALPHA_TSUNAMI CONFIG_ALPHA_MCPCIA unset CONFIG_ALPHA_IRONGATE unset CONFIG_ALPHA_BROKEN_IRQ_MASK -unset CONFIG_ALPHA_LARGE_VMALLOC # Most of these machines have ISA slots; not exactly sure which don't, # and this doesn't activate hordes of code, so do it always. define_bool CONFIG_ISA y +define_bool CONFIG_EISA y define_bool CONFIG_SBUS n +define_bool CONFIG_MCA n if [ "$CONFIG_ALPHA_JENSEN" = "y" ] then @@ -214,6 +215,8 @@ -o "$CONFIG_ALPHA_WILDFIRE" = "y" -o "$CONFIG_ALPHA_TITAN" = "y" ] then bool 'Large VMALLOC support' CONFIG_ALPHA_LARGE_VMALLOC +else + define_bool CONFIG_ALPHA_LARGE_VMALLOC n fi source drivers/pci/Config.in diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c --- v2.4.0-test10/linux/arch/alpha/kernel/alpha_ksyms.c Fri Aug 4 16:15:38 2000 +++ linux/arch/alpha/kernel/alpha_ksyms.c Sun Nov 12 19:27:11 2000 @@ -160,15 +160,20 @@ EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__strnlen_user); -/* - * The following are specially called from the semaphore assembly stubs. - */ -EXPORT_SYMBOL_NOVERS(__down_failed); -EXPORT_SYMBOL_NOVERS(__down_failed_interruptible); -EXPORT_SYMBOL_NOVERS(__up_wakeup); -EXPORT_SYMBOL_NOVERS(__down_read_failed); -EXPORT_SYMBOL_NOVERS(__down_write_failed); -EXPORT_SYMBOL_NOVERS(__rwsem_wake); +/* Semaphore helper functions. */ +EXPORT_SYMBOL(__down_failed); +EXPORT_SYMBOL(__down_failed_interruptible); +EXPORT_SYMBOL(__up_wakeup); +EXPORT_SYMBOL(down); +EXPORT_SYMBOL(down_interruptible); +EXPORT_SYMBOL(up); +EXPORT_SYMBOL(__down_read_failed); +EXPORT_SYMBOL(__down_write_failed); +EXPORT_SYMBOL(__rwsem_wake); +EXPORT_SYMBOL(down_read); +EXPORT_SYMBOL(down_write); +EXPORT_SYMBOL(up_read); +EXPORT_SYMBOL(up_write); /* * SMP-specific symbols. diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c --- v2.4.0-test10/linux/arch/alpha/kernel/irq.c Wed Jun 21 22:30:59 2000 +++ linux/arch/alpha/kernel/irq.c Fri Nov 17 08:47:05 2000 @@ -747,7 +747,7 @@ unsigned int mask; mask = 0; - for (i = 0; i < 16; i++) { + for (i = 0; i < NR_IRQS; i++) { irq_desc_t *desc = irq_desc + i; unsigned int status; @@ -755,8 +755,11 @@ status = desc->status; if (status & IRQ_AUTODETECT) { - if (!(status & IRQ_WAITING)) - mask |= 1 << i; + /* We only react to ISA interrupts */ + if (!(status & IRQ_WAITING)) { + if (i < 16) + mask |= 1 << i; + } desc->status = status & ~IRQ_AUTODETECT; desc->handler->shutdown(i); diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/kernel/semaphore.c linux/arch/alpha/kernel/semaphore.c --- v2.4.0-test10/linux/arch/alpha/kernel/semaphore.c Thu Feb 24 22:36:04 2000 +++ linux/arch/alpha/kernel/semaphore.c Sun Nov 12 19:31:11 2000 @@ -1,139 +1,267 @@ /* - * Generic semaphore code. Buyer beware. Do your own - * specific changes in + * Alpha semaphore implementation. + * + * (C) Copyright 1996 Linus Torvalds + * (C) Copyright 1999, 2000 Richard Henderson */ #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. + * + * 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. + * 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. + * 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. + * 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. + * 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. + * 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 + * 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 + * 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_VAR \ - struct task_struct *tsk = current; \ - wait_queue_t wait; \ - init_waitqueue_entry(&wait, tsk) - -#define DOWN_HEAD(task_state) \ - \ - \ - tsk->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) \ - tsk->state = (task_state); \ - } \ - tsk->state = TASK_RUNNING; \ - remove_wait_queue(&sem->wait, &wait) - -void -__down(struct semaphore * sem) -{ - DOWN_VAR; - DOWN_HEAD(TASK_UNINTERRUPTIBLE); - - if (waking_non_zero(sem)) - break; - schedule(); +void +__down_failed(struct semaphore *sem) +{ + DECLARE_WAITQUEUE(wait, current); - DOWN_TAIL(TASK_UNINTERRUPTIBLE); +#if DEBUG_SEMAPHORE + printk("%s(%d): down failed(%p)\n", + current->comm, current->pid, sem); +#endif + + current->state = TASK_UNINTERRUPTIBLE; + wmb(); + add_wait_queue_exclusive(&sem->wait, &wait); + + /* At this point we know that sem->count is negative. In order + to avoid racing with __up, we must check for wakeup before + going to sleep the first time. */ + + while (1) { + long ret, tmp; + + /* An atomic conditional decrement of sem->waking. */ + __asm__ __volatile__( + "1: ldl_l %1,%2\n" + " blt %1,2f\n" + " subl %1,1,%0\n" + " stl_c %0,%2\n" + " beq %0,3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=r"(ret), "=&r"(tmp), "=m"(sem->waking) + : "0"(0)); + + if (ret) + break; + + schedule(); + set_task_state(current, TASK_UNINTERRUPTIBLE); + } + + remove_wait_queue(&sem->wait, &wait); + current->state = TASK_RUNNING; + +#if DEBUG_SEMAPHORE + printk("%s(%d): down acquired(%p)\n", + current->comm, current->pid, sem); +#endif } int -__down_interruptible(struct semaphore * sem) +__down_failed_interruptible(struct semaphore *sem) { - int ret = 0; - DOWN_VAR; - DOWN_HEAD(TASK_INTERRUPTIBLE); - - ret = waking_non_zero_interruptible(sem, tsk); - if (ret) - { - if (ret == 1) - /* ret != 0 only if we get interrupted -arca */ - ret = 0; - break; + DECLARE_WAITQUEUE(wait, current); + long ret; + +#if DEBUG_SEMAPHORE + printk("%s(%d): down failed(%p)\n", + current->comm, current->pid, sem); +#endif + + current->state = TASK_INTERRUPTIBLE; + wmb(); + add_wait_queue_exclusive(&sem->wait, &wait); + + while (1) { + long tmp, tmp2, tmp3; + + /* We must undo the sem->count down_interruptible decrement + simultaneously and atomicly with the sem->waking + adjustment, otherwise we can race with __up. This is + accomplished by doing a 64-bit ll/sc on two 32-bit words. + + "Equivalent" C. Note that we have to do this all without + (taken) branches in order to be a valid ll/sc sequence. + + do { + tmp = ldq_l; + ret = 0; + if (tmp >= 0) { // waking >= 0 + tmp += 0xffffffff00000000; // waking -= 1 + ret = 1; + } + else if (pending) { + // count += 1, but since -1 + 1 carries into the + // high word, we have to be more careful here. + tmp = (tmp & 0xffffffff00000000) + | ((tmp + 1) & 0x00000000ffffffff); + ret = -EINTR; + } + tmp = stq_c = tmp; + } while (tmp == 0); + */ + + __asm__ __volatile__( + "1: ldq_l %1,%4\n" + " lda %0,0\n" + " cmovne %5,%6,%0\n" + " addq %1,1,%2\n" + " and %1,%7,%3\n" + " andnot %2,%7,%2\n" + " cmovge %1,1,%0\n" + " or %3,%2,%2\n" + " addq %1,%7,%3\n" + " cmovne %5,%2,%1\n" + " cmovge %2,%3,%1\n" + " stq_c %1,%4\n" + " beq %1,3f\n" + "2:\n" + ".subsection 2\n" + "3: br 1b\n" + ".previous" + : "=&r"(ret), "=&r"(tmp), "=&r"(tmp2), + "=&r"(tmp3), "=m"(*sem) + : "r"(signal_pending(current)), "r"(-EINTR), + "r"(0xffffffff00000000)); + + /* At this point we have ret + 1 got the lock + 0 go to sleep + -EINTR interrupted */ + if (ret != 0) + break; + + schedule(); + set_task_state(current, TASK_INTERRUPTIBLE); } - schedule(); - DOWN_TAIL(TASK_INTERRUPTIBLE); - return ret; + remove_wait_queue(&sem->wait, &wait); + current->state = TASK_RUNNING; + wake_up(&sem->wait); + +#if DEBUG_SEMAPHORE + printk("%s(%d): down %s(%p)\n", + current->comm, current->pid, + (ret < 0 ? "interrupted" : "acquired"), sem); +#endif + + /* Convert "got the lock" to 0==success. */ + return (ret < 0 ? ret : 0); +} + +void +__up_wakeup(struct semaphore *sem) +{ + wake_up(&sem->wait); +} + +void +down(struct semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif +#if DEBUG_SEMAPHORE + printk("%s(%d): down(%p) from %p\n", + current->comm, current->pid, sem, + atomic_read(&sem->count), __builtin_return_address(0)); +#endif + __down(sem); } int -__down_trylock(struct semaphore * sem) +down_interruptible(struct semaphore *sem) { - return waking_non_zero_trylock(sem); +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif +#if DEBUG_SEMAPHORE + printk("%s(%d): down(%p) from %p\n", + current->comm, current->pid, sem, + atomic_read(&sem->count), __builtin_return_address(0)); +#endif + return __down_interruptible(sem); +} + +int +down_trylock(struct semaphore *sem) +{ + int ret; + +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + + ret = __down_trylock(sem); + +#if DEBUG_SEMAPHORE + printk("%s(%d): down_trylock %s from %p\n", + current->comm, current->pid, + ret ? "failed" : "acquired", + __builtin_return_address(0)); +#endif + + return ret; +} + +void +up(struct semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif +#if DEBUG_SEMAPHORE + printk("%s(%d): up(%p) from %p\n", + current->comm, current->pid, sem, + atomic_read(&sem->count), __builtin_return_address(0)); +#endif + __up(sem); } @@ -142,124 +270,106 @@ */ void -__down_read(struct rw_semaphore *sem, int count) +__down_read_failed(struct rw_semaphore *sem, int count) { - long tmp; - DOWN_VAR; + DECLARE_WAITQUEUE(wait, current); retry_down: if (count < 0) { - /* Wait for the lock to become unbiased. Readers - are non-exclusive. */ + /* Waiting on multiple readers and/or writers. */ - /* This takes care of granting the lock. */ - up_read(sem); + /* Undo the acquisition we started in down_read. */ + atomic_inc(&sem->count); + current->state = TASK_UNINTERRUPTIBLE; + wmb(); add_wait_queue(&sem->wait, &wait); - while (sem->count < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - if (sem->count >= 0) - break; + mb(); + while (atomic_read(&sem->count) < 0) { schedule(); + set_task_state(current, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; + current->state = TASK_RUNNING; - __asm __volatile ( - " mb\n" - "1: ldl_l %0,%1\n" - " subl %0,1,%2\n" - " subl %0,1,%0\n" - " stl_c %2,%1\n" - " bne %2,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=r"(count), "=m"(sem->count), "=r"(tmp) - : : "memory"); + mb(); + count = atomic_dec_return(&sem->count); if (count <= 0) goto retry_down; } else { + /* Waiting on exactly one writer. */ + + current->state = TASK_UNINTERRUPTIBLE; + wmb(); add_wait_queue(&sem->wait, &wait); + mb(); - while (1) { - if (test_and_clear_bit(0, &sem->granted)) - break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - if ((sem->granted & 1) == 0) - schedule(); + while (!test_and_clear_bit(0, &sem->granted)) { + schedule(); + set_task_state(current, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; + current->state = TASK_RUNNING; } } void -__down_write(struct rw_semaphore *sem, int count) +__down_write_failed(struct rw_semaphore *sem, int count) { - long tmp; - DOWN_VAR; + DECLARE_WAITQUEUE(wait, current); retry_down: if (count + RW_LOCK_BIAS < 0) { - up_write(sem); + /* Waiting on multiple readers and/or writers. */ + /* Undo the acquisition we started in down_write. */ + atomic_add(RW_LOCK_BIAS, &sem->count); + + current->state = TASK_UNINTERRUPTIBLE; + wmb(); add_wait_queue_exclusive(&sem->wait, &wait); + mb(); - while (sem->count < 0) { - set_task_state(tsk, (TASK_UNINTERRUPTIBLE - | TASK_EXCLUSIVE)); - if (sem->count >= RW_LOCK_BIAS) - break; + while (atomic_read(&sem->count) + RW_LOCK_BIAS < 0) { schedule(); + set_task_state(current, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->wait, &wait); - tsk->state = TASK_RUNNING; + current->state = TASK_RUNNING; - __asm __volatile ( - " mb\n" - "1: ldl_l %0,%1\n" - " ldah %2,%3(%0)\n" - " ldah %0,%3(%0)\n" - " stl_c %2,%1\n" - " bne %2,2f\n" - ".subsection 2\n" - "2: br 1b\n" - ".previous" - : "=r"(count), "=m"(sem->count), "=r"(tmp) - : "i"(-(RW_LOCK_BIAS >> 16)) - : "memory"); + count = atomic_sub_return(RW_LOCK_BIAS, &sem->count); if (count != 0) goto retry_down; } else { - /* Put ourselves at the end of the list. */ - add_wait_queue_exclusive(&sem->write_bias_wait, &wait); + /* Waiting on exactly one writer. */ + + current->state = TASK_UNINTERRUPTIBLE; + wmb(); + add_wait_queue_exclusive(&sem->wait, &wait); + mb(); - while (1) { - if (test_and_clear_bit(1, &sem->granted)) - break; - set_task_state(tsk, (TASK_UNINTERRUPTIBLE - | TASK_EXCLUSIVE)); - if ((sem->granted & 2) == 0) - schedule(); + while (!test_and_clear_bit(1, &sem->granted)) { + schedule(); + set_task_state(current, TASK_UNINTERRUPTIBLE); } remove_wait_queue(&sem->write_bias_wait, &wait); - tsk->state = TASK_RUNNING; + 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 (sem->count >= 0) + count = atomic_read(&sem->count); + if (__builtin_expect(count >= 0, 0)) wake_up(&sem->wait); } } void -__do_rwsem_wake(struct rw_semaphore *sem, int readers) +__rwsem_wake(struct rw_semaphore *sem, int readers) { if (readers) { if (test_and_set_bit(0, &sem->granted)) @@ -270,4 +380,68 @@ BUG(); wake_up(&sem->write_bias_wait); } +} + +void +down_read(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + __down_read(sem); +#if WAITQUEUE_DEBUG + if (sem->granted & 2) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + atomic_inc(&sem->readers); +#endif +} + +void +down_write(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); +#endif + __down_write(sem); +#if WAITQUEUE_DEBUG + if (sem->granted & 3) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + if (atomic_read(&sem->readers)) + BUG(); + atomic_inc(&sem->writers); +#endif +} + +void +up_read(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); + if (sem->granted & 2) + BUG(); + if (atomic_read(&sem->writers)) + BUG(); + atomic_dec(&sem->readers); +#endif + __up_read(sem); +} + +void +up_write(struct rw_semaphore *sem) +{ +#if WAITQUEUE_DEBUG + CHECK_MAGIC(sem->__magic); + if (sem->granted & 3) + BUG(); + if (atomic_read(&sem->readers)) + BUG(); + if (atomic_read(&sem->writers) != 1) + BUG(); + atomic_dec(&sem->writers); +#endif + __up_write(sem); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c --- v2.4.0-test10/linux/arch/alpha/kernel/time.c Sun Oct 8 10:50:04 2000 +++ linux/arch/alpha/kernel/time.c Sun Nov 12 19:27:11 2000 @@ -378,6 +378,9 @@ * BUG: This routine does not handle hour overflow properly; it just * sets the minutes. Usually you won't notice until after reboot! */ + +extern int abs(int); + static int set_rtc_mmss(unsigned long nowtime) { diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile --- v2.4.0-test10/linux/arch/alpha/lib/Makefile Tue Oct 31 12:42:25 2000 +++ linux/arch/alpha/lib/Makefile Sun Nov 12 19:27:11 2000 @@ -12,7 +12,7 @@ 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 semaphore.o fpreg.o \ + csum_ipv6_magic.o strcasecmp.o fpreg.o \ callback_srm.o srm_puts.o srm_printk.o lib.a: $(OBJS) diff -u --recursive --new-file v2.4.0-test10/linux/arch/alpha/lib/semaphore.S linux/arch/alpha/lib/semaphore.S --- v2.4.0-test10/linux/arch/alpha/lib/semaphore.S Mon Feb 7 20:09:05 2000 +++ linux/arch/alpha/lib/semaphore.S Wed Dec 31 16:00:00 1969 @@ -1,348 +0,0 @@ -/* - * linux/arch/alpha/lib/semaphore.S - * - * Copyright (C) 1999, 2000 Richard Henderson - */ - -/* - * The semaphore operations have a special calling sequence that - * allow us to do a simpler in-line version of them. These routines - * need to convert that sequence back into the C sequence when - * there is contention on the semaphore. - */ - - .set noat - .set noreorder - .align 4 - -/* __down_failed takes the semaphore in $24, clobbers $24 and $28. */ - - .globl __down_failed - .ent __down_failed -__down_failed: - ldgp $29,0($27) - lda $30, -20*8($30) - stq $28, 0*8($30) - stq $0, 1*8($30) - stq $1, 2*8($30) - stq $2, 3*8($30) - stq $3, 4*8($30) - stq $4, 5*8($30) - stq $5, 6*8($30) - stq $6, 7*8($30) - stq $7, 8*8($30) - stq $16, 9*8($30) - stq $17, 10*8($30) - stq $18, 11*8($30) - stq $19, 12*8($30) - stq $20, 13*8($30) - stq $21, 14*8($30) - stq $22, 15*8($30) - stq $23, 16*8($30) - stq $25, 17*8($30) - stq $26, 18*8($30) - .frame $30, 20*8, $28 - .prologue 1 - - mov $24, $16 - jsr __down - - ldq $28, 0*8($30) - ldq $0, 1*8($30) - ldq $1, 2*8($30) - ldq $2, 3*8($30) - ldq $3, 4*8($30) - ldq $4, 5*8($30) - ldq $5, 6*8($30) - ldq $6, 7*8($30) - ldq $7, 8*8($30) - ldq $16, 9*8($30) - ldq $17, 10*8($30) - ldq $18, 11*8($30) - ldq $19, 12*8($30) - ldq $20, 13*8($30) - ldq $21, 14*8($30) - ldq $22, 15*8($30) - ldq $23, 16*8($30) - ldq $25, 17*8($30) - ldq $26, 18*8($30) - lda $30, 20*8($30) - ret $31, ($28), 0 - .end __down_failed - -/* __down_failed_interruptible takes the semaphore in $24, - clobbers $28, returns success in $24. */ - - .globl __down_failed_interruptible - .ent __down_failed_interruptible -__down_failed_interruptible: - ldgp $29,0($27) - lda $30, -20*8($30) - stq $28, 0*8($30) - stq $0, 1*8($30) - stq $1, 2*8($30) - stq $2, 3*8($30) - stq $3, 4*8($30) - stq $4, 5*8($30) - stq $5, 6*8($30) - stq $6, 7*8($30) - stq $7, 8*8($30) - stq $16, 9*8($30) - stq $17, 10*8($30) - stq $18, 11*8($30) - stq $19, 12*8($30) - stq $20, 13*8($30) - stq $21, 14*8($30) - stq $22, 15*8($30) - stq $23, 16*8($30) - stq $25, 17*8($30) - stq $26, 18*8($30) - .frame $30, 20*8, $28 - .prologue 1 - - mov $24, $16 - jsr __down_interruptible - mov $0, $24 - - ldq $28, 0*8($30) - ldq $0, 1*8($30) - ldq $1, 2*8($30) - ldq $2, 3*8($30) - ldq $3, 4*8($30) - ldq $4, 5*8($30) - ldq $5, 6*8($30) - ldq $6, 7*8($30) - ldq $7, 8*8($30) - ldq $16, 9*8($30) - ldq $17, 10*8($30) - ldq $18, 11*8($30) - ldq $19, 12*8($30) - ldq $20, 13*8($30) - ldq $21, 14*8($30) - ldq $22, 15*8($30) - ldq $23, 16*8($30) - ldq $25, 17*8($30) - ldq $26, 18*8($30) - lda $30, 20*8($30) - ret $31, ($28), 0 - .end __down_failed_interruptible - -/* __up_wakeup takes the semaphore in $24, clobbers $24 and $28. */ - - .globl __up_wakeup - .ent __up_wakeup -__up_wakeup: - ldgp $29,0($27) - lda $30, -20*8($30) - stq $28, 0*8($30) - stq $0, 1*8($30) - stq $1, 2*8($30) - stq $2, 3*8($30) - stq $3, 4*8($30) - stq $4, 5*8($30) - stq $5, 6*8($30) - stq $6, 7*8($30) - stq $7, 8*8($30) - stq $16, 9*8($30) - stq $17, 10*8($30) - stq $18, 11*8($30) - stq $19, 12*8($30) - stq $20, 13*8($30) - stq $21, 14*8($30) - stq $22, 15*8($30) - stq $23, 16*8($30) - stq $25, 17*8($30) - stq $26, 18*8($30) - .frame $30, 20*8, $28 - .prologue 1 - - mov $24, $16 - jsr __up - - ldq $28, 0*8($30) - ldq $0, 1*8($30) - ldq $1, 2*8($30) - ldq $2, 3*8($30) - ldq $3, 4*8($30) - ldq $4, 5*8($30) - ldq $5, 6*8($30) - ldq $6, 7*8($30) - ldq $7, 8*8($30) - ldq $16, 9*8($30) - ldq $17, 10*8($30) - ldq $18, 11*8($30) - ldq $19, 12*8($30) - ldq $20, 13*8($30) - ldq $21, 14*8($30) - ldq $22, 15*8($30) - ldq $23, 16*8($30) - ldq $25, 17*8($30) - ldq $26, 18*8($30) - lda $30, 20*8($30) - ret $31, ($28), 0 - .end __up_wakeup - -/* __down_read_failed takes the semaphore in $24, count in $25; - clobbers $24, $25 and $28. */ - - .globl __down_read_failed - .ent __down_read_failed -__down_read_failed: - ldgp $29,0($27) - lda $30, -18*8($30) - stq $28, 0*8($30) - stq $0, 1*8($30) - stq $1, 2*8($30) - stq $2, 3*8($30) - stq $3, 4*8($30) - stq $4, 5*8($30) - stq $5, 6*8($30) - stq $6, 7*8($30) - stq $7, 8*8($30) - stq $16, 9*8($30) - stq $17, 10*8($30) - stq $18, 11*8($30) - stq $19, 12*8($30) - stq $20, 13*8($30) - stq $21, 14*8($30) - stq $22, 15*8($30) - stq $23, 16*8($30) - stq $26, 17*8($30) - .frame $30, 18*8, $28 - .prologue 1 - - mov $24, $16 - mov $25, $17 - jsr __down_read - - ldq $28, 0*8($30) - ldq $0, 1*8($30) - ldq $1, 2*8($30) - ldq $2, 3*8($30) - ldq $3, 4*8($30) - ldq $4, 5*8($30) - ldq $5, 6*8($30) - ldq $6, 7*8($30) - ldq $7, 8*8($30) - ldq $16, 9*8($30) - ldq $17, 10*8($30) - ldq $18, 11*8($30) - ldq $19, 12*8($30) - ldq $20, 13*8($30) - ldq $21, 14*8($30) - ldq $22, 15*8($30) - ldq $23, 16*8($30) - ldq $26, 17*8($30) - lda $30, 18*8($30) - ret $31, ($28), 0 - .end __down_read_failed - -/* __down_write_failed takes the semaphore in $24, count in $25; - clobbers $24, $25 and $28. */ - - .globl __down_write_failed - .ent __down_write_failed -__down_write_failed: - ldgp $29,0($27) - lda $30, -20*8($30) - stq $28, 0*8($30) - stq $0, 1*8($30) - stq $1, 2*8($30) - stq $2, 3*8($30) - stq $3, 4*8($30) - stq $4, 5*8($30) - stq $5, 6*8($30) - stq $6, 7*8($30) - stq $7, 8*8($30) - stq $16, 9*8($30) - stq $17, 10*8($30) - stq $18, 11*8($30) - stq $19, 12*8($30) - stq $20, 13*8($30) - stq $21, 14*8($30) - stq $22, 15*8($30) - stq $23, 16*8($30) - stq $26, 17*8($30) - .frame $30, 18*8, $28 - .prologue 1 - - mov $24, $16 - mov $25, $17 - jsr __down_write - - ldq $28, 0*8($30) - ldq $0, 1*8($30) - ldq $1, 2*8($30) - ldq $2, 3*8($30) - ldq $3, 4*8($30) - ldq $4, 5*8($30) - ldq $5, 6*8($30) - ldq $6, 7*8($30) - ldq $7, 8*8($30) - ldq $16, 9*8($30) - ldq $17, 10*8($30) - ldq $18, 11*8($30) - ldq $19, 12*8($30) - ldq $20, 13*8($30) - ldq $21, 14*8($30) - ldq $22, 15*8($30) - ldq $23, 16*8($30) - ldq $26, 17*8($30) - lda $30, 18*8($30) - ret $31, ($28), 0 - .end __down_write_failed - -/* __rwsem_wake takes the semaphore in $24, readers in $25; - clobbers $24, $25, and $28. */ - - .globl __rwsem_wake - .ent __rwsem_wake -__rwsem_wake: - ldgp $29,0($27) - lda $30, -18*8($30) - stq $28, 0*8($30) - stq $0, 1*8($30) - stq $1, 2*8($30) - stq $2, 3*8($30) - stq $3, 4*8($30) - stq $4, 5*8($30) - stq $5, 6*8($30) - stq $6, 7*8($30) - stq $7, 8*8($30) - stq $16, 9*8($30) - stq $17, 10*8($30) - stq $18, 11*8($30) - stq $19, 12*8($30) - stq $20, 13*8($30) - stq $21, 14*8($30) - stq $22, 15*8($30) - stq $23, 16*8($30) - stq $26, 17*8($30) - .frame $30, 18*8, $28 - .prologue 1 - - mov $24, $16 - mov $25, $17 - jsr __do_rwsem_wake - - ldq $28, 0*8($30) - ldq $0, 1*8($30) - ldq $1, 2*8($30) - ldq $2, 3*8($30) - ldq $3, 4*8($30) - ldq $4, 5*8($30) - ldq $5, 6*8($30) - ldq $6, 7*8($30) - ldq $7, 8*8($30) - ldq $16, 9*8($30) - ldq $17, 10*8($30) - ldq $18, 11*8($30) - ldq $19, 12*8($30) - ldq $20, 13*8($30) - ldq $21, 14*8($30) - ldq $22, 15*8($30) - ldq $23, 16*8($30) - ldq $26, 17*8($30) - lda $30, 18*8($30) - ret $31, ($28), 0 - .end __rwsem_wake diff -u --recursive --new-file v2.4.0-test10/linux/arch/arm/config.in linux/arch/arm/config.in --- v2.4.0-test10/linux/arch/arm/config.in Tue Oct 31 12:42:25 2000 +++ linux/arch/arm/config.in Thu Nov 16 12:51:28 2000 @@ -5,7 +5,9 @@ mainmenu_name "Linux Kernel Configuration" define_bool CONFIG_ARM y +define_bool CONFIG_EISA n define_bool CONFIG_SBUS n +define_bool CONFIG_MCA n define_bool CONFIG_UID16 y diff -u --recursive --new-file v2.4.0-test10/linux/arch/arm/kernel/semaphore.c linux/arch/arm/kernel/semaphore.c --- v2.4.0-test10/linux/arch/arm/kernel/semaphore.c Tue Oct 31 12:42:25 2000 +++ linux/arch/arm/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -58,7 +58,7 @@ { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -78,7 +78,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -92,7 +92,7 @@ int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -128,7 +128,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -197,7 +197,7 @@ for (;;) { if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!sem->write_bias_granted) schedule(); } @@ -255,7 +255,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/Makefile linux/arch/i386/Makefile --- v2.4.0-test10/linux/arch/i386/Makefile Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/Makefile Thu Nov 16 13:15:20 2000 @@ -54,6 +54,10 @@ CFLAGS += -march=i686 endif +ifdef CONFIG_MPENTIUM4 +CFLAGS += -march=i686 +endif + ifdef CONFIG_MK6 CFLAGS += $(shell if $(CC) -march=k6 -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=k6"; else echo "-march=i586"; fi) endif @@ -63,7 +67,7 @@ endif ifdef CONFIG_MCRUSOE -CFLAGS += -march=i586 +CFLAGS += -march=i686 -malign-functions=0 -malign-jumps=0 -malign-loops=0 endif ifdef CONFIG_MWINCHIPC6 diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/config.in linux/arch/i386/config.in --- v2.4.0-test10/linux/arch/i386/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/config.in Thu Nov 16 12:51:28 2000 @@ -34,6 +34,7 @@ Pentium-MMX CONFIG_M586MMX \ Pentium-Pro/Celeron/Pentium-II CONFIG_M686 \ Pentium-III CONFIG_M686FXSR \ + Pentium-4 CONFIG_MPENTIUM4 \ K6/K6-II/K6-III CONFIG_MK6 \ Athlon/K7 CONFIG_MK7 \ Crusoe CONFIG_MCRUSOE \ @@ -92,6 +93,15 @@ define_bool CONFIG_X86_FXSR y define_bool CONFIG_X86_XMM y fi +if [ "$CONFIG_MPENTIUM4" = "y" ]; then + define_int CONFIG_X86_L1_CACHE_SHIFT 7 + define_bool CONFIG_X86_TSC y + define_bool CONFIG_X86_GOOD_APIC y + define_bool CONFIG_X86_PGE y + define_bool CONFIG_X86_USE_PPRO_CHECKSUM y + define_bool CONFIG_X86_FXSR y + define_bool CONFIG_X86_XMM y +fi if [ "$CONFIG_MK6" = "y" ]; then define_int CONFIG_X86_L1_CACHE_SHIFT 5 define_bool CONFIG_X86_ALIGNMENT_16 y @@ -158,6 +168,7 @@ define_bool CONFIG_X86_LOCAL_APIC y fi fi + if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then define_bool CONFIG_HAVE_DEC_LOCK y fi @@ -194,8 +205,12 @@ source drivers/pci/Config.in +bool 'EISA support' CONFIG_EISA + if [ "$CONFIG_VISWS" != "y" ]; then bool 'MCA support' CONFIG_MCA +else + define_bool CONFIG_MCA n fi bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/defconfig linux/arch/i386/defconfig --- v2.4.0-test10/linux/arch/i386/defconfig Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/defconfig Thu Nov 16 18:20:29 2000 @@ -28,6 +28,7 @@ # CONFIG_M586MMX is not set # CONFIG_M686 is not set CONFIG_M686FXSR=y +# CONFIG_MPENTIUM4 is not set # CONFIG_MK6 is not set # CONFIG_MK7 is not set # CONFIG_MCRUSOE is not set @@ -71,6 +72,7 @@ CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y CONFIG_PCI_NAMES=y +# CONFIG_EISA is not set # CONFIG_MCA is not set CONFIG_HOTPLUG=y @@ -79,6 +81,8 @@ # CONFIG_PCMCIA=y CONFIG_CARDBUS=y +# CONFIG_I82365 is not set +# CONFIG_TCIC is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y @@ -143,11 +147,12 @@ # 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_NET_IPIP is not set # CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set # CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set @@ -359,21 +364,29 @@ 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 is not set +# CONFIG_DE4X5 is not set # CONFIG_DGRS is not set +# CONFIG_DM9102 is not set CONFIG_EEPRO100=y +# CONFIG_EEPRO100_PM 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_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 # diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c --- v2.4.0-test10/linux/arch/i386/kernel/acpi.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/acpi.c Fri Nov 17 17:19:17 2000 @@ -258,6 +258,8 @@ {ACPI_FACP, "facp", &acpi_facp, 0, 0644, NULL, &acpi_do_table}, {ACPI_DSDT, "dsdt", &acpi_dsdt, 0, 0644, NULL, &acpi_do_table}, + + {ACPI_FACS, "facs", &acpi_facs, 0, 0644, NULL, &acpi_do_table}, {ACPI_PM1_ENABLE, "pm1_enable", NULL, 0, @@ -722,12 +724,21 @@ if (!acpi_init_table(&acpi_facp, dt, 1)) { struct acpi_facp *facp = (struct acpi_facp*) acpi_facp.table; + struct acpi_table *facs; // map DSDT if it exists - dt = acpi_map_table(facp->dsdt); - if (acpi_init_table(&acpi_dsdt, dt, 1)) - acpi_unmap_table(dt); - + if ((dt = acpi_map_table(facp->dsdt))) { + if (acpi_init_table(&acpi_dsdt, dt, 1)) + acpi_unmap_table(dt); + } + + /* + * map FACS if it exists + */ + if ((facs = acpi_map_table(facp->facs))) { + if (acpi_init_table(&acpi_facs,facs,1)) + acpi_unmap_table(facs); + } break; } else { diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c --- v2.4.0-test10/linux/arch/i386/kernel/apic.c Sun Oct 8 10:50:06 2000 +++ linux/arch/i386/kernel/apic.c Wed Nov 8 10:18:13 2000 @@ -219,39 +219,6 @@ if (!test_bit(GET_APIC_ID(apic_read(APIC_ID)), &phys_cpu_present_map)) BUG(); - value = apic_read(APIC_SPIV); - value &= ~APIC_VECTOR_MASK; - /* - * Enable APIC - */ - value |= (1<<8); - - /* - * Some unknown Intel IO/APIC (or APIC) errata is biting us with - * certain networking cards. If high frequency interrupts are - * happening on a particular IOAPIC pin, plus the IOAPIC routing - * entry is masked/unmasked at a high rate as well then sooner or - * later IOAPIC line gets 'stuck', no more interrupts are received - * from the device. If focus CPU is disabled then the hang goes - * away, oh well :-( - * - * [ This bug can be reproduced easily with a level-triggered - * PCI Ne2000 networking cards and PII/PIII processors, dual - * BX chipset. ] - */ -#if 0 - /* Enable focus processor (bit==0) */ - value &= ~(1<<9); -#else - /* Disable focus processor (bit==1) */ - value |= (1<<9); -#endif - /* - * Set spurious IRQ vector - */ - value |= SPURIOUS_APIC_VECTOR; - apic_write_around(APIC_SPIV, value); - /* * Set up LVT0, LVT1: * @@ -323,6 +290,42 @@ * Must be "all ones" explicitly for 82489DX. */ apic_write_around(APIC_DFR, 0xffffffff); + + /* + * Now that we are all set up, enable the APIC + */ + value = apic_read(APIC_SPIV); + value &= ~APIC_VECTOR_MASK; + /* + * Enable APIC + */ + value |= (1<<8); + + /* + * Some unknown Intel IO/APIC (or APIC) errata is biting us with + * certain networking cards. If high frequency interrupts are + * happening on a particular IOAPIC pin, plus the IOAPIC routing + * entry is masked/unmasked at a high rate as well then sooner or + * later IOAPIC line gets 'stuck', no more interrupts are received + * from the device. If focus CPU is disabled then the hang goes + * away, oh well :-( + * + * [ This bug can be reproduced easily with a level-triggered + * PCI Ne2000 networking cards and PII/PIII processors, dual + * BX chipset. ] + */ +#if 0 + /* Enable focus processor (bit==0) */ + value &= ~(1<<9); +#else + /* Disable focus processor (bit==1) */ + value |= (1<<9); +#endif + /* + * Set spurious IRQ vector + */ + value |= SPURIOUS_APIC_VECTOR; + apic_write_around(APIC_SPIV, value); } void __init init_apic_mappings(void) diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c --- v2.4.0-test10/linux/arch/i386/kernel/apm.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/apm.c Wed Nov 15 00:41:03 2000 @@ -1126,6 +1126,7 @@ } #endif } + remove_wait_queue(&apm_waitqueue, &wait); } static int check_apm_user(struct apm_user *as, const char *func) @@ -1422,9 +1423,6 @@ kapmd_running = 1; - exit_files(current); /* daemonize doesn't do exit_files */ - current->files = init_task.files; - atomic_inc(¤t->files->count); daemonize(); strcpy(current->comm, "kapm-idled"); @@ -1574,8 +1572,6 @@ &apm_bios_fops }; -#define APM_INIT_ERROR_RETURN return -1 - /* * Just start the APM thread. We do NOT want to do APM BIOS * calls from anything but the APM thread, if for no other reason @@ -1590,7 +1586,7 @@ { if (apm_bios_info.version == 0) { printk(KERN_INFO "apm: BIOS not found.\n"); - APM_INIT_ERROR_RETURN; + return -ENODEV; } printk(KERN_INFO "apm: BIOS version %d.%d Flags 0x%02x (Driver version %s)\n", @@ -1600,7 +1596,7 @@ driver_version); if ((apm_bios_info.flags & APM_32_BIT_SUPPORT) == 0) { printk(KERN_INFO "apm: no 32 bit BIOS support\n"); - APM_INIT_ERROR_RETURN; + return -ENODEV; } /* @@ -1629,15 +1625,15 @@ if (apm_disabled) { printk(KERN_NOTICE "apm: disabled on user request.\n"); - APM_INIT_ERROR_RETURN; + return -ENODEV; } if ((smp_num_cpus > 1) && !power_off) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n"); - APM_INIT_ERROR_RETURN; + return -ENODEV; } if (PM_IS_ACTIVE()) { printk(KERN_NOTICE "apm: overridden by ACPI.\n"); - APM_INIT_ERROR_RETURN; + return -ENODEV; } pm_active = 1; @@ -1686,7 +1682,7 @@ if (smp_num_cpus > 1) { printk(KERN_NOTICE "apm: disabled - APM is not SMP safe (power off active).\n"); - APM_INIT_ERROR_RETURN; + return 0; } misc_register(&apm_device); diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c --- v2.4.0-test10/linux/arch/i386/kernel/bluesmoke.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/bluesmoke.c Sun Nov 12 21:55:50 2000 @@ -10,7 +10,7 @@ static int banks; -void mcheck_fault(void) +void do_machine_check(struct pt_regs * regs, long error_code) { int recover=1; u32 alow, ahigh, high, low; @@ -66,22 +66,19 @@ * This has to be run for each processor */ -void mcheck_init(void) +void mcheck_init(struct cpuinfo_x86 *c) { u32 l, h; int i; - struct cpuinfo_x86 *c; static int done; - c=cpu_data+smp_processor_id(); - - if(c->x86_vendor!=X86_VENDOR_INTEL) + if( c->x86_vendor != X86_VENDOR_INTEL ) return; - if(!(c->x86_capability&X86_FEATURE_MCE)) + if( !test_bit(X86_FEATURE_TSC, &c->x86_capability) ) return; - if(!(c->x86_capability&X86_FEATURE_MCA)) + if( !test_bit(X86_FEATURE_MCA, &c->x86_capability) ) return; /* Ok machine check is available */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S --- v2.4.0-test10/linux/arch/i386/kernel/entry.S Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/entry.S Wed Nov 8 17:09:50 2000 @@ -383,11 +383,6 @@ pushl $ SYMBOL_NAME(do_coprocessor_segment_overrun) jmp error_code -ENTRY(reserved) - pushl $0 - pushl $ SYMBOL_NAME(do_reserved) - jmp error_code - ENTRY(double_fault) pushl $ SYMBOL_NAME(do_double_fault) jmp error_code @@ -418,7 +413,7 @@ ENTRY(machine_check) pushl $0 - pushl $ SYMBOL_NAME(mcheck_fault) + pushl $ SYMBOL_NAME(do_machine_check) jmp error_code ENTRY(spurious_interrupt_bug) diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c --- v2.4.0-test10/linux/arch/i386/kernel/i386_ksyms.c Tue Aug 8 12:35:36 2000 +++ linux/arch/i386/kernel/i386_ksyms.c Sat Nov 11 18:56:57 2000 @@ -49,7 +49,9 @@ /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); +#ifdef CONFIG_EISA EXPORT_SYMBOL(EISA_bus); +#endif EXPORT_SYMBOL(MCA_bus); EXPORT_SYMBOL(__verify_write); EXPORT_SYMBOL(dump_thread); diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c --- v2.4.0-test10/linux/arch/i386/kernel/i387.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/i387.c Fri Nov 3 09:47:48 2000 @@ -442,6 +442,8 @@ if ( HAVE_FXSR ) { __copy_from_user( &tsk->thread.i387.fxsave, (void *)buf, sizeof(struct user_fxsr_struct) ); + /* mxcsr bit 6 and 31-16 must be zero for security reasons */ + tsk->thread.i387.fxsave.mxcsr &= 0xffbf; return 0; } else { return -EIO; diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c --- v2.4.0-test10/linux/arch/i386/kernel/i8259.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/i8259.c Sat Nov 18 20:54:39 2000 @@ -374,7 +374,6 @@ spin_unlock_irqrestore(&i8259A_lock, flags); } -#ifndef CONFIG_VISWS /* * Note that on a 486, we don't want to do a SIGFPE on an irq13 * as the irq is unreliable, and exception 16 works correctly @@ -400,12 +399,13 @@ * New motherboards sometimes make IRQ 13 be a PCI interrupt, * so allow interrupt sharing. */ -static struct irqaction irq13 = { math_error_irq, SA_SHIRQ, 0, "fpu", NULL, NULL }; +static struct irqaction irq13 = { math_error_irq, 0, 0, "fpu", NULL, NULL }; /* * IRQ2 is cascade interrupt to second interrupt controller */ +#ifndef CONFIG_VISWS static struct irqaction irq2 = { no_action, 0, 0, "cascade", NULL, NULL}; #endif @@ -494,6 +494,12 @@ #ifndef CONFIG_VISWS setup_irq(2, &irq2); - setup_irq(13, &irq13); #endif + + /* + * External FPU? Set up irq13 if so, for + * original braindamaged IBM FERR coupling. + */ + if (boot_cpu_data.hard_math && !cpu_has_fpu) + setup_irq(13, &irq13); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c --- v2.4.0-test10/linux/arch/i386/kernel/mpparse.c Sun Oct 8 10:50:06 2000 +++ linux/arch/i386/kernel/mpparse.c Tue Nov 14 21:25:34 2000 @@ -97,6 +97,8 @@ return("Pentium(tm) Pro"); case 0x0F: + if (model == 0x00) + return("Pentium 4(tm)"); if (model == 0x0F) return("Special controller"); } @@ -125,6 +127,44 @@ Dprintk(" 64 bit compare & exchange supported.\n"); if (m->mpc_featureflag&(1<<9)) Dprintk(" Internal APIC present.\n"); + if (m->mpc_featureflag&(1<<11)) + Dprintk(" SEP present.\n"); + if (m->mpc_featureflag&(1<<12)) + Dprintk(" MTRR present.\n"); + if (m->mpc_featureflag&(1<<13)) + Dprintk(" PGE present.\n"); + if (m->mpc_featureflag&(1<<14)) + Dprintk(" MCA present.\n"); + if (m->mpc_featureflag&(1<<15)) + Dprintk(" CMOV present.\n"); + if (m->mpc_featureflag&(1<<16)) + Dprintk(" PAT present.\n"); + if (m->mpc_featureflag&(1<<17)) + Dprintk(" PSE present.\n"); + if (m->mpc_featureflag&(1<<18)) + Dprintk(" PSN present.\n"); + if (m->mpc_featureflag&(1<<19)) + Dprintk(" Cache Line Flush Instruction present.\n"); + /* 20 Reserved */ + if (m->mpc_featureflag&(1<<21)) + Dprintk(" Debug Trace and EMON Store present.\n"); + if (m->mpc_featureflag&(1<<22)) + Dprintk(" ACPI Thermal Throttle Registers present.\n"); + if (m->mpc_featureflag&(1<<23)) + Dprintk(" MMX present.\n"); + if (m->mpc_featureflag&(1<<24)) + Dprintk(" FXSR present.\n"); + if (m->mpc_featureflag&(1<<25)) + Dprintk(" XMM present.\n"); + if (m->mpc_featureflag&(1<<26)) + Dprintk(" Willamette New Instructions present.\n"); + if (m->mpc_featureflag&(1<<27)) + Dprintk(" Self Snoop present.\n"); + /* 28 Reserved */ + if (m->mpc_featureflag&(1<<29)) + Dprintk(" Thermal Monitor present.\n"); + /* 30, 31 Reserved */ + if (m->mpc_cpuflag & CPU_BOOTPROCESSOR) { Dprintk(" Bootup CPU\n"); @@ -378,7 +418,7 @@ processor.mpc_cpufeature = (boot_cpu_data.x86 << 8) | (boot_cpu_data.x86_model << 4) | boot_cpu_data.x86_mask; - processor.mpc_featureflag = boot_cpu_data.x86_capability; + processor.mpc_featureflag = boot_cpu_data.x86_capability[0]; processor.mpc_reserved[0] = 0; processor.mpc_reserved[1] = 0; for (i = 0; i < 2; i++) { diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/msr.c linux/arch/i386/kernel/msr.c --- v2.4.0-test10/linux/arch/i386/kernel/msr.c Tue Jun 20 13:58:42 2000 +++ linux/arch/i386/kernel/msr.c Sun Nov 12 21:55:50 2000 @@ -231,7 +231,7 @@ if ( !(cpu_online_map & (1UL << cpu)) ) return -ENXIO; /* No such CPU */ - if ( !(c->x86_capability & X86_FEATURE_MSR) ) + if ( !test_bit(X86_FEATURE_MSR, &c->x86_capability) ) return -EIO; /* MSR not supported */ return 0; diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c --- v2.4.0-test10/linux/arch/i386/kernel/mtrr.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/mtrr.c Sun Nov 12 21:55:50 2000 @@ -228,6 +228,9 @@ 20000221 Richard Gooch Compile fix if procfs and devfs not enabled. Formatting changes. + v1.37 + 20001109 H. Peter Anvin + Use the new centralized CPU feature detects. */ #include #include @@ -266,11 +269,28 @@ #include #include -#define MTRR_VERSION "1.36 (20000221)" +#define MTRR_VERSION "1.37 (20001109)" #define TRUE 1 #define FALSE 0 +/* + * The code assumes all processors support the same MTRR + * interface. This is generally a good assumption, but could + * potentially be a problem. + */ +enum mtrr_if_type { + MTRR_IF_NONE, /* No MTRRs supported */ + MTRR_IF_INTEL, /* Intel (P6) standard MTRRs */ + MTRR_IF_AMD_K6, /* AMD pre-Athlon MTRRs */ + MTRR_IF_CYRIX_ARR, /* Cyrix ARRs */ + MTRR_IF_CENTAUR_MCR, /* Centaur MCRs */ +} mtrr_if = MTRR_IF_NONE; + +static __initdata char *mtrr_if_name[] = { + "none", "Intel", "AMD K6", "Cyrix ARR", "Centaur MCR" +}; + #define MTRRcap_MSR 0x0fe #define MTRRdefType_MSR 0x2ff @@ -350,18 +370,11 @@ /* Disable interrupts locally */ __save_flags (ctxt->flags); __cli (); - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */ - /* else fall through */ - case X86_VENDOR_CENTAUR: - if(boot_cpu_data.x86 != 6) - return; - /*break;*/ - } + if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) + return; + /* Save value of CR4 and clear Page Global Enable (bit 7) */ - if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) + if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) asm volatile ("movl %%cr4, %0\n\t" "movl %0, %1\n\t" "andb $0x7f, %b1\n\t" @@ -377,20 +390,15 @@ "wbinvd\n\t" : "=r" (tmp) : : "memory"); - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - case X86_VENDOR_INTEL: - case X86_VENDOR_CENTAUR: + if ( mtrr_if == MTRR_IF_INTEL ) { /* Disable MTRRs, and set the default type to uncached */ rdmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi); wrmsr (MTRRdefType_MSR, ctxt->deftype_lo & 0xf300UL, ctxt->deftype_hi); - break; - case X86_VENDOR_CYRIX: + } else { + /* Cyrix ARRs - everything else were excluded at the top */ tmp = getCx86 (CX86_CCR3); setCx86 (CX86_CCR3, (tmp & 0x0f) | 0x10); ctxt->ccr3 = tmp; - break; } } /* End Function set_mtrr_prepare */ @@ -399,33 +407,21 @@ { unsigned long tmp; - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 >= 6) break; /* Athlon and post-Athlon CPUs */ - /* else fall through */ - case X86_VENDOR_CENTAUR: - if(boot_cpu_data.x86 != 6) - { - __restore_flags (ctxt->flags); - return; - } - /*break;*/ + if ( mtrr_if != MTRR_IF_INTEL && mtrr_if != MTRR_IF_CYRIX_ARR ) { + __restore_flags (ctxt->flags); + return; } + /* Flush caches and TLBs */ asm volatile ("wbinvd" : : : "memory" ); /* Restore MTRRdefType */ - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - case X86_VENDOR_INTEL: - case X86_VENDOR_CENTAUR: + if ( mtrr_if == MTRR_IF_INTEL ) { + /* Intel (P6) standard MTRRs */ wrmsr (MTRRdefType_MSR, ctxt->deftype_lo, ctxt->deftype_hi); - break; - case X86_VENDOR_CYRIX: + } else { + /* Cyrix ARRs - everything else was excluded at the top */ setCx86 (CX86_CCR3, ctxt->ccr3); - break; } /* Enable caches */ @@ -435,7 +431,7 @@ : "=r" (tmp) : : "memory"); /* Restore value of CR4 */ - if (boot_cpu_data.x86_capability & X86_FEATURE_PGE) + if ( test_bit(X86_FEATURE_PGE, &boot_cpu_data.x86_capability) ) asm volatile ("movl %0, %%cr4" : : "r" (ctxt->cr4val) : "memory"); @@ -448,31 +444,20 @@ { unsigned long config, dummy; - switch (boot_cpu_data.x86_vendor) + switch ( mtrr_if ) { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 < 6) return 2; /* pre-Athlon CPUs */ - /* else fall through */ - case X86_VENDOR_INTEL: + case MTRR_IF_INTEL: rdmsr (MTRRcap_MSR, config, dummy); return (config & 0xff); - /*break;*/ - case X86_VENDOR_CYRIX: - /* Cyrix have 8 ARRs */ + case MTRR_IF_AMD_K6: + return 2; + case MTRR_IF_CYRIX_ARR: return 8; - case X86_VENDOR_CENTAUR: - /* and Centaur has 8 MCR's */ - if(boot_cpu_data.x86==5) - return 8; - /* the cyrix III has intel compatible MTRR */ - if(boot_cpu_data.x86==6) - { - rdmsr (MTRRcap_MSR, config, dummy); - return (config & 0xff); - } - /*break;*/ + case MTRR_IF_CENTAUR_MCR: + return 8; + default: + return 0; } - return 0; } /* End Function get_num_var_ranges */ /* Returns non-zero if we have the write-combining memory type */ @@ -480,24 +465,19 @@ { unsigned long config, dummy; - switch (boot_cpu_data.x86_vendor) + switch ( mtrr_if ) { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 < 6) return 1; /* pre-Athlon CPUs */ - /* else fall through */ - case X86_VENDOR_CENTAUR: - if (boot_cpu_data.x86 == 5) - return 1; /* C6 */ - /* CyrixIII is Intel like */ - case X86_VENDOR_INTEL: + case MTRR_IF_INTEL: rdmsr (MTRRcap_MSR, config, dummy); return (config & (1<<10)); - /*break;*/ - case X86_VENDOR_CYRIX: return 1; - /*break;*/ + case MTRR_IF_AMD_K6: + case MTRR_IF_CENTAUR_MCR: + case MTRR_IF_CYRIX_ARR: + return 1; + default: + return 0; } - return 0; } /* End Function have_wrcomb */ static void intel_get_mtrr (unsigned int reg, unsigned long *base, @@ -1171,47 +1151,48 @@ mtrr_type ltype; unsigned long lbase, lsize, last; - if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV; - switch (boot_cpu_data.x86_vendor) + switch ( mtrr_if ) { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 < 6) - { /* pre-Athlon CPUs */ - /* Apply the K6 block alignment and size rules - In order - o Uncached or gathering only - o 128K or bigger block - o Power of 2 block - o base suitably aligned to the power - */ - if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) || - (size & ~(size-1))-size || ( base & (size-1) ) ) - return -EINVAL; - break; - } - /* Else fall through */ - case X86_VENDOR_INTEL: - /* Double check for Intel, we may run on Athlon */ - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) + case MTRR_IF_NONE: + return -ENXIO; /* No MTRRs whatsoever */ + + case MTRR_IF_AMD_K6: + /* Apply the K6 block alignment and size rules + In order + o Uncached or gathering only + o 128K or bigger block + o Power of 2 block + o base suitably aligned to the power + */ + if ( type > MTRR_TYPE_WRCOMB || size < (1 << 17) || + (size & ~(size-1))-size || ( base & (size-1) ) ) + return -EINVAL; + break; + + case MTRR_IF_INTEL: + /* For Intel PPro stepping <= 7, must be 4 MiB aligned */ + if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model == 1 && + boot_cpu_data.x86_mask <= 7 ) { - /* For Intel PPro stepping <= 7, must be 4 MiB aligned */ - if ( (boot_cpu_data.x86 == 6) && (boot_cpu_data.x86_model == 1) && - (boot_cpu_data.x86_mask <= 7) && ( base & ( (1 << 22) -1 ) ) ) + if ( base & ((1 << 22)-1) ) { printk (KERN_WARNING "mtrr: base(0x%lx) is not 4 MiB aligned\n", base); return -EINVAL; } } - /* Fall through */ - case X86_VENDOR_CYRIX: - case X86_VENDOR_CENTAUR: + /* Fall through */ + + 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 (boot_cpu_data.x86_vendor == X86_VENDOR_CENTAUR && boot_cpu_data.x86 == 5) + if ( mtrr_if == MTRR_IF_CENTAUR_MCR ) { if (type != MTRR_TYPE_WRCOMB) { @@ -1237,10 +1218,11 @@ return -EINVAL; } break; - default: + + default: return -EINVAL; - /*break;*/ } + if (type >= MTRR_NUM_TYPES) { printk ("mtrr: type: %u illegal\n", type); @@ -1328,7 +1310,8 @@ mtrr_type ltype; unsigned long lbase, lsize; - if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return -ENODEV; + if ( mtrr_if == MTRR_IF_NONE ) return -ENXIO; + max = get_num_var_ranges (); down (&main_lock); if (reg < 0) @@ -1356,7 +1339,7 @@ printk ("mtrr: register: %d too big\n", reg); return -EINVAL; } - if (boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX) + if ( mtrr_if == MTRR_IF_CYRIX_ARR ) { if ( (reg == 3) && arr3_protected ) { @@ -1772,42 +1755,41 @@ set_mtrr_done (&ctxt); } /* End Function centaur_mcr_init */ -static void __init mtrr_setup(void) +static int __init mtrr_setup(void) { - printk ("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n", MTRR_VERSION); - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 < 6) - { - /* pre-Athlon CPUs */ - get_mtrr = amd_get_mtrr; - set_mtrr_up = amd_set_mtrr_up; - break; - } - /* Else fall through */ - case X86_VENDOR_INTEL: + if ( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) ) { + /* Intel (P6) standard MTRRs */ + mtrr_if = MTRR_IF_INTEL; get_mtrr = intel_get_mtrr; set_mtrr_up = intel_set_mtrr_up; - break; - case X86_VENDOR_CYRIX: + } 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; + } else if ( test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) ) { + /* Cyrix ARRs */ + mtrr_if = MTRR_IF_CYRIX_ARR; get_mtrr = cyrix_get_arr; set_mtrr_up = cyrix_set_arr_up; get_free_region = cyrix_get_free_region; - break; - case X86_VENDOR_CENTAUR: - if(boot_cpu_data.x86 == 5) - { - get_mtrr = centaur_get_mcr; - set_mtrr_up = centaur_set_mcr_up; - } - if(boot_cpu_data.x86 == 6) - { - get_mtrr = intel_get_mtrr; - set_mtrr_up = intel_set_mtrr_up; - } - break; - } + cyrix_arr_init(); + } 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(); + } else { + /* No supported MTRR interface */ + mtrr_if = MTRR_IF_NONE; + } + + printk ("mtrr: v%s Richard Gooch (rgooch@atnf.csiro.au)\n" + "mtrr: detected mtrr type: %s\n", + MTRR_VERSION, mtrr_if_name[mtrr_if]); + + return (mtrr_if != MTRR_IF_NONE); } /* End Function mtrr_setup */ #ifdef CONFIG_SMP @@ -1817,24 +1799,12 @@ void __init mtrr_init_boot_cpu(void) { - if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return; - mtrr_setup (); - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 < 6) break; /* Pre-Athlon CPUs */ - case X86_VENDOR_INTEL: + if ( !mtrr_setup () ) + return; + + if ( mtrr_if == MTRR_IF_INTEL ) { + /* Only for Intel MTRRs */ get_mtrr_state (&smp_mtrr_state); - break; - case X86_VENDOR_CYRIX: - cyrix_arr_init (); - break; - case X86_VENDOR_CENTAUR: /* C6 and Cyrix III have different ones */ - if(boot_cpu_data.x86 == 5) - centaur_mcr_init (); - if(boot_cpu_data.x86 == 6) - get_mtrr_state(&smp_mtrr_state); - break; } } /* End Function mtrr_init_boot_cpu */ @@ -1859,16 +1829,12 @@ void __init mtrr_init_secondary_cpu(void) { - if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return; - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - /* Just for robustness: pre-Athlon CPUs cannot do SMP */ - if (boot_cpu_data.x86 < 6) break; - case X86_VENDOR_INTEL: - intel_mtrr_init_secondary_cpu (); + switch ( mtrr_if ) { + case MTRR_IF_INTEL: + /* Intel (P6) standard MTRRs */ + intel_mtrr_init_secondary_cpu(); break; - case X86_VENDOR_CYRIX: + case MTRR_IF_CYRIX_ARR: /* This is _completely theoretical_! * I assume here that one day Cyrix will support Intel APIC. * In reality on non-Intel CPUs we won't even get to this routine. @@ -1877,39 +1843,26 @@ */ cyrix_arr_init_secondary (); break; - default: + default: + /* I see no MTRRs I can support in SMP mode... */ printk ("mtrr: SMP support incomplete for this vendor\n"); - break; } } /* End Function mtrr_init_secondary_cpu */ #endif /* CONFIG_SMP */ int __init mtrr_init(void) { - if ( !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) ) return 0; #ifdef CONFIG_SMP - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_AMD: - if (boot_cpu_data.x86 < 6) break; /* Pre-Athlon CPUs */ - case X86_VENDOR_INTEL: + /* mtrr_setup() should already have been called from mtrr_init_boot_cpu() */ + + if ( mtrr_if == MTRR_IF_INTEL ) { finalize_mtrr_state (&smp_mtrr_state); mtrr_state_warn (smp_changes_mask); - break; } -#else /* CONFIG_SMP */ - mtrr_setup (); - switch (boot_cpu_data.x86_vendor) - { - case X86_VENDOR_CYRIX: - cyrix_arr_init (); - break; - case X86_VENDOR_CENTAUR: - if(boot_cpu_data.x86 == 5) - centaur_mcr_init (); - break; - } -#endif /* !CONFIG_SMP */ +#else + if ( !mtrr_setup() ) + return 0; /* MTRRs not supported? */ +#endif #ifdef CONFIG_PROC_FS proc_root_mtrr = create_proc_entry ("mtrr", S_IWUSR | S_IRUGO, &proc_root); @@ -1924,3 +1877,11 @@ init_table (); return 0; } /* End Function mtrr_init */ + +/* + * Local Variables: + * mode:c + * c-file-style:"k&r" + * c-basic-offset:4 + * End: + */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c --- v2.4.0-test10/linux/arch/i386/kernel/pci-irq.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/pci-irq.c Sat Nov 18 21:11:19 2000 @@ -265,6 +265,20 @@ return 1; } +/* + * Cyrix: nibble offset 0x5C + */ +static int pirq_cyrix_get(struct pci_dev *router, struct pci_dev *dev, int pirq) +{ + return read_config_nybble(router, 0x5C, pirq-1); +} + +static int pirq_cyrix_set(struct pci_dev *router, struct pci_dev *dev, int pirq, int irq) +{ + write_config_nybble(router, 0x5C, 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) @@ -283,12 +297,19 @@ { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set }, + { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX, pirq_piix_get, pirq_piix_set }, { "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set }, + { "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set }, + { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set }, { "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, pirq_via_get, pirq_via_set }, + { "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 }, + { "default", 0, 0, NULL, NULL } }; @@ -298,7 +319,6 @@ static void __init pirq_find_router(void) { struct irq_routing_table *rt = pirq_table; - u16 rvendor, rdevice; struct irq_router *r; #ifdef CONFIG_PCI_BIOS @@ -308,32 +328,31 @@ return; } #endif - if (!(pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn))) { + /* fall back to default router if nothing else found */ + pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1; + + pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn); + if (!pirq_router_dev) { DBG("PCI: Interrupt router not found at %02x:%02x\n", rt->rtr_bus, rt->rtr_devfn); - /* fall back to default router */ - pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1; return; } - if (rt->rtr_vendor) { - rvendor = rt->rtr_vendor; - rdevice = rt->rtr_device; - } else { - /* - * Several BIOSes forget to set the router type. In such cases, we - * use chip vendor/device. This doesn't guarantee us semantics of - * PIRQ values, but was found to work in practice and it's still - * better than not trying. - */ - DBG("PCI: Guessed interrupt router ID from %s\n", pirq_router_dev->slot_name); - rvendor = pirq_router_dev->vendor; - rdevice = pirq_router_dev->device; - } - for(r=pirq_routers; r->vendor; r++) - if (r->vendor == rvendor && r->device == rdevice) + + for(r=pirq_routers; r->vendor; r++) { + /* Exact match against router table entry? Use it! */ + if (r->vendor == rt->rtr_vendor && r->device == rt->rtr_device) { + pirq_router = r; break; - pirq_router = r; - printk("PCI: Using IRQ router %s [%04x/%04x] at %s\n", r->name, - rvendor, rdevice, pirq_router_dev->slot_name); + } + /* Match against router device entry? Use it as a fallback */ + if (r->vendor == pirq_router_dev->vendor && r->device == pirq_router_dev->device) { + pirq_router = r; + } + } + printk("PCI: Using IRQ router %s [%04x/%04x] at %s\n", + pirq_router->name, + pirq_router_dev->vendor, + pirq_router_dev->device, + pirq_router_dev->slot_name); } static struct irq_info *pirq_get_info(struct pci_dev *dev, int pin) diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/semaphore.c linux/arch/i386/kernel/semaphore.c --- v2.4.0-test10/linux/arch/i386/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/semaphore.c Sat Nov 18 17:31:25 2000 @@ -59,7 +59,7 @@ { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -79,7 +79,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -93,7 +93,7 @@ int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -129,7 +129,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -315,7 +315,7 @@ for (;;) { if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!sem->write_bias_granted) schedule(); } @@ -371,7 +371,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c --- v2.4.0-test10/linux/arch/i386/kernel/setup.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/setup.c Sat Nov 18 20:54:24 2000 @@ -55,6 +55,9 @@ * Cyrix III, Pentium IV support. * Dave Jones , October 2000 * + * Massive cleanup of CPU detection and bug handling; + * Transmeta CPU detection, + * H. Peter Anvin , November 2000 */ /* @@ -107,7 +110,9 @@ /* * Bus types .. */ +#ifdef CONFIG_EISA int EISA_bus; +#endif int MCA_bus; /* for MCA, but anyone else can use it if they want */ @@ -543,7 +548,7 @@ to--; if (!memcmp(from+4, "nopentium", 9)) { from += 9+4; - boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE; + clear_bit(X86_FEATURE_PSE, &boot_cpu_data.x86_capability); } else if (!memcmp(from+4, "exactmap", 8)) { from += 8+4; e820.nr_map = 0; @@ -846,70 +851,158 @@ #endif } +#ifndef CONFIG_X86_TSC +static int tsc_disable __initdata = 0; + +static int __init tsc_setup(char *str) +{ + tsc_disable = 1; + return 1; +} + +__setup("notsc", tsc_setup); +#endif + static int __init get_model_name(struct cpuinfo_x86 *c) { - unsigned int n, dummy, *v; + unsigned int *v; + char *p, *q; - cpuid(0x80000000, &n, &dummy, &dummy, &dummy); - if (n < 0x80000004) + if (cpuid_eax(0x80000000) < 0x80000004) return 0; - cpuid(0x80000001, &dummy, &dummy, &dummy, &(c->x86_capability)); + v = (unsigned int *) c->x86_model_id; cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); c->x86_model_id[48] = 0; + + /* Intel chips right-justify this string for some dumb reason; + undo that brain damage */ + p = q = &c->x86_model_id[0]; + while ( *p == ' ' ) + p++; + if ( p != q ) { + while ( *p ) + *q++ = *p++; + while ( q <= &c->x86_model_id[48] ) + *q++ = '\0'; /* Zero-pad the rest */ + } + return 1; } static void __init display_cacheinfo(struct cpuinfo_x86 *c) { - unsigned int n, dummy, ecx, edx; + unsigned int n, dummy, ecx, edx, l2size; - cpuid(0x80000000, &n, &dummy, &dummy, &dummy); + n = cpuid_eax(0x80000000); if (n >= 0x80000005) { cpuid(0x80000005, &dummy, &dummy, &ecx, &edx); - printk("CPU: L1 I Cache: %dK L1 D Cache: %dK (%d bytes/line)\n", - edx>>24, ecx>>24, edx&0xFF); + printk("CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n", + edx>>24, edx&0xFF, ecx>>24, ecx&0xFF); c->x86_cache_size=(ecx>>24)+(edx>>24); } - if (n < 0x80000006) /* Cyrix just has large L1. */ + if (n < 0x80000006) /* Some chips just has a large L1. */ return; - cpuid(0x80000006, &dummy, &dummy, &ecx, &edx); - c->x86_cache_size = ecx >>16; + ecx = cpuid_ecx(0x80000006); + l2size = ecx >> 16; /* AMD errata T13 (order #21922) */ - if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && - boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 3 && - boot_cpu_data.x86_mask == 0) - { - c->x86_cache_size = 64; + if (c->x86_vendor == X86_VENDOR_AMD && + c->x86 == 6 && + c->x86_model == 3 && + c->x86_mask == 0) { + l2size = 64; } - printk("CPU: L2 Cache: %dK\n", ecx>>16); + + if ( l2size == 0 ) + return; /* Again, no L2 cache is possible */ + + c->x86_cache_size = l2size; + + printk("CPU: L2 Cache: %dK (%d bytes/line)\n", + l2size, ecx & 0xFF); } +/* + * B step AMD K6 before B 9730xxxx have hardware bugs that can cause + * misexecution of code under Linux. Owners of such processors should + * contact AMD for precise details and a CPU swap. + * + * See http://www.mygale.com/~poulot/k6bug.html + * http://www.amd.com/K6/k6docs/revgd.html + * + * The following test is erm.. interesting. AMD neglected to up + * the chip setting when fixing the bug but they also tweaked some + * performance at the same time.. + */ + +extern void vide(void); +__asm__(".align 4\nvide: ret"); -static int __init amd_model(struct cpuinfo_x86 *c) +static int __init init_amd(struct cpuinfo_x86 *c) { u32 l, h; unsigned long flags; int mbytes = max_mapnr >> (20-PAGE_SHIFT); + int r; - int r=get_model_name(c); + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; + 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ + clear_bit(0*32+31, &c->x86_capability); + + r = get_model_name(c); switch(c->x86) { case 5: if( c->x86_model < 6 ) { - /* Anyone with a K5 want to fill this in */ + /* Based on AMD doc 20734R - June 2000 */ + if ( c->x86_model == 0 ) { + clear_bit(X86_FEATURE_APIC, &c->x86_capability); + set_bit(X86_FEATURE_PGE, &c->x86_capability); + } break; } + if ( c->x86_model == 6 && c->x86_mask == 1 ) { + const int K6_BUG_LOOP = 1000000; + int n; + void (*f_vide)(void); + unsigned long d, d2; + + printk(KERN_INFO "AMD K6 stepping B detected - "); + + /* + * It looks like AMD fixed the 2.6.2 bug and improved indirect + * calls at the same time. + */ + + n = K6_BUG_LOOP; + f_vide = vide; + rdtscl(d); + while (n--) + f_vide(); + rdtscl(d2); + d = d2-d; + + /* Knock these two lines out if it debugs out ok */ + printk(KERN_INFO "K6 BUG %ld %d (Report these if test report is incorrect)\n", d, 20*K6_BUG_LOOP); + printk(KERN_INFO "AMD K6 stepping B detected - "); + /* -- cut here -- */ + if (d > 20*K6_BUG_LOOP) + printk("system stability may be impaired when more than 32 MB are used.\n"); + else + printk("probably OK (after B9730xxxx).\n"); + printk(KERN_INFO "Please see http://www.mygale.com/~poulot/k6bug.html\n"); + } + /* K6 with old style WHCR */ if( c->x86_model < 8 || (c->x86_model== 8 && c->x86_mask < 8)) @@ -954,11 +1047,11 @@ } /* Set MTRR capability flag if appropriate */ - if((boot_cpu_data.x86_model == 13) || - (boot_cpu_data.x86_model == 9) || - ((boot_cpu_data.x86_model == 8) && - (boot_cpu_data.x86_mask >= 8))) - c->x86_capability |= X86_FEATURE_MTRR; + if ( (c->x86_model == 13) || + (c->x86_model == 9) || + ((c->x86_model == 8) && + (c->x86_mask >= 8)) ) + set_bit(X86_FEATURE_K6_MTRR, &c->x86_capability); break; } @@ -971,7 +1064,6 @@ display_cacheinfo(c); return r; } - /* * Read Cyrix DEVID registers (DIR) to get more detailed info. about the CPU @@ -1032,14 +1124,56 @@ static char cyrix_model_mult1[] __initdata = "12??43"; static char cyrix_model_mult2[] __initdata = "12233445"; -static void __init cyrix_model(struct cpuinfo_x86 *c) +/* + * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old + * BIOSes for compatability with DOS games. This makes the udelay loop + * work correctly, and improves performance. + */ + +extern void calibrate_delay(void) __init; + +static void __init check_cx686_slop(struct cpuinfo_x86 *c) +{ + if (Cx86_dir0_msb == 3) { + unsigned char ccr3, ccr5; + + cli(); + ccr3 = getCx86(CX86_CCR3); + setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN */ + ccr5 = getCx86(CX86_CCR5); + if (ccr5 & 2) + setCx86(CX86_CCR5, ccr5 & 0xfd); /* reset SLOP */ + setCx86(CX86_CCR3, ccr3); /* disable MAPEN */ + sti(); + + if (ccr5 & 2) { /* possible wrong calibration done */ + printk(KERN_INFO "Recalibrating delay loop with SLOP bit reset\n"); + calibrate_delay(); + c->loops_per_sec = loops_per_sec; + } + } +} + +static void __init init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; char *buf = c->x86_model_id; const char *p = NULL; + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; + 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ + clear_bit(0*32+31, &c->x86_capability); + + /* Cyrix used bit 24 in extended (AMD) CPUID for Cyrix MMX extensions */ + if ( test_bit(1*32+24, &c->x86_capability) ) { + clear_bit(1*32+24, &c->x86_capability); + set_bit(X86_FEATURE_CXMMX, &c->x86_capability); + } + do_cyrix_devid(&dir0, &dir1); + check_cx686_slop(c); + Cx86_dir0_msb = dir0_msn = dir0 >> 4; /* identifies CPU "family" */ dir0_lsn = dir0 & 0xf; /* model or clock multiplier */ @@ -1080,7 +1214,7 @@ } else /* 686 */ p = Cx86_cb+1; /* Emulate MTRRs using Cyrix's ARRs. */ - c->x86_capability |= X86_FEATURE_MTRR; + set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability); /* 6x86's contain this bug */ c->coma_bug = 1; break; @@ -1112,14 +1246,14 @@ /* GXm supports extended cpuid levels 'ala' AMD */ if (c->cpuid_level == 2) { get_model_name(c); /* get CPU marketing name */ - c->x86_capability&=~X86_FEATURE_TSC; + clear_bit(X86_FEATURE_TSC, c->x86_capability); return; } else { /* MediaGX */ Cx86_cb[2] = (dir0_lsn & 1) ? '3' : '4'; p = Cx86_cb+2; c->x86_model = (dir1 & 0x20) ? 1 : 2; - c->x86_capability&=~X86_FEATURE_TSC; + clear_bit(X86_FEATURE_TSC, &c->x86_capability); } break; @@ -1132,7 +1266,7 @@ if (((dir1 & 0x0f) > 4) || ((dir1 & 0xf0) == 0x20)) (c->x86_model)++; /* Emulate MTRRs using Cyrix's ARRs. */ - c->x86_capability |= X86_FEATURE_MTRR; + set_bit(X86_FEATURE_CYRIX_ARR, &c->x86_capability); break; case 0xf: /* Cyrix 486 without DEVID registers */ @@ -1158,7 +1292,7 @@ return; } -static void __init centaur_model(struct cpuinfo_x86 *c) +static void __init init_centaur(struct cpuinfo_x86 *c) { enum { ECX8=1<<1, @@ -1187,6 +1321,10 @@ u32 lo,hi,newlo; u32 aa,bb,cc,dd; + /* Bit 31 in normal CPUID used for nonstandard 3DNow ID; + 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */ + clear_bit(0*32+31, &c->x86_capability); + switch (c->x86) { case 5: @@ -1196,7 +1334,7 @@ fcr_set=ECX8|DSMC|EDCTLB|EMMX|ERETSTK; fcr_clr=DPDC; printk("Disabling bugged TSC.\n"); - c->x86_capability &= ~X86_FEATURE_TSC; + clear_bit(X86_FEATURE_TSC, &c->x86_capability); break; case 8: switch(c->x86_mask) { @@ -1238,15 +1376,15 @@ printk("Centaur FCR is 0x%X\n",lo); } /* Emulate MTRRs using Centaur's MCR. */ - c->x86_capability |= X86_FEATURE_MTRR; + set_bit(X86_FEATURE_CENTAUR_MCR, &c->x86_capability); /* Report CX8 */ - c->x86_capability |= X86_FEATURE_CX8; + set_bit(X86_FEATURE_CX8, &c->x86_capability); /* Set 3DNow! on Winchip 2 and above. */ if (c->x86_model >=8) - c->x86_capability |= X86_FEATURE_AMD3D; + set_bit(X86_FEATURE_3DNOW, &c->x86_capability); /* See if we can find out some more. */ - cpuid(0x80000000,&aa,&bb,&cc,&dd); - if (aa>=0x80000005) { /* Yes, we can. */ + if ( cpuid_eax(0x80000000) >= 0x80000005 ) { + /* Yes, we can. */ cpuid(0x80000005,&aa,&bb,&cc,&dd); /* Add L1 data and code cache sizes. */ c->x86_cache_size = (cc>>24)+(dd>>24); @@ -1261,10 +1399,10 @@ lo |= (1<<1 | 1<<7); /* Report CX8 & enable PGE */ wrmsr (0x1107, lo, hi); - c->x86_capability |= X86_FEATURE_CX8; + set_bit(X86_FEATURE_CX8, &c->x86_capability); rdmsr (0x80000001, lo, hi); if (hi & (1<<31)) - c->x86_capability |= X86_FEATURE_AMD3D; + set_bit(X86_FEATURE_3DNOW, &c->x86_capability); get_model_name(c); display_cacheinfo(c); @@ -1276,7 +1414,7 @@ } -static void __init transmeta_model(struct cpuinfo_x86 *c) +static void __init init_transmeta(struct cpuinfo_x86 *c) { unsigned int cap_mask, uk, max, dummy; unsigned int cms_rev1, cms_rev2; @@ -1287,17 +1425,15 @@ display_cacheinfo(c); /* Print CMS and CPU revision */ - cpuid(0x80860000, &max, &dummy, &dummy, &dummy); + max = cpuid_eax(0x80860000); if ( max >= 0x80860001 ) { cpuid(0x80860001, &dummy, &cpu_rev, &cpu_freq, &cpu_flags); - printk("CPU: Processor revision %u.%u.%u.%u, %u MHz%s%s\n", + printk("CPU: Processor revision %u.%u.%u.%u, %u MHz\n", (cpu_rev >> 24) & 0xff, (cpu_rev >> 16) & 0xff, (cpu_rev >> 8) & 0xff, cpu_rev & 0xff, - cpu_freq, - (cpu_flags & 1) ? " [recovery]" : "", - (cpu_flags & 2) ? " [longrun]" : ""); + cpu_freq); } if ( max >= 0x80860002 ) { cpuid(0x80860002, &dummy, &cms_rev1, &cms_rev2, &dummy); @@ -1333,13 +1469,154 @@ printk("CPU: %s\n", cpu_info); } - /* Unhide possibly hidden flags */ + /* Unhide possibly hidden capability flags */ rdmsr(0x80860004, cap_mask, uk); wrmsr(0x80860004, ~0, uk); - cpuid(0x00000001, &dummy, &dummy, &dummy, &c->x86_capability); + c->x86_capability[0] = cpuid_edx(0x00000001); wrmsr(0x80860004, cap_mask, uk); } +extern void trap_init_f00f_bug(void); + +static void __init init_intel(struct cpuinfo_x86 *c) +{ +#ifndef CONFIG_M686 + static int f00f_workaround_enabled = 0; +#endif + extern void mcheck_init(struct cpuinfo_x86 *c); + char *p = NULL; + unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */ + +#ifndef CONFIG_M686 + /* + * All current models of Pentium and Pentium with MMX technology CPUs + * have the F0 0F bug, which lets nonpriviledged users lock up the system. + * Note that the workaround only should be initialized once... + */ + c->f00f_bug = 0; + if ( c->x86 == 5 ) { + c->f00f_bug = 1; + if ( !f00f_workaround_enabled ) { + trap_init_f00f_bug(); + printk(KERN_INFO "Intel Pentium with F0 0F bug - workaround enabled.\n"); + f00f_workaround_enabled = 1; + } + } +#endif + + + if (c->cpuid_level > 1) { + /* supports eax=2 call */ + int i, j, n; + int regs[4]; + unsigned char *dp = (unsigned char *)regs; + + /* Number of times to iterate */ + n = cpuid_eax(2) & 0xFF; + + for ( i = 0 ; i < n ; i++ ) { + cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); + + /* If bit 31 is set, this is an unknown format */ + for ( j = 0 ; j < 3 ; j++ ) { + if ( regs[j] < 0 ) regs[j] = 0; + } + + /* Byte 0 is level count, not a descriptor */ + for ( j = 1 ; j < 16 ; j++ ) { + unsigned char des = dp[j]; + unsigned char dl, dh; + unsigned int cs; + + dh = des >> 4; + dl = des & 0x0F; + + switch ( dh ) + { + case 2: + if ( dl ) { + /* L3 cache */ + cs = (dl-1) << 9; + l3 += cs; + } + break; + case 4: + case 8: + if ( dl ) { + /* L2 cache */ + cs = 128 << (dl-1); + l2 += cs; + } + break; + case 6: + if (dl > 5) { + /* L1 D cache */ + cs = 8<<(dl-6); + l1d += cs; + } + break; + case 7: + /* L1 I cache */ + cs = dl ? (16 << (dl-1)) : 12; + l1i += cs; + break; + default: + /* TLB, or something else we don't know about */ + break; + } + } + } + if ( l1i || l1d ) + printk("CPU: L1 I cache: %dK, L1 D cache: %dK\n", + l1i, l1d); + if ( l2 ) + printk("CPU: L2 cache: %dK\n", l2); + if ( l3 ) + printk("CPU: L3 cache: %dK\n", l3); + + /* + * This assumes the L3 cache is shared; it typically lives in + * the northbridge. The L1 caches are included by the L2 + * cache, and so should not be included for the purpose of + * SMP switching weights. + */ + c->x86_cache_size = l2 ? l2 : (l1i+l1d); + } + + /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it */ + if ( c->x86 == 6 && c->x86_model < 3 && c->x86_mask < 3 ) + clear_bit(X86_FEATURE_SEP, &c->x86_capability); + + /* Names for the Pentium II/Celeron processors + detectable only by also checking the cache size. + Dixon is NOT a Celeron. */ + if (c->x86 == 6) { + switch (c->x86_model) { + case 5: + if (l2 == 0) + p = "Celeron (Covington)"; + if (l2 == 256) + p = "Mobile Pentium II (Dixon)"; + break; + + case 6: + if (l2 == 128) + p = "Celeron (Mendocino)"; + break; + + case 8: + if (l2 == 128) + p = "Celeron (Coppermine)"; + break; + } + } + + if ( p ) + strcpy(c->x86_model_id, p); + + /* Enable MCA if available */ + mcheck_init(c); +} void __init get_cpu_vendor(struct cpuinfo_x86 *c) { @@ -1359,7 +1636,8 @@ c->x86_vendor = X86_VENDOR_NEXGEN; else if (!strcmp(v, "RiseRiseRise")) c->x86_vendor = X86_VENDOR_RISE; - else if (!strcmp(v, "GenuineTMx86")) + else if (!strcmp(v, "GenuineTMx86") || + !strcmp(v, "TransmetaCPU")) c->x86_vendor = X86_VENDOR_TRANSMETA; else c->x86_vendor = X86_VENDOR_UNKNOWN; @@ -1367,11 +1645,13 @@ struct cpu_model_info { int vendor; - int x86; + int family; char *model_names[16]; }; /* Naming convention should be: [()] */ +/* This table only is used unless init_() below doesn't set it; */ +/* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */ static struct cpu_model_info cpu_models[] __initdata = { { X86_VENDOR_INTEL, 4, { "486 DX-25/33", "486 DX-50", "486 SX", "486 DX/2", "486 SL", @@ -1391,12 +1671,12 @@ { NULL, NULL, NULL, "486 DX/2", NULL, NULL, NULL, "486 DX/2-WB", "486 DX/4", "486 DX/4-WB", NULL, NULL, NULL, NULL, "Am5x86-WT", "Am5x86-WB" }}, - { X86_VENDOR_AMD, 5, + { X86_VENDOR_AMD, 5, /* Is this this really necessary?? */ { "K5/SSA5", "K5", "K5", "K5", NULL, NULL, "K6", "K6", "K6-2", "K6-3", NULL, NULL, NULL, NULL, NULL, NULL }}, - { X86_VENDOR_AMD, 6, + { X86_VENDOR_AMD, 6, /* Is this this really necessary?? */ { "Athlon", "Athlon", "Athlon", NULL, "Athlon", NULL, NULL, NULL, NULL, @@ -1410,11 +1690,27 @@ { X86_VENDOR_RISE, 5, { "mP6", "mP6", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, - { X86_VENDOR_TRANSMETA, 5, - { NULL, NULL, NULL, "Crusoe", NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }}, }; +/* Look up CPU names by table lookup. */ +static char __init *table_lookup_model(struct cpuinfo_x86 *c) +{ + struct cpu_model_info *info = cpu_models; + int i; + + if ( c->x86_model >= 16 ) + return NULL; /* Range check */ + + for ( i = 0 ; i < sizeof(cpu_models)/sizeof(struct cpu_model_info) ; i++ ) { + if ( info->vendor == c->x86_vendor && + info->family == c->x86 ) { + return info->model_names[c->x86_model]; + } + info++; + } + return NULL; /* Not found */ +} + /* * Detect a NexGen CPU running without BIOS hypercode new enough * to have CPUID. (Thanks to Herbert Oppmann) @@ -1439,13 +1735,15 @@ static void __init squash_the_stupid_serial_number(struct cpuinfo_x86 *c) { - if(c->x86_capability&(X86_FEATURE_PN) && disable_x86_serial_nr) { + if( test_bit(X86_FEATURE_PN, &c->x86_capability) && + disable_x86_serial_nr ) { /* Disable processor serial number */ unsigned long lo,hi; rdmsr(0x119,lo,hi); lo |= 0x200000; wrmsr(0x119,lo,hi); printk(KERN_INFO "CPU serial number disabled.\n"); + clear_bit(X86_FEATURE_PN, &c->x86_capability); } } @@ -1458,157 +1756,255 @@ __setup("serialnumber", x86_serial_nr_setup); -void __init identify_cpu(struct cpuinfo_x86 *c) +/* Standard macro to see if a specific flag is changeable */ +static inline int flag_is_changeable_p(u32 flag) { - int i=0; - char *p = NULL; - extern void mcheck_init(void); + u32 f1, f2; - c->loops_per_sec = loops_per_sec; - c->x86_cache_size = -1; - - get_cpu_vendor(c); + asm("pushfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl %2,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "popfl\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (flag)); + return ((f1^f2) & flag) != 0; +} - switch (c->x86_vendor) { - case X86_VENDOR_UNKNOWN: - if (c->cpuid_level < 0) - { - /* It may be a nexgen with cpuid disabled.. */ - if(deep_magic_nexgen_probe()) - { - strcpy(c->x86_model_id, "Nx586"); - c->x86_vendor = X86_VENDOR_NEXGEN; - } - return; - } - break; +/* Probe for the CPUID instruction */ +static int __init have_cpuid_p(void) +{ + return flag_is_changeable_p(X86_EFLAGS_ID); +} - case X86_VENDOR_CYRIX: - cyrix_model(c); - return; +/* + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected + * by the fact that they preserve the flags across the division of 5/2. + * PII and PPro exhibit this behavior too, but they have cpuid available. + */ + +/* + * Perform the Cyrix 5/2 test. A Cyrix won't change + * the flags, while other 486 chips will. + */ +static inline int test_cyrix_52div(void) +{ + unsigned int test; - case X86_VENDOR_AMD: - if (amd_model(c)) - return; - break; + __asm__ __volatile__( + "sahf\n\t" /* clear flags (%eax = 0x0005) */ + "div %b2\n\t" /* divide 5 by 2 */ + "lahf" /* store flags into %ah */ + : "=a" (test) + : "0" (5), "q" (2) + : "cc"); + + /* AH is 0x02 on Cyrix after the divide.. */ + return (unsigned char) (test >> 8) == 0x02; +} + +/* Try to detect a CPU with disabled CPUID, and if so, enable. This routine + may also be used to detect non-CPUID processors and fill in some of + the information manually. */ +static int __init id_and_try_enable_cpuid(struct cpuinfo_x86 *c) +{ + /* First of all, decide if this is a 486 or higher */ + /* It's a 486 if we can modify the AC flag */ + if ( flag_is_changeable_p(X86_EFLAGS_AC) ) + c->x86 = 4; + else + c->x86 = 3; - case X86_VENDOR_CENTAUR: - centaur_model(c); - return; + /* Detect Cyrix with disabled CPUID */ + if ( c->x86 == 4 && test_cyrix_52div() ) { + strcpy(c->x86_vendor_id, "CyrixInstead"); + } - case X86_VENDOR_INTEL: + /* Detect NexGen with old hypercode */ + if ( deep_magic_nexgen_probe() ) { + strcpy(c->x86_vendor_id, "NexGenDriven"); + } - squash_the_stupid_serial_number(c); - mcheck_init(); + return have_cpuid_p(); /* Check to see if CPUID now enabled? */ +} - if (c->cpuid_level > 1) { - /* supports eax=2 call */ - int edx, dummy; +/* + * This does the hard work of actually picking apart the CPU stuff... + */ +void __init identify_cpu(struct cpuinfo_x86 *c) +{ + int junk, i; + u32 xlvl, tfms; - cpuid(2, &dummy, &dummy, &dummy, &edx); + c->loops_per_sec = loops_per_sec; + c->x86_cache_size = -1; + c->x86_vendor = X86_VENDOR_UNKNOWN; + c->cpuid_level = -1; /* CPUID not detected */ + c->x86_model = c->x86_mask = 0; /* So far unknown... */ + c->x86_vendor_id[0] = '\0'; /* Unset */ + c->x86_model_id[0] = '\0'; /* Unset */ + memset(&c->x86_capability, 0, sizeof c->x86_capability); + + if ( !have_cpuid_p() && !id_and_try_enable_cpuid(c) ) { + /* CPU doesn't have CPUID */ + + /* If there are any capabilities, they're vendor-specific */ + /* enable_cpuid() would have set c->x86 for us. */ + } else { + /* CPU does have CPUID */ + + /* Get vendor name */ + cpuid(0x00000000, &c->cpuid_level, + (int *)&c->x86_vendor_id[0], + (int *)&c->x86_vendor_id[8], + (int *)&c->x86_vendor_id[4]); + + get_cpu_vendor(c); - /* We need only the LSB */ - edx &= 0xff; + /* Initialize the standard set of capabilities */ + /* Note that the vendor-specific code below might override */ - switch (edx) { - case 0x40: - c->x86_cache_size = 0; - break; + /* Intel-defined flags: level 0x00000001 */ + if ( c->cpuid_level >= 0x00000001 ) { + cpuid(0x00000001, &tfms, &junk, &junk, + &c->x86_capability[0]); + c->x86 = (tfms >> 8) & 15; + c->x86_model = (tfms >> 4) & 15; + c->x86_mask = tfms & 15; + } else { + /* Have CPUID level 0 only - unheard of */ + c->x86 = 4; + } - case 0x41: /* 4-way 128 */ - c->x86_cache_size = 128; - break; + /* AMD-defined flags: level 0x80000001 */ + xlvl = cpuid_eax(0x80000000); + if ( (xlvl & 0xffff0000) == 0x80000000 ) { + if ( xlvl >= 0x80000001 ) + c->x86_capability[1] = cpuid_edx(0x80000001); + if ( xlvl >= 0x80000004 ) + get_model_name(c); /* Default name */ + } - case 0x42: /* 4-way 256 */ - case 0x82: /* 8-way 256 */ - c->x86_cache_size = 256; - break; + /* Transmeta-defined flags: level 0x80860001 */ + xlvl = cpuid_eax(0x80860000); + if ( (xlvl & 0xffff0000) == 0x80860000 ) { + if ( xlvl >= 0x80860001 ) + c->x86_capability[2] = cpuid_edx(0x80860001); + } + } - case 0x43: /* 4-way 512 */ - c->x86_cache_size = 512; - break; + printk("CPU: Before vendor init, caps: %08x %08x %08x, vendor = %d\n", + c->x86_capability[0], + c->x86_capability[1], + c->x86_capability[2], + c->x86_vendor); - case 0x44: /* 4-way 1024 */ - case 0x84: /* 8-way 1024 */ - c->x86_cache_size = 1024; - break; + /* + * Vendor-specific initialization. In this section we + * canonicalize the feature flags, meaning if there are + * features a certain CPU supports which CPUID doesn't + * tell us, CPUID claiming incorrect flags, or other bugs, + * we handle them here. + * + * At the end of this section, c->x86_capability better + * indicate the features this CPU genuinely supports! + */ + switch ( c->x86_vendor ) { + case X86_VENDOR_UNKNOWN: + default: + /* Not much we can do here... */ + break; - case 0x45: /* 4-way 2048 */ - case 0x85: /* 8-way 2048 */ - c->x86_cache_size = 2048; - break; + case X86_VENDOR_CYRIX: + init_cyrix(c); + break; - default: - c->x86_cache_size = 0; - break; - } - } + case X86_VENDOR_AMD: + init_amd(c); + break; - /* Pentium IV. */ - if (c->x86 == 15) { - get_model_name(c); - return; - } + case X86_VENDOR_CENTAUR: + init_centaur(c); + break; - /* Names for the Pentium II/Celeron processors - detectable only by also checking the cache size. - Dixon is NOT a Celeron. */ - if (c->x86 == 6) { - switch (c->x86_model) { - case 5: - if (c->x86_cache_size == 0) - p = "Celeron (Covington)"; - if (c->x86_cache_size == 256) - p = "Mobile Pentium II (Dixon)"; - break; - - case 6: - if (c->x86_cache_size == 128) - p = "Celeron (Mendocino)"; - break; - - case 8: - if (c->x86_cache_size == 128) - p = "Celeron (Coppermine)"; - break; - } - } - if (p!=NULL) - goto name_decoded; + case X86_VENDOR_INTEL: + init_intel(c); + break; - break; + case X86_VENDOR_NEXGEN: + c->x86_cache_size = 256; /* A few had 1 MB... */ + break; - case X86_VENDOR_TRANSMETA: - transmeta_model(c); - squash_the_stupid_serial_number(c); - return; + case X86_VENDOR_TRANSMETA: + init_transmeta(c); + break; } - - /* may be changed in the switch so needs to be after */ - if(c->x86_vendor == X86_VENDOR_NEXGEN) - c->x86_cache_size = 256; /* A few had 1Mb.. */ + printk("CPU: After vendor init, caps: %08x %08x %08x %08x\n", + c->x86_capability[0], + c->x86_capability[1], + c->x86_capability[2], + c->x86_capability[3]); - for (i = 0; i < sizeof(cpu_models)/sizeof(struct cpu_model_info); i++) { - if (cpu_models[i].vendor == c->x86_vendor && - cpu_models[i].x86 == c->x86) { - if (c->x86_model <= 16) - p = cpu_models[i].model_names[c->x86_model]; - } + /* + * The vendor-specific functions might have changed features. Now + * we do "generic changes." + */ + + /* TSC disabled? */ +#ifdef CONFIG_TSC + if ( tsc_disable ) + clear_bit(X86_FEATURE_TSC, &c->x86_capability); +#endif + + /* Disable the PN if appropriate */ + squash_the_stupid_serial_number(c); + + /* If the model name is still unset, do table lookup. */ + if ( !c->x86_model_id[0] ) { + char *p; + p = table_lookup_model(c); + if ( p ) + strcpy(c->x86_model_id, p); + else + /* Last resort... */ + sprintf(c->x86_model_id, "%02x/%02x", + c->x86_vendor, c->x86_model); } -name_decoded: + /* Now the feature flags better reflect actual CPU features! */ + + printk("CPU: After generic, caps: %08x %08x %08x %08x\n", + c->x86_capability[0], + c->x86_capability[1], + c->x86_capability[2], + c->x86_capability[3]); - if (p) { - strcpy(c->x86_model_id, p); - return; + /* + * On SMP, boot_cpu_data holds the common feature set between + * all CPUs; so make sure that we indicate which features are + * common between the CPUs. The first time this routine gets + * executed, c == &boot_cpu_data. + */ + if ( c != &boot_cpu_data ) { + /* AND the already accumulated flags with these */ + for ( i = 0 ; i < NCAPINTS ; i++ ) + boot_cpu_data.x86_capability[i] &= c->x86_capability[i]; } - sprintf(c->x86_model_id, "%02x/%02x", c->x86_vendor, c->x86_model); + printk("CPU: Common caps: %08x %08x %08x %08x\n", + boot_cpu_data.x86_capability[0], + boot_cpu_data.x86_capability[1], + boot_cpu_data.x86_capability[2], + boot_cpu_data.x86_capability[3]); } - /* * Perform early boot up checks for a valid TSC. See arch/i386/kernel/time.c */ @@ -1617,14 +2013,12 @@ { get_cpu_vendor(&boot_cpu_data); - if(boot_cpu_data.x86_vendor != X86_VENDOR_CYRIX) - return; - - cyrix_model(&boot_cpu_data); + if ( boot_cpu_data.x86_vendor == X86_VENDOR_CYRIX ) + init_cyrix(&boot_cpu_data); } - +/* These need to match */ static char *cpu_vendor_names[] __initdata = { "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" }; @@ -1646,7 +2040,7 @@ else printk("%s", c->x86_model_id); - if (c->x86_mask || c->cpuid_level>=0) + if (c->x86_mask || c->cpuid_level >= 0) printk(" stepping %02x\n", c->x86_mask); else printk("\n"); @@ -1659,23 +2053,39 @@ int get_cpuinfo(char * buffer) { char *p = buffer; - int sep_bug; /* - * Flags should be entered into the array ONLY if there is no overlap. - * Else a number should be used and then overridden in the case - * statement below. --Jauder - * - * NOTE: bits 10, 19-22, 26-31 are reserved. - * - * Data courtesy of http://www.sandpile.org/arch/cpuid.htm - * Thanks to the Greasel! + * These flag bits must match the definitions in . + * NULL means this bit is undefined or reserved; either way it doesn't + * have meaning as far as Linux is concerned. Note that it's important + * to realize there is a difference between this table and CPUID -- if + * applications want to get the raw CPUID data, they should access + * /dev/cpu//cpuid instead. */ static char *x86_cap_flags[] = { + /* Intel-defined */ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", - "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov", - "16", "pse36", "psn", "19", "20", "21", "22", "mmx", - "24", "xmm", "26", "27", "28", "29", "30", "31" + "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", + "pat", "pse36", "pn", "clflsh", NULL, "dtes", "acpi", "mmx", + "fxsr", "sse", "sse2", "selfsnoop", NULL, "acc", "ia64", NULL, + + /* AMD-defined */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, "mmxext", NULL, + NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow", + + /* Transmeta-defined */ + "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Other (Linux-defined) */ + "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr", NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; struct cpuinfo_x86 *c = cpu_data; int i, n; @@ -1702,7 +2112,7 @@ else p += sprintf(p, "stepping\t: unknown\n"); - if (c->x86_capability & X86_FEATURE_TSC) { + if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) { p += sprintf(p, "cpu MHz\t\t: %lu.%06lu\n", cpu_khz / 1000, (cpu_khz % 1000)); } @@ -1711,65 +2121,19 @@ if (c->x86_cache_size >= 0) p += sprintf(p, "cache size\t: %d KB\n", c->x86_cache_size); - /* Modify the capabilities according to chip type */ - switch (c->x86_vendor) { - - case X86_VENDOR_CYRIX: - x86_cap_flags[24] = "cxmmx"; - break; - - case X86_VENDOR_AMD: - if (c->x86 == 5 && c->x86_model == 6) - x86_cap_flags[10] = "sep"; - if (c->x86 < 6) - x86_cap_flags[16] = "fcmov"; - else - x86_cap_flags[16] = "pat"; - x86_cap_flags[22] = "mmxext"; - x86_cap_flags[24] = "fxsr"; - x86_cap_flags[30] = "3dnowext"; - x86_cap_flags[31] = "3dnow"; - break; - - case X86_VENDOR_INTEL: - x86_cap_flags[16] = "pat"; - x86_cap_flags[18] = "pn"; - x86_cap_flags[24] = "fxsr"; - x86_cap_flags[25] = "xmm"; - break; - - case X86_VENDOR_CENTAUR: - if (c->x86_model >=8) /* Only Winchip2 and above */ - x86_cap_flags[31] = "3dnow"; - break; - - default: - /* Unknown CPU manufacturer or no special handling needed */ - break; - } - - sep_bug = c->x86_vendor == X86_VENDOR_INTEL && - c->x86 == 0x06 && - c->cpuid_level >= 0 && - (c->x86_capability & X86_FEATURE_SEP) && - c->x86_model < 3 && - c->x86_mask < 3; - /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */ - fpu_exception = c->hard_math && (ignore_irq13 | (c->x86_capability & X86_FEATURE_FPU)); + fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu); p += sprintf(p, "fdiv_bug\t: %s\n" "hlt_bug\t\t: %s\n" - "sep_bug\t\t: %s\n" "f00f_bug\t: %s\n" "coma_bug\t: %s\n" "fpu\t\t: %s\n" "fpu_exception\t: %s\n" "cpuid level\t: %d\n" "wp\t\t: %s\n" - "flags\t\t:", + "features\t:", c->fdiv_bug ? "yes" : "no", c->hlt_works_ok ? "no" : "yes", - sep_bug ? "yes" : "no", c->f00f_bug ? "yes" : "no", c->coma_bug ? "yes" : "no", c->hard_math ? "yes" : "no", @@ -1777,8 +2141,9 @@ c->cpuid_level, c->wp_works_ok ? "yes" : "no"); - for ( i = 0 ; i < 32 ; i++ ) - if ( c->x86_capability & (1 << i) ) + for ( i = 0 ; i < 32*NCAPINTS ; i++ ) + if ( test_bit(i, &c->x86_capability) && + x86_cap_flags[i] != NULL ) p += sprintf(p, " %s", x86_cap_flags[i]); p += sprintf(p, "\nbogomips\t: %lu.%02lu\n\n", @@ -1788,18 +2153,6 @@ return p - buffer; } -#ifndef CONFIG_X86_TSC -static int tsc_disable __initdata = 0; - -static int __init tsc_setup(char *str) -{ - tsc_disable = 1; - return 1; -} - -__setup("notsc", tsc_setup); -#endif - static unsigned long cpu_initialized __initdata = 0; /* @@ -1824,7 +2177,8 @@ #ifndef CONFIG_X86_TSC if (tsc_disable && cpu_has_tsc) { printk("Disabling TSC...\n"); - boot_cpu_data.x86_capability &= ~X86_FEATURE_TSC; + /**** FIX-HPA: DOES THIS REALLY BELONG HERE? ****/ + clear_bit(X86_FEATURE_TSC, boot_cpu_data.x86_capability); set_in_cr4(X86_CR4_TSD); } #endif @@ -1869,3 +2223,11 @@ current->used_math = 0; stts(); } + +/* + * Local Variables: + * mode:c + * c-file-style:"k&r" + * c-basic-offset:8 + * End: + */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c --- v2.4.0-test10/linux/arch/i386/kernel/smpboot.c Sun Oct 8 10:50:06 2000 +++ linux/arch/i386/kernel/smpboot.c Thu Nov 16 13:18:38 2000 @@ -455,7 +455,7 @@ cpu_init(); smp_callin(); while (!atomic_read(&smp_commenced)) - /* nothing */ ; + rep_nop(); /* * low-memory mappings have been cleared, flush them from * the local TLBs too. diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c --- v2.4.0-test10/linux/arch/i386/kernel/traps.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/kernel/traps.c Sun Nov 19 17:16:34 2000 @@ -63,6 +63,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) { @@ -92,7 +93,6 @@ asmlinkage void page_fault(void); asmlinkage void coprocessor_error(void); asmlinkage void simd_coprocessor_error(void); -asmlinkage void reserved(void); asmlinkage void alignment_check(void); asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); @@ -312,7 +312,6 @@ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) DO_ERROR(12, SIGBUS, "stack segment", stack_segment) DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2()) -DO_ERROR(18, SIGSEGV, "reserved", reserved) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { @@ -396,7 +395,6 @@ __setup("nmi_watchdog=", setup_nmi_watchdog); -extern spinlock_t console_lock; static spinlock_t nmi_print_lock = SPIN_LOCK_UNLOCKED; inline void nmi_watchdog_tick(struct pt_regs * regs) @@ -439,8 +437,7 @@ * We are in trouble anyway, lets at least try * to get a message out. */ - spin_trylock(&console_lock); - spin_unlock(&console_lock); + bust_spinlocks(); printk("NMI Watchdog detected LOCKUP on CPU%d, registers:\n", cpu); show_registers(regs); printk("console shuts up ...\n"); @@ -954,8 +951,10 @@ #endif void __init trap_init(void) { +#ifdef CONFIG_EISA if (isa_readl(0x0FFFD9) == 'E'+('I'<<8)+('S'<<16)+('A'<<24)) EISA_bus = 1; +#endif set_trap_gate(0,÷_error); set_trap_gate(1,&debug); diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/lib/mmx.c linux/arch/i386/lib/mmx.c --- v2.4.0-test10/linux/arch/i386/lib/mmx.c Wed Oct 27 18:30:39 1999 +++ linux/arch/i386/lib/mmx.c Wed Nov 8 17:09:49 2000 @@ -16,6 +16,9 @@ * Add *user handling. Checksums are not a win with MMX on any CPU * tested so far for any MMX solution figured. * + * 22/09/2000 - Arjan van de Ven + * Improved for non-egineering-sample Athlons + * */ void *_mmx_memcpy(void *to, const void *from, size_t len) @@ -104,28 +107,26 @@ " pxor %%mm0, %%mm0\n" : : ); - for(i=0;i<4096/128;i++) + for(i=0;i<4096/64;i++) { __asm__ __volatile__ ( - " movq %%mm0, (%0)\n" - " movq %%mm0, 8(%0)\n" - " movq %%mm0, 16(%0)\n" - " movq %%mm0, 24(%0)\n" - " movq %%mm0, 32(%0)\n" - " movq %%mm0, 40(%0)\n" - " movq %%mm0, 48(%0)\n" - " movq %%mm0, 56(%0)\n" - " movq %%mm0, 64(%0)\n" - " movq %%mm0, 72(%0)\n" - " movq %%mm0, 80(%0)\n" - " movq %%mm0, 88(%0)\n" - " movq %%mm0, 96(%0)\n" - " movq %%mm0, 104(%0)\n" - " movq %%mm0, 112(%0)\n" - " movq %%mm0, 120(%0)\n" + " movntq %%mm0, (%0)\n" + " movntq %%mm0, 8(%0)\n" + " movntq %%mm0, 16(%0)\n" + " movntq %%mm0, 24(%0)\n" + " movntq %%mm0, 32(%0)\n" + " movntq %%mm0, 40(%0)\n" + " movntq %%mm0, 48(%0)\n" + " movntq %%mm0, 56(%0)\n" : : "r" (page) : "memory"); - page+=128; + page+=64; } + /* since movntq is weakly-ordered, a "sfence" is needed to become + * ordered again. + */ + __asm__ __volatile__ ( + " sfence \n" : : + ); stts(); } @@ -140,6 +141,9 @@ current->flags &= ~PF_USEDFPU; } + /* maybe the prefetch stuff can go before the expensive fnsave... + * but that is for later. -AV + */ __asm__ __volatile__ ( "1: prefetch (%0)\n" " prefetch 64(%0)\n" @@ -162,21 +166,21 @@ __asm__ __volatile__ ( "1: prefetch 320(%0)\n" "2: movq (%0), %%mm0\n" + " movntq %%mm0, (%1)\n" " movq 8(%0), %%mm1\n" + " movntq %%mm1, 8(%1)\n" " movq 16(%0), %%mm2\n" + " movntq %%mm2, 16(%1)\n" " movq 24(%0), %%mm3\n" - " movq %%mm0, (%1)\n" - " movq %%mm1, 8(%1)\n" - " movq %%mm2, 16(%1)\n" - " movq %%mm3, 24(%1)\n" - " movq 32(%0), %%mm0\n" - " movq 40(%0), %%mm1\n" - " movq 48(%0), %%mm2\n" - " movq 56(%0), %%mm3\n" - " movq %%mm0, 32(%1)\n" - " movq %%mm1, 40(%1)\n" - " movq %%mm2, 48(%1)\n" - " movq %%mm3, 56(%1)\n" + " movntq %%mm3, 24(%1)\n" + " movq 32(%0), %%mm4\n" + " movntq %%mm4, 32(%1)\n" + " movq 40(%0), %%mm5\n" + " movntq %%mm5, 40(%1)\n" + " movq 48(%0), %%mm6\n" + " movntq %%mm6, 48(%1)\n" + " movq 56(%0), %%mm7\n" + " movntq %%mm7, 56(%1)\n" ".section .fixup, \"ax\"\n" "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ " jmp 2b\n" @@ -189,6 +193,12 @@ from+=64; to+=64; } + /* since movntq is weakly-ordered, a "sfence" is needed to become + * ordered again. + */ + __asm__ __volatile__ ( + " sfence \n" : : + ); stts(); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- v2.4.0-test10/linux/arch/i386/mm/fault.c Tue Oct 31 12:42:26 2000 +++ linux/arch/i386/mm/fault.c Sat Nov 11 19:01:11 2000 @@ -77,6 +77,19 @@ return 0; } +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); +} + asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); extern unsigned long idt; @@ -250,6 +263,8 @@ * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. */ + + bust_spinlocks(); if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); diff -u --recursive --new-file v2.4.0-test10/linux/arch/ia64/config.in linux/arch/ia64/config.in --- v2.4.0-test10/linux/arch/ia64/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/ia64/config.in Thu Nov 16 12:51:28 2000 @@ -21,6 +21,8 @@ define_bool CONFIG_SWIOTLB y # for now... define_bool CONFIG_ISA n +define_bool CONFIG_EISA n +define_bool CONFIG_MCA n define_bool CONFIG_SBUS n choice 'IA-64 system type' \ diff -u --recursive --new-file v2.4.0-test10/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c --- v2.4.0-test10/linux/arch/ia64/ia32/sys_ia32.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ia64/ia32/sys_ia32.c Fri Nov 17 11:36:27 2000 @@ -3392,7 +3392,7 @@ } inode = file->f_dentry->d_inode; - if (!inode || !inode->i_sock || !socki_lookup(inode)) + if (!inode->i_sock || !socki_lookup(inode)) { *err = -ENOTSOCK; fput(file); diff -u --recursive --new-file v2.4.0-test10/linux/arch/ia64/kernel/semaphore.c linux/arch/ia64/kernel/semaphore.c --- v2.4.0-test10/linux/arch/ia64/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ia64/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -50,7 +50,7 @@ { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -70,7 +70,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -85,7 +85,7 @@ int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -121,7 +121,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -248,7 +248,7 @@ for (;;) { if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!sem->write_bias_granted) schedule(); } @@ -277,7 +277,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (sem->count < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (sem->count >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/m68k/config.in linux/arch/m68k/config.in --- v2.4.0-test10/linux/arch/m68k/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/config.in Thu Nov 16 12:51:28 2000 @@ -25,6 +25,8 @@ comment 'Platform dependent setup' define_bool CONFIG_ISA n +define_bool CONFIG_EISA n +define_bool CONFIG_MCA n define_bool CONFIG_PCMCIA n bool 'Amiga support' CONFIG_AMIGA diff -u --recursive --new-file v2.4.0-test10/linux/arch/m68k/kernel/semaphore.c linux/arch/m68k/kernel/semaphore.c --- v2.4.0-test10/linux/arch/m68k/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/m68k/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -180,7 +180,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(current, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); @@ -199,7 +199,7 @@ for (;;) { if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) break; - set_task_state(current, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(current, TASK_UNINTERRUPTIBLE); if (!sem->write_bias_granted) schedule(); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/mips/config.in linux/arch/mips/config.in --- v2.4.0-test10/linux/arch/mips/config.in Sun Oct 8 10:50:06 2000 +++ linux/arch/mips/config.in Thu Nov 16 12:51:28 2000 @@ -33,11 +33,13 @@ # unset CONFIG_ARC32 unset CONFIG_ISA +unset CONFIG_EISA unset CONFIG_PCI unset CONFIG_MIPS_JAZZ unset CONFIG_VIDEO_G364 unset CONFIG_PC_KEYB +define_bool CONFIG_MCA n define_bool CONFIG_SBUS n if [ "$CONFIG_ALGOR_P4032" = "y" ]; then @@ -59,7 +61,6 @@ define_bool CONFIG_PC_KEYB y fi if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then - define_bool CONFIG_ISA n define_bool CONFIG_COBALT_27 y define_bool CONFIG_COBALT_LCD y define_bool CONFIG_COBALT_SERIAL y @@ -83,6 +84,9 @@ if [ "$CONFIG_ISA" != "y" ]; then define_bool CONFIG_ISA n + define_bool CONFIG_EISA n +else + define_bool CONFIG_EISA y fi if [ "$CONFIG_PCI" != "y" ]; then diff -u --recursive --new-file v2.4.0-test10/linux/arch/mips/kernel/semaphore.c linux/arch/mips/kernel/semaphore.c --- v2.4.0-test10/linux/arch/mips/kernel/semaphore.c Thu Feb 24 22:52:30 2000 +++ linux/arch/mips/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -187,8 +187,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(tsk, (TASK_UNINTERRUPTIBLE - | TASK_EXCLUSIVE)); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= RW_LOCK_BIAS) break; schedule(); @@ -208,8 +207,7 @@ while (1) { if (test_and_clear_bit(1, &sem->granted)) break; - set_task_state(tsk, (TASK_UNINTERRUPTIBLE - | TASK_EXCLUSIVE)); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if ((sem->granted & 2) == 0) schedule(); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/mips64/config.in linux/arch/mips64/config.in --- v2.4.0-test10/linux/arch/mips64/config.in Sun Oct 8 10:50:07 2000 +++ linux/arch/mips64/config.in Thu Nov 16 12:51:28 2000 @@ -57,12 +57,16 @@ if [ "$CONFIG_ISA" != "y" ]; then define_bool CONFIG_ISA n + define_bool CONFIG_EISA n +else + define_bool CONFIG_EISA y fi if [ "$CONFIG_PCI" != "y" ]; then define_bool CONFIG_PCI n fi +define_bool CONFIG_MCA n define_bool CONFIG_SBUS n mainmenu_option next_comment diff -u --recursive --new-file v2.4.0-test10/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c --- v2.4.0-test10/linux/arch/mips64/kernel/linux32.c Thu Jul 27 18:36:54 2000 +++ linux/arch/mips64/kernel/linux32.c Wed Nov 8 19:01:34 2000 @@ -241,7 +241,7 @@ return -ENOMEM; new = 1; } - kaddr = (char *)kmap(page); + kaddr = kmap(page); if (new && offset) memset(kaddr, 0, offset); diff -u --recursive --new-file v2.4.0-test10/linux/arch/mips64/kernel/semaphore.c linux/arch/mips64/kernel/semaphore.c --- v2.4.0-test10/linux/arch/mips64/kernel/semaphore.c Thu Feb 24 22:53:35 2000 +++ linux/arch/mips64/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -187,8 +187,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(tsk, (TASK_UNINTERRUPTIBLE - | TASK_EXCLUSIVE)); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= RW_LOCK_BIAS) break; schedule(); @@ -208,8 +207,7 @@ while (1) { if (test_and_clear_bit(1, &sem->granted)) break; - set_task_state(tsk, (TASK_UNINTERRUPTIBLE - | TASK_EXCLUSIVE)); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if ((sem->granted & 2) == 0) schedule(); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c --- v2.4.0-test10/linux/arch/ppc/8xx_io/commproc.c Mon Jun 19 13:25:06 2000 +++ linux/arch/ppc/8xx_io/commproc.c Sat Nov 11 18:14:38 2000 @@ -149,7 +149,7 @@ /* After servicing the interrupt, we have to remove the status * indicator. */ - ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec); + ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << vec); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/config.in linux/arch/ppc/config.in --- v2.4.0-test10/linux/arch/ppc/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/ppc/config.in Thu Nov 16 12:51:28 2000 @@ -98,7 +98,11 @@ bool 'Mac-on-Linux support' CONFIG_MOL define_bool CONFIG_ISA n +define_bool CONFIG_EISA n define_bool CONFIG_SBUS n + +# Yes MCA RS/6000s exist but Linux-PPC does not currently support any +define_bool CONFIG_MCA n if [ "$CONFIG_APUS" = "y" -o "$CONFIG_4xx" = "y" -o \ "$CONFIG_8260" = "y" ]; then diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/apus_defconfig linux/arch/ppc/configs/apus_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/apus_defconfig Mon Jun 19 17:59:36 2000 +++ linux/arch/ppc/configs/apus_defconfig Sat Nov 11 18:14:38 2000 @@ -1,139 +1,161 @@ # # Automatically generated make config: don't edit # +# CONFIG_UID16 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y # # Platform support # CONFIG_PPC=y CONFIG_6xx=y +# CONFIG_4xx is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8260 is not set # CONFIG_8xx is not set -CONFIG_PMAC=y -# CONFIG_PREP is not set -# CONFIG_CHRP is not set -# CONFIG_ALL_PPC is not set +CONFIG_ALL_PPC=y +# CONFIG_GEMINI is not set +# CONFIG_EST8260 is not set # CONFIG_APUS is not set -# CONFIG_MBX is not set # CONFIG_SMP is not set -CONFIG_MACH_SPECIFIC=y +# CONFIG_ALTIVEC is not set # # General setup # -CONFIG_EXPERIMENTAL=y -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set +# CONFIG_ISA is not set +# CONFIG_SBUS is not set CONFIG_PCI=y -# CONFIG_PCI_QUIRKS is not set -CONFIG_PCI_OLD_PROC=y CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y CONFIG_BINFMT_MISC=m -# CONFIG_BINFMT_JAVA is not set +# CONFIG_PCI_NAMES is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set # CONFIG_VGA_CONSOLE is not set CONFIG_FB=y CONFIG_FB_COMPAT_XPMAC=y -CONFIG_PMAC_PBOOK=y -CONFIG_MAC_KEYBOARD=y -CONFIG_MAC_FLOPPY=y -CONFIG_MAC_SERIAL=y -CONFIG_ADBMOUSE=y +# CONFIG_PPC_RTC is not set CONFIG_PROC_DEVICETREE=y -# CONFIG_KGDB is not set -# CONFIG_XMON is not set -# CONFIG_TOTALMP is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_MOTOROLA_HOTSWAP is not set +# CONFIG_CMDLINE_BOOL is not set # -# Plug and Play support +# Memory Technology Devices (MTD) # -# CONFIG_PNP is not set +# CONFIG_MTD is not set # -# Block devices +# Plug and Play configuration # -# CONFIG_BLK_DEV_FD is not set -CONFIG_BLK_DEV_IDE=y +# CONFIG_PNP is not set +# CONFIG_ISAPNP is not set # -# Please see Documentation/ide.txt for help/info on IDE drives +# Block devices # -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=y -CONFIG_BLK_DEV_IDECD=y -# CONFIG_BLK_DEV_IDETAPE is not set -CONFIG_BLK_DEV_IDEFLOPPY=y -# CONFIG_BLK_DEV_IDESCSI is not set -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_RZ1000 is not set -# CONFIG_BLK_DEV_IDEPCI is not set -# CONFIG_BLK_DEV_SL82C105 is not set -CONFIG_BLK_DEV_IDE_PMAC=y -CONFIG_BLK_DEV_IDEDMA_PMAC=y -CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDEDMA_PMAC_AUTO=y -# CONFIG_IDE_CHIPSETS is not set +# 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_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=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_HD 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_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options # CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set CONFIG_NETLINK=y # CONFIG_RTNETLINK is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y 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_MROUTE is not set -CONFIG_IP_ALIAS=y +# CONFIG_INET_ECN is not set # CONFIG_SYN_COOKIES is not set - -# -# (it is safe to leave these untouched) -# -CONFIG_INET_RARP=y -CONFIG_IP_NOSR=y -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=m +# 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 # CONFIG_NET_HW_FLOWCONTROL is not set -# CONFIG_CPU_IS_SLOW is not set + +# +# QoS and/or fair queueing +# # CONFIG_NET_SCHED 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=y @@ -142,14 +164,17 @@ # SCSI support type (disk, tape, CD-ROM) # 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=y +CONFIG_SR_EXTRA_DEVS=2 # CONFIG_CHR_DEV_SG is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs # +# CONFIG_SCSI_DEBUG_QUEUES is not set # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set @@ -157,96 +182,136 @@ # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set # CONFIG_SCSI_AHA1542 is not set # CONFIG_SCSI_AHA1740 is not set CONFIG_SCSI_AIC7XXX=y -# CONFIG_OVERRIDE_CMDS is not set +# CONFIG_AIC7XXX_TCQ_ON_BY_DEFAULT is not set +CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 CONFIG_AIC7XXX_PROC_STATS=y CONFIG_AIC7XXX_RESET_DELAY=15 # CONFIG_SCSI_ADVANSYS is not set # CONFIG_SCSI_IN2000 is not set # 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 # CONFIG_SCSI_EATA_DMA is not set # CONFIG_SCSI_EATA_PIO is not set -# CONFIG_SCSI_EATA is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set # CONFIG_SCSI_NCR53C7xx is not set # CONFIG_SCSI_NCR53C8XX is not set +# CONFIG_SCSI_SYM53C8XX 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_QLOGIC_ISP is not set -# CONFIG_SCSI_SEAGATE is not set +# 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 -# CONFIG_SCSI_ULTRASTOR is not set # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_MESH=y CONFIG_SCSI_MESH_SYNC_RATE=5 CONFIG_SCSI_MAC53C94=y # +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# # Network device support # CONFIG_NETDEVICES=y + +# +# ARCnet devices +# # CONFIG_ARCNET is not set + +# +# Appletalk devices +# +# CONFIG_APPLETALK is not set # 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 + +# +# Ethernet (10 or 100Mbit) +# CONFIG_NET_ETHERNET=y CONFIG_MACE=y CONFIG_BMAC=y +# CONFIG_GMAC is not set +# CONFIG_NCR885E is not set +# CONFIG_OAKNET 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_RTL8139 is not set -# CONFIG_YELLOWFIN 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_EISA=y -# CONFIG_PCNET32 is not set -# CONFIG_AC3200 is not set -# CONFIG_APRICOT is not set -# CONFIG_CS89x0 is not set -CONFIG_DE4X5=y -CONFIG_DEC_ELCP=m -# CONFIG_DGRS is not set -# CONFIG_EEXPRESS_PRO100 is not set -# CONFIG_LNE390 is not set -# CONFIG_NE3210 is not set -# CONFIG_NE2K_PCI 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_ZNET is not set +# CONFIG_NET_PCI 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_DLCI is not set -# CONFIG_LTPC is not set -# CONFIG_COPS is not set -# CONFIG_IPDDP is not set CONFIG_PPP=y +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_ASYNC is not set +# CONFIG_PPP_SYNC_TTY is not set +# CONFIG_PPP_DEFLATE is not set +# CONFIG_PPP_BSDCOMP is not set +# CONFIG_PPPOE is not set +# CONFIG_SLIP is not set # -# CCP compressors for PPP are only built as modules. +# Wireless LAN (non-hamradio) # -# CONFIG_SLIP is not set # 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 -# CONFIG_HOSTESS_SV11 is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set # # Amateur Radio support @@ -254,27 +319,46 @@ # CONFIG_HAMRADIO is not set # +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set # -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# Old CD-ROM drivers (not SCSI, not IDE) # # CONFIG_CD_NO_IDESCSI is not set # # Console drivers # + +# +# 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 is not set CONFIG_FB_OF=y CONFIG_FB_CONTROL=y CONFIG_FB_PLATINUM=y CONFIG_FB_VALKYRIE=y -CONFIG_FB_ATY=y -CONFIG_FB_IMSTT=y CONFIG_FB_CT65550=y +CONFIG_FB_IMSTT=y # CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_MATROX is not set +CONFIG_FB_ATY=y +# 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 is not set CONFIG_FBCON_CFB8=y @@ -292,6 +376,21 @@ # CONFIG_FONT_ACORN_8x8 is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# +# CONFIG_ADB_CUDA is not set +# CONFIG_ADB_PMU is not set +CONFIG_MAC_FLOPPY=y +CONFIG_MAC_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_ADB is not set + +# # Character devices # CONFIG_VT=y @@ -301,58 +400,127 @@ # CONFIG_SERIAL_NONSTANDARD is not set CONFIG_UNIX98_PTYS=y CONFIG_UNIX98_PTY_COUNT=256 + +# +# 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_RTC is not set -# CONFIG_VIDEO_DEV is not set +# CONFIG_INTEL_RNG is not set CONFIG_NVRAM=y -# CONFIG_JOYSTICK 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 # -# Filesystems +# File systems # # CONFIG_QUOTA is not set -# CONFIG_MINIX_FS is not set -CONFIG_EXT2_FS=y -CONFIG_ISO9660_FS=y -# CONFIG_JOLIET 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 +# CONFIG_AFFS_FS is not set +CONFIG_HFS_FS=y +# CONFIG_BFS_FS is not set CONFIG_FAT_FS=m CONFIG_MSDOS_FS=m # 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=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=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=y +# CONFIG_NFSD_V3 is not set CONFIG_SUNRPC=y CONFIG_LOCKD=y -# CONFIG_CODA_FS is not set # CONFIG_SMB_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_NTFS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_AFFS_FS is not set -CONFIG_HFS_FS=y -# CONFIG_ROMFS_FS is not set -CONFIG_AUTOFS_FS=y -# CONFIG_UFS_FS is not set -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_SMD_DISKLABEL is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -CONFIG_DEVPTS_FS=y -# CONFIG_ADFS_FS is not set -# CONFIG_QNX4FS_FS is not set -CONFIG_MAC_PARTITION=y +# 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=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 @@ -369,6 +537,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 @@ -378,16 +550,40 @@ # 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 # # Sound # CONFIG_SOUND=y -CONFIG_DMASOUND=y +# CONFIG_DMASOUND_AWACS is not set +# 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 is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/bseip_defconfig linux/arch/ppc/configs/bseip_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/bseip_defconfig Mon Jun 19 17:59:36 2000 +++ linux/arch/ppc/configs/bseip_defconfig Sat Nov 11 18:14:38 2000 @@ -9,18 +9,27 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +# CONFIG_MODULES is not set + +# # Platform support # CONFIG_PPC=y # CONFIG_6xx is not set # CONFIG_4xx is not set -# CONFIG_PPC64BRIDGE is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8260 is not set CONFIG_8xx=y CONFIG_SERIAL_CONSOLE=y # CONFIG_RPXLITE is not set # CONFIG_RPXCLASSIC is not set CONFIG_BSEIP=y +# CONFIG_TQM8xxL is not set +# CONFIG_TQM860L is not set +# CONFIG_TQM860 is not set # CONFIG_MBX is not set # CONFIG_WINCEPT is not set # CONFIG_ALL_PPC is not set @@ -29,15 +38,13 @@ CONFIG_MATH_EMULATION=y # -# Loadable module support -# -# CONFIG_MODULES is not set - -# # General setup # +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set +# CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y @@ -56,6 +63,11 @@ # CONFIG_PARPORT is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Plug and Play configuration # # CONFIG_PNP is not set @@ -68,16 +80,25 @@ # 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=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# 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_RAID15_DANGEROUS is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -96,17 +117,11 @@ 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_INET_ECN is not set CONFIG_SYN_COOKIES=y - -# -# (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 @@ -117,10 +132,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 @@ -155,6 +171,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 @@ -173,6 +190,7 @@ # 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 is not set # CONFIG_NET_POCKET is not set @@ -180,8 +198,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 @@ -236,6 +255,15 @@ # CONFIG_FB is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# + +# # Character devices # # CONFIG_VT is not set @@ -260,19 +288,19 @@ # 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 - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -281,9 +309,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 @@ -301,6 +333,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 @@ -360,6 +393,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 @@ -375,7 +409,9 @@ # CONFIG_SCC1_ENET is not set CONFIG_SCC2_ENET=y # CONFIG_FEC_ENET is not set +# CONFIG_ENET_BIG_BUFFERS is not set CONFIG_8xxSMC2=y +# CONFIG_8xx_ALTSMC2 is not set # CONFIG_8xxSCC is not set # diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/common_defconfig Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/configs/common_defconfig Sat Nov 11 18:14:38 2000 @@ -36,6 +36,7 @@ # General setup # # CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set CONFIG_PCI=y @@ -58,7 +59,6 @@ CONFIG_VGA_CONSOLE=y CONFIG_FB=y CONFIG_FB_COMPAT_XPMAC=y -CONFIG_PMAC_PBOOK=y CONFIG_PPC_RTC=y CONFIG_PROC_DEVICETREE=y CONFIG_BOOTX_TEXT=y @@ -83,18 +83,25 @@ # 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=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# 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=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -130,6 +137,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 @@ -203,10 +211,11 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # 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_VIA82CXXX_TUNING is not set CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y @@ -262,6 +271,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 @@ -273,8 +283,6 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 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=y @@ -293,6 +301,8 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # 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 @@ -342,6 +352,7 @@ # 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=y @@ -358,26 +369,28 @@ # 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_ES3210 is not set -# CONFIG_EPIC100 is not set +# CONFIG_WINBOND_840 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 CONFIG_PPP=y CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y CONFIG_PPP_ASYNC=y # CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=y @@ -483,13 +496,15 @@ # # Macintosh device drivers # +CONFIG_ADB_CUDA=y +CONFIG_ADB_PMU=y +CONFIG_PMAC_PBOOK=y +CONFIG_PMAC_BACKLIGHT=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y # CONFIG_SERIAL_CONSOLE is not set CONFIG_ADB=y -CONFIG_ADB_CUDA=y CONFIG_ADB_MACIO=y -CONFIG_ADB_PMU=y CONFIG_INPUT_ADBHID=y CONFIG_MAC_HID=y CONFIG_MAC_ADBKEYCODES=y @@ -686,6 +701,7 @@ # 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 @@ -715,7 +731,6 @@ # 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 is not set # CONFIG_SOUND_AWE32_SYNTH is not set # CONFIG_SOUND_WAVEFRONT is not set @@ -768,6 +783,7 @@ # 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) diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/est8260_defconfig linux/arch/ppc/configs/est8260_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/est8260_defconfig Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/configs/est8260_defconfig Sat Nov 11 18:14:38 2000 @@ -38,6 +38,7 @@ # General setup # # CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set # CONFIG_PCI is not set @@ -81,18 +82,25 @@ # 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=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# 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=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -130,6 +138,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 @@ -183,6 +192,7 @@ # 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 is not set # CONFIG_NET_POCKET is not set @@ -190,8 +200,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 diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/gemini_defconfig Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/configs/gemini_defconfig Sat Nov 11 18:14:38 2000 @@ -9,12 +9,20 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # Platform support # CONFIG_PPC=y CONFIG_6xx=y # CONFIG_4xx is not set -# CONFIG_PPC64 is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8260 is not set # CONFIG_8xx is not set # CONFIG_ALL_PPC is not set @@ -26,15 +34,10 @@ CONFIG_MACH_SPECIFIC=y # -# Loadable module support -# -CONFIG_MODULES=y -CONFIG_MODVERSIONS=y -CONFIG_KMOD=y - -# # General setup # +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set CONFIG_PCI=y @@ -46,6 +49,7 @@ CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set +# CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set # CONFIG_PCMCIA is not set @@ -55,33 +59,47 @@ # CONFIG_PARPORT is not set # CONFIG_VGA_CONSOLE is not set # CONFIG_FB is not set -# CONFIG_PMAC_PBOOK is not set -# CONFIG_MAC_FLOPPY is not set -# CONFIG_MAC_SERIAL is not set -# CONFIG_ADB is not set +# CONFIG_PPC_RTC is not set # CONFIG_PROC_DEVICETREE is not set # CONFIG_BOOTX_TEXT is not set # CONFIG_MOTOROLA_HOTSWAP 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_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 is not set +# CONFIG_BLK_DEV_INITRD is not set # -# Additional Block Devices +# Multi-device support (RAID and LVM) # -# CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +# CONFIG_MD is not set # CONFIG_BLK_DEV_MD is not set -# CONFIG_RAID15_DANGEROUS is not set -# CONFIG_BLK_DEV_RAM 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_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -98,17 +116,11 @@ 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_MROUTE is not set -CONFIG_IP_ALIAS=y +# CONFIG_INET_ECN is not set CONFIG_SYN_COOKIES=y - -# -# (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 @@ -119,10 +131,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 @@ -167,6 +180,7 @@ # # SCSI low-level drivers # +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_7000FASST is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AHA152X is not set @@ -178,6 +192,8 @@ # 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 # CONFIG_SCSI_EATA_DMA is not set @@ -185,17 +201,29 @@ # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set # CONFIG_SCSI_NCR53C406A is not set -# CONFIG_SCSI_SYM53C416 is not set -# CONFIG_SCSI_SIM710 is not set -# CONFIG_SCSI_NCR53C7xx_sync is not set -# CONFIG_SCSI_NCR53C7xx_FAST is not set -# CONFIG_SCSI_NCR53C7xx_DISCONNECT is not set +# CONFIG_SCSI_NCR53C7xx is not set +CONFIG_SCSI_NCR53C8XX=y +# CONFIG_SCSI_SYM53C8XX is not set +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 +# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT 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_QLOGIC_ISP is not set +# 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 # CONFIG_SCSI_DEBUG is not set @@ -203,6 +231,11 @@ # CONFIG_SCSI_MAC53C94 is not set # +# IEEE 1394 (FireWire) support +# +# CONFIG_IEEE1394 is not set + +# # Network device support # CONFIG_NETDEVICES=y @@ -214,6 +247,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 @@ -232,6 +266,7 @@ # 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 is not set # CONFIG_NET_POCKET is not set @@ -239,8 +274,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 @@ -295,6 +331,15 @@ # CONFIG_FB is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# + +# # Character devices # # CONFIG_VT is not set @@ -320,19 +365,19 @@ # 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 - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -341,8 +386,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 @@ -351,27 +401,39 @@ # 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=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 @@ -379,11 +441,23 @@ # 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 diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/mbx_defconfig linux/arch/ppc/configs/mbx_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/mbx_defconfig Sat Nov 27 15:41:59 1999 +++ linux/arch/ppc/configs/mbx_defconfig Sat Nov 11 18:14:38 2000 @@ -1,98 +1,110 @@ # -# Automatically generated by make menuconfig: don't edit +# Automatically generated make config: don't edit # +# CONFIG_UID16 is not set + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y + +# +# Loadable module support +# +# CONFIG_MODULES is not set # # Platform support # CONFIG_PPC=y # CONFIG_6xx is not set +# CONFIG_4xx is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8260 is not set CONFIG_8xx=y -# CONFIG_PMAC is not set -# CONFIG_PREP is not set -# CONFIG_CHRP is not set -# CONFIG_ALL_PPC is not set -# CONFIG_APUS is not set +CONFIG_SERIAL_CONSOLE=y +# CONFIG_RPXLITE is not set +# CONFIG_RPXCLASSIC is not set +# CONFIG_BSEIP is not set +# CONFIG_TQM8xxL is not set +# CONFIG_TQM860L is not set +# CONFIG_TQM860 is not set CONFIG_MBX=y -CONFIG_MACH_SPECIFIC=y +# CONFIG_WINCEPT is not set +# CONFIG_ALL_PPC is not set # CONFIG_SMP is not set -CONFIG_SERIAL_CONSOLE=y +CONFIG_MACH_SPECIFIC=y +CONFIG_MATH_EMULATION=y # # General setup # -CONFIG_EXPERIMENTAL=y -# CONFIG_MODULES is not set -CONFIG_PCI=y -# CONFIG_PCI_QUIRKS is not set -CONFIG_PCI_OLD_PROC=y +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set +# CONFIG_ISA is not set +# CONFIG_SBUS is not set +# CONFIG_PCI_QSPAN is not set +# CONFIG_PCI is not set CONFIG_NET=y # CONFIG_SYSCTL is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set -# CONFIG_BINFMT_JAVA is not set +# CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set -# CONFIG_PMAC_PBOOK is not set -# CONFIG_MAC_KEYBOARD is not set -# CONFIG_MAC_FLOPPY is not set -# CONFIG_MAC_SERIAL is not set -# CONFIG_ADBMOUSE is not set -# CONFIG_BLK_DEV_IDE_PMAC is not set -# CONFIG_PROC_DEVICETREE is not set -# CONFIG_KGDB is not set -# CONFIG_XMON is not set -# CONFIG_TOTALMP is not set -# CONFIG_BOOTX_TEXT is not set # -# Plug and Play support +# 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_IDE=y -# CONFIG_BLK_DEV_HD_IDE is not set -CONFIG_BLK_DEV_IDEDISK=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_RZ1000 is not set -CONFIG_BLK_DEV_IDEPCI=y -CONFIG_BLK_DEV_IDEDMA=y -# CONFIG_BLK_DEV_OFFBOARD is not set -CONFIG_IDEDMA_PCI_AUTO=y -# CONFIG_BLK_DEV_OPTI621 is not set -# CONFIG_BLK_DEV_TRM290 is not set -# CONFIG_BLK_DEV_NS87415 is not set -# CONFIG_BLK_DEV_VIA82CXXX is not set -# CONFIG_BLK_DEV_CMD646 is not set -CONFIG_BLK_DEV_SL82C105=y -# 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 is not set # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_MD is not set # CONFIG_BLK_DEV_RAM is not set -# CONFIG_BLK_DEV_XD is not set -CONFIG_PARIDE_PARPORT=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_HD 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_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options # # CONFIG_PACKET is not set # CONFIG_NETLINK is not set -# CONFIG_FIREWALL is not set +# CONFIG_NETFILTER is not set # CONFIG_FILTER is not set CONFIG_UNIX=y CONFIG_INET=y @@ -101,26 +113,29 @@ 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 -# CONFIG_INET_RARP is not set -CONFIG_IP_NOSR=y -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_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 # CONFIG_NET_HW_FLOWCONTROL is not set -CONFIG_CPU_IS_SLOW=y # # QoS and/or fair queueing @@ -128,6 +143,13 @@ # CONFIG_NET_SCHED 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 @@ -136,33 +158,66 @@ # 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_MACE is not set # CONFIG_BMAC is not set +# CONFIG_GMAC is not set +# CONFIG_NCR885E is not set +# CONFIG_OAKNET 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_RTL8139 is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_ACENIC 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_EISA is not set +# CONFIG_NET_PCI 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_DLCI 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_SHAPER is not set -# CONFIG_HOSTESS_SV11 is not set -# CONFIG_COSA 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 @@ -170,12 +225,17 @@ # CONFIG_HAMRADIO is not set # +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set # -# CD-ROM drivers (not for SCSI or IDE/ATAPI drives) +# Old CD-ROM drivers (not SCSI, not IDE) # # CONFIG_CD_NO_IDESCSI is not set @@ -184,83 +244,182 @@ # # +# Frame-buffer support +# +# CONFIG_FB is not set + +# +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# + +# # Character devices # -CONFIG_VT=y -# CONFIG_VT_CONSOLE is not set -CONFIG_SERIAL=y -CONFIG_SERIAL_CONSOLE=y +# CONFIG_VT is not set +# 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 +# I2C support # -# CONFIG_VIDEO_DEV is not set +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_MOUSE is not set # -# Joystick support +# 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 # -# Filesystems +# 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 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_BSD_DISKLABEL is not set +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_SMD_DISKLABEL is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL 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 # # Sound # # CONFIG_SOUND is not set + +# +# MPC8xx CPM Options +# +CONFIG_SCC_ENET=y +CONFIG_SCC1_ENET=y +# CONFIG_FEC_ENET is not set +CONFIG_ENET_BIG_BUFFERS=y +CONFIG_8xxSMC2=y +# CONFIG_8xx_ALTSMC2 is not set +CONFIG_8xxSCC=y + +# +# Generic MPC8xx Options +# +CONFIG_8xx_COPYBACK=y +CONFIG_8xx_CPU6=y + +# +# USB support +# +# CONFIG_USB is not set + +# +# Kernel hacking +# +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_KGDB is not set +# CONFIG_XMON is not set diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/oak_defconfig Mon Jun 19 17:59:36 2000 +++ linux/arch/ppc/configs/oak_defconfig Sat Nov 11 18:14:38 2000 @@ -1,6 +1,7 @@ # -# Default configuration for the IBM PowerPC 403 "Oak" evaluation boards. +# Automatically generated make config: don't edit # +# CONFIG_UID16 is not set # # Code maturity level options @@ -8,13 +9,21 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # Platform support # CONFIG_PPC=y # CONFIG_6xx is not set CONFIG_4xx=y -# CONFIG_PPC64BRIDGE is not set -# CONFIG_82xx is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8260 is not set # CONFIG_8xx is not set CONFIG_OAK=y # CONFIG_WALNUT is not set @@ -23,35 +32,33 @@ # CONFIG_MATH_EMULATION is not set # -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# # General setup # +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set +# CONFIG_ISA is not set +# CONFIG_SBUS is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set -# CONFIG_PMAC_PBOOK is not set -# CONFIG_MAC_FLOPPY is not set -# CONFIG_MAC_SERIAL is not set -# CONFIG_ADB is not set -# CONFIG_PROC_DEVICETREE is not set -# CONFIG_TOTALMP is not set -# CONFIG_BOOTX_TEXT is not set -# CONFIG_MOTOROLA_HOTSWAP is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set # # Plug and Play configuration @@ -63,22 +70,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_CPQ_CISS_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_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=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD 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_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -94,17 +107,11 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y CONFIG_IP_PNP_RARP=y -# 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_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 @@ -115,10 +122,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 @@ -130,6 +138,13 @@ # CONFIG_NET_SCHED 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 @@ -144,7 +159,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 # @@ -153,25 +170,26 @@ CONFIG_NET_ETHERNET=y # CONFIG_MACE is not set # CONFIG_BMAC is not set +# CONFIG_GMAC is not set # CONFIG_NCR885E is not set CONFIG_OAKNET=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_RTL8139 is not set -# CONFIG_DM9102 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_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 @@ -184,7 +202,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 @@ -202,6 +220,11 @@ # CONFIG_HAMRADIO is not set # +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -221,6 +244,15 @@ # CONFIG_FB is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# + +# # Character devices # # CONFIG_VT is not set @@ -240,24 +272,24 @@ # # CONFIG_BUSMOUSE is not set # CONFIG_MOUSE is not set -# CONFIG_QIC02_TAPE is not set # -# Watchdog Cards +# Joysticks # -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set +# CONFIG_JOYSTICK is not set # -# Video For Linux +# Input core support is needed for joysticks # -# CONFIG_VIDEO_DEV is not set +# CONFIG_QIC02_TAPE is not set # -# Joystick support +# Watchdog Cards # -# CONFIG_JOYSTICK is not set +# 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 @@ -266,19 +298,22 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_AGP is not set # CONFIG_DRM is not set # -# Support for USB +# Multimedia devices # -# CONFIG_USB is not set +# CONFIG_VIDEO_DEV is not set # -# Filesystems +# 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 @@ -287,45 +322,71 @@ # 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_UDF_FS 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_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set +CONFIG_MSDOS_PARTITION=y # CONFIG_NLS is not set # # Sound # # CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/rpxcllf_defconfig linux/arch/ppc/configs/rpxcllf_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/rpxcllf_defconfig Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/configs/rpxcllf_defconfig Sat Nov 11 18:14:38 2000 @@ -41,8 +41,10 @@ # General setup # # CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set +# CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y @@ -78,18 +80,25 @@ # 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=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# 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=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -127,6 +136,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 @@ -180,6 +190,7 @@ # 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 is not set # CONFIG_NET_POCKET is not set @@ -187,8 +198,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 diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/rpxlite_defconfig linux/arch/ppc/configs/rpxlite_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/rpxlite_defconfig Mon Jun 19 17:59:36 2000 +++ linux/arch/ppc/configs/rpxlite_defconfig Sat Nov 11 18:14:38 2000 @@ -9,18 +9,27 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +# CONFIG_MODULES is not set + +# # Platform support # CONFIG_PPC=y # CONFIG_6xx is not set # CONFIG_4xx is not set -# CONFIG_PPC64BRIDGE is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8260 is not set CONFIG_8xx=y CONFIG_SERIAL_CONSOLE=y CONFIG_RPXLITE=y # CONFIG_RPXCLASSIC is not set # CONFIG_BSEIP is not set +# CONFIG_TQM8xxL is not set +# CONFIG_TQM860L is not set +# CONFIG_TQM860 is not set # CONFIG_MBX is not set # CONFIG_WINCEPT is not set # CONFIG_ALL_PPC is not set @@ -29,15 +38,13 @@ CONFIG_MATH_EMULATION=y # -# Loadable module support -# -# CONFIG_MODULES is not set - -# # General setup # +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set +# CONFIG_PCI_QSPAN is not set # CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y @@ -56,6 +63,11 @@ # CONFIG_PARPORT is not set # +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# # Plug and Play configuration # # CONFIG_PNP is not set @@ -68,16 +80,25 @@ # 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=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# 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_RAID15_DANGEROUS is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_INITRD=y +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -96,17 +117,11 @@ 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_INET_ECN is not set CONFIG_SYN_COOKIES=y - -# -# (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 @@ -117,10 +132,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 @@ -155,6 +171,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 @@ -173,6 +190,7 @@ # 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 is not set # CONFIG_NET_POCKET is not set @@ -180,8 +198,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 @@ -236,6 +255,15 @@ # CONFIG_FB is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# + +# # Character devices # # CONFIG_VT is not set @@ -260,19 +288,19 @@ # 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 - -# -# Video For Linux -# -# CONFIG_VIDEO_DEV is not set # CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set @@ -281,9 +309,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 @@ -301,6 +333,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 @@ -360,6 +393,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 @@ -375,6 +409,7 @@ # CONFIG_SCC1_ENET is not set CONFIG_SCC2_ENET=y # CONFIG_FEC_ENET is not set +# CONFIG_ENET_BIG_BUFFERS is not set # CONFIG_8xxSMC2 is not set # CONFIG_8xxSCC is not set diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig --- v2.4.0-test10/linux/arch/ppc/configs/walnut_defconfig Mon Jun 19 17:59:36 2000 +++ linux/arch/ppc/configs/walnut_defconfig Sat Nov 11 18:14:38 2000 @@ -1,6 +1,7 @@ # -# Default configuration for the IBM PowerPC 405GP "Walnut" evaluation board. +# Automatically generated make config: don't edit # +# CONFIG_UID16 is not set # # Code maturity level options @@ -8,13 +9,21 @@ CONFIG_EXPERIMENTAL=y # +# Loadable module support +# +CONFIG_MODULES=y +# CONFIG_MODVERSIONS is not set +CONFIG_KMOD=y + +# # Platform support # CONFIG_PPC=y # CONFIG_6xx is not set CONFIG_4xx=y -# CONFIG_PPC64BRIDGE is not set -# CONFIG_82xx is not set +# CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set +# CONFIG_8260 is not set # CONFIG_8xx is not set # CONFIG_OAK is not set CONFIG_WALNUT=y @@ -23,35 +32,33 @@ # CONFIG_MATH_EMULATION is not set # -# Loadable module support -# -CONFIG_MODULES=y -# CONFIG_MODVERSIONS is not set -CONFIG_KMOD=y - -# # General setup # -CONFIG_PCI=y +# CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set +# CONFIG_ISA is not set +# CONFIG_SBUS is not set +# CONFIG_PCI is not set CONFIG_NET=y CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y # CONFIG_BINFMT_MISC is not set # CONFIG_HOTPLUG is not set +# CONFIG_PCMCIA is not set + +# +# Parallel port support +# # CONFIG_PARPORT is not set -# CONFIG_VGA_CONSOLE is not set -# CONFIG_FB is not set -# CONFIG_PMAC_PBOOK is not set -# CONFIG_MAC_FLOPPY is not set -# CONFIG_MAC_SERIAL is not set -# CONFIG_ADB is not set -# CONFIG_PROC_DEVICETREE is not set -# CONFIG_TOTALMP is not set -# CONFIG_BOOTX_TEXT is not set -# CONFIG_MOTOROLA_HOTSWAP is not set + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set # # Plug and Play configuration @@ -63,22 +70,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_CPQ_CISS_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_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=y -# CONFIG_PARIDE is not set -# CONFIG_BLK_DEV_IDE_MODES is not set -# CONFIG_BLK_DEV_HD 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_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -94,17 +107,11 @@ CONFIG_IP_PNP=y CONFIG_IP_PNP_BOOTP=y CONFIG_IP_PNP_RARP=y -# 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_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 @@ -115,10 +122,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 @@ -130,6 +138,13 @@ # CONFIG_NET_SCHED 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 @@ -144,7 +159,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 # @@ -153,25 +170,26 @@ CONFIG_NET_ETHERNET=y # CONFIG_MACE is not set # CONFIG_BMAC is not set +# CONFIG_GMAC is not set # CONFIG_NCR885E is not set # CONFIG_OAKNET 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_RTL8139 is not set -# CONFIG_DM9102 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_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 @@ -184,7 +202,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 @@ -202,6 +220,11 @@ # CONFIG_HAMRADIO is not set # +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# # ISDN subsystem # # CONFIG_ISDN is not set @@ -221,6 +244,15 @@ # CONFIG_FB is not set # +# Input core support +# +# CONFIG_INPUT is not set + +# +# Macintosh device drivers +# + +# # Character devices # # CONFIG_VT is not set @@ -234,30 +266,33 @@ # I2C support # CONFIG_I2C=y +# 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 is not set -# CONFIG_QIC02_TAPE is not set # -# Watchdog Cards +# Joysticks # -# CONFIG_WATCHDOG is not set -# CONFIG_NVRAM is not set -# CONFIG_RTC is not set +# CONFIG_JOYSTICK is not set # -# Video For Linux +# Input core support is needed for joysticks # -# CONFIG_VIDEO_DEV is not set +# CONFIG_QIC02_TAPE is not set # -# Joystick support +# Watchdog Cards # -# CONFIG_JOYSTICK is not set +# 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 @@ -266,19 +301,22 @@ # Ftape, the floppy tape device driver # # CONFIG_FTAPE is not set +# CONFIG_AGP is not set # CONFIG_DRM is not set # -# Support for USB +# Multimedia devices # -# CONFIG_USB is not set +# CONFIG_VIDEO_DEV is not set # -# Filesystems +# 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 @@ -287,45 +325,71 @@ # 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_UDF_FS 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_MAC_PARTITION is not set -# CONFIG_MSDOS_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_SUN_PARTITION is not set +CONFIG_MSDOS_PARTITION=y # CONFIG_NLS is not set # # Sound # # CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/defconfig linux/arch/ppc/defconfig --- v2.4.0-test10/linux/arch/ppc/defconfig Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/defconfig Sat Nov 11 18:14:38 2000 @@ -36,6 +36,7 @@ # General setup # # CONFIG_HIGHMEM is not set +# CONFIG_MOL is not set # CONFIG_ISA is not set # CONFIG_SBUS is not set CONFIG_PCI=y @@ -58,7 +59,6 @@ CONFIG_VGA_CONSOLE=y CONFIG_FB=y CONFIG_FB_COMPAT_XPMAC=y -CONFIG_PMAC_PBOOK=y CONFIG_PPC_RTC=y CONFIG_PROC_DEVICETREE=y CONFIG_BOOTX_TEXT=y @@ -83,18 +83,25 @@ # 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=y # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# 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=y -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_INITRD=y +# CONFIG_BLK_DEV_LVM is not set +# CONFIG_LVM_PROC_FS is not set # # Networking options @@ -130,6 +137,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 @@ -203,10 +211,11 @@ # CONFIG_BLK_DEV_OPTI621 is not set # CONFIG_BLK_DEV_PDC202XX is not set # 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_VIA82CXXX_TUNING is not set CONFIG_BLK_DEV_SL82C105=y CONFIG_BLK_DEV_IDE_PMAC=y CONFIG_BLK_DEV_IDEDMA_PMAC=y @@ -262,6 +271,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 @@ -273,8 +283,6 @@ # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 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=y @@ -293,6 +301,8 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # 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 @@ -342,6 +352,7 @@ # 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=y @@ -358,26 +369,28 @@ # 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_ES3210 is not set -# CONFIG_EPIC100 is not set +# CONFIG_WINBOND_840 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 CONFIG_PPP=y CONFIG_PPP_MULTILINK=y -CONFIG_PPP_FILTER=y CONFIG_PPP_ASYNC=y # CONFIG_PPP_SYNC_TTY is not set CONFIG_PPP_DEFLATE=y @@ -483,13 +496,15 @@ # # Macintosh device drivers # +CONFIG_ADB_CUDA=y +CONFIG_ADB_PMU=y +CONFIG_PMAC_PBOOK=y +CONFIG_PMAC_BACKLIGHT=y CONFIG_MAC_FLOPPY=y CONFIG_MAC_SERIAL=y # CONFIG_SERIAL_CONSOLE is not set CONFIG_ADB=y -CONFIG_ADB_CUDA=y CONFIG_ADB_MACIO=y -CONFIG_ADB_PMU=y CONFIG_INPUT_ADBHID=y CONFIG_MAC_HID=y CONFIG_MAC_ADBKEYCODES=y @@ -686,6 +701,7 @@ # 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 @@ -715,7 +731,6 @@ # 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 is not set # CONFIG_SOUND_AWE32_SYNTH is not set # CONFIG_SOUND_WAVEFRONT is not set @@ -768,17 +783,13 @@ # 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) # CONFIG_USB_HID=y # CONFIG_USB_WACOM is not set - -# -# Mac-on-Linux (MOL) support -# -# CONFIG_MOL is not set # # Kernel hacking diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S --- v2.4.0-test10/linux/arch/ppc/kernel/entry.S Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/kernel/entry.S Sat Nov 11 18:14:38 2000 @@ -298,12 +298,10 @@ SYNC RFI -#ifdef CONFIG_SMP - .globl ret_from_smpfork -ret_from_smpfork: + .globl ret_from_fork +ret_from_fork: bl schedule_tail b ret_from_except -#endif .globl ret_from_intercept ret_from_intercept: diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S --- v2.4.0-test10/linux/arch/ppc/kernel/hashtable.S Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/kernel/hashtable.S Sat Nov 11 18:14:38 2000 @@ -90,9 +90,14 @@ REST_2GPRS(7, r21) #endif /* Get PTE (linux-style) and check access */ + lis r0,KERNELBASE@h /* check if kernel address */ + cmplw 0,r3,r0 mfspr r2,SPRG3 /* current task's THREAD (phys) */ lwz r5,PGDIR(r2) /* virt page-table root */ - tophys(r5,r5) /* convert to phys addr */ + blt+ 112f /* assume user more likely */ + lis r5,swapper_pg_dir@ha /* if kernel address, use */ + addi r5,r5,swapper_pg_dir@l /* kernel page table */ +112: tophys(r5,r5) /* convert to phys addr */ rlwimi r5,r3,12,20,29 /* insert top 10 bits of address */ lwz r5,0(r5) /* get pmd entry */ rlwinm. r5,r5,0,0,19 /* extract address of pte page */ @@ -152,11 +157,7 @@ mfsrin r5,r3 /* get segment reg for segment */ rlwinm r5,r5,0,5,31 sldi r5,r5,12 - -#ifndef CONFIG_SMP /* do this later for SMP */ ori r5,r5,1 /* set V (valid) bit */ -#endif - rlwimi r5,r3,16,20,24 /* put in API (abbrev page index) */ /* Get the address of the primary PTE group in the hash table */ .globl hash_page_patch_A @@ -284,7 +285,9 @@ */ found_empty: found_slot: - std r5,0(r3) /* clear V (valid) bit in PTE */ + li r0,1 + andc r5,r5,r0 /* clear V (valid) bit in PTE */ + std r5,0(r3) sync tlbsync sync @@ -299,11 +302,7 @@ /* Construct the high word of the PPC-style PTE */ mfsrin r5,r3 /* get segment reg for segment */ rlwinm r5,r5,7,1,24 /* put VSID in 0x7fffff80 bits */ - -#ifndef CONFIG_SMP /* do this later for SMP */ oris r5,r5,0x8000 /* set V (valid) bit */ -#endif - rlwimi r5,r3,10,26,31 /* put in API (abbrev page index) */ /* Get the address of the primary PTE group in the hash table */ .globl hash_page_patch_A @@ -417,7 +416,8 @@ */ found_empty: found_slot: - stw r5,0(r3) /* clear V (valid) bit in PTE */ + rlwinm r5,r5,0,1,31 /* clear V (valid) bit in PTE */ + stw r5,0(r3) sync tlbsync sync diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S --- v2.4.0-test10/linux/arch/ppc/kernel/head.S Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/kernel/head.S Sat Nov 11 18:14:38 2000 @@ -521,10 +521,15 @@ */ mfctr r0 /* Get PTE (linux-style) and check access */ + mfspr r3,IMISS + lis r1,KERNELBASE@h /* check if kernel address */ + cmplw 0,r3,r1 mfspr r2,SPRG3 lwz r2,PGDIR(r2) - tophys(r2,r2) - mfspr r3,IMISS + blt+ 112f + lis r2,swapper_pg_dir@ha /* if kernel address, use */ + addi r2,r2,swapper_pg_dir@l /* kernel page table */ +112: tophys(r2,r2) rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ rlwinm. r2,r2,0,0,19 /* extract address of pte page */ @@ -588,10 +593,15 @@ */ mfctr r0 /* Get PTE (linux-style) and check access */ + mfspr r3,DMISS + lis r1,KERNELBASE@h /* check if kernel address */ + cmplw 0,r3,r1 mfspr r2,SPRG3 lwz r2,PGDIR(r2) - tophys(r2,r2) - mfspr r3,DMISS + blt+ 112f + lis r2,swapper_pg_dir@ha /* if kernel address, use */ + addi r2,r2,swapper_pg_dir@l /* kernel page table */ +112: tophys(r2,r2) rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ rlwinm. r2,r2,0,0,19 /* extract address of pte page */ @@ -654,10 +664,15 @@ */ mfctr r0 /* Get PTE (linux-style) and check access */ + mfspr r3,DMISS + lis r1,KERNELBASE@h /* check if kernel address */ + cmplw 0,r3,r1 mfspr r2,SPRG3 lwz r2,PGDIR(r2) - tophys(r2,r2) - mfspr r3,DMISS + blt+ 112f + lis r2,swapper_pg_dir@ha /* if kernel address, use */ + addi r2,r2,swapper_pg_dir@l /* kernel page table */ +112: tophys(r2,r2) rlwimi r2,r3,12,20,29 /* insert top 10 bits of address */ lwz r2,0(r2) /* get pmd entry */ rlwinm. r2,r2,0,0,19 /* extract address of pte page */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c --- v2.4.0-test10/linux/arch/ppc/kernel/irq.c Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/kernel/irq.c Sat Nov 11 18:19:56 2000 @@ -343,6 +343,11 @@ return 0; } +unsigned int probe_irq_mask(unsigned long irqs) +{ + return 0; +} + void __init init_IRQ(void) { static int once = 0; diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S --- v2.4.0-test10/linux/arch/ppc/kernel/misc.S Sun Oct 8 10:50:07 2000 +++ linux/arch/ppc/kernel/misc.S Sat Nov 11 18:14:38 2000 @@ -1219,11 +1219,7 @@ .long sys_getresuid /* 165 */ .long sys_query_module .long sys_poll -#ifdef CONFIG_NFSD .long sys_nfsservctl -#else - .long sys_ni_syscall -#endif .long sys_setresgid .long sys_getresgid /* 170 */ .long sys_prctl diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c --- v2.4.0-test10/linux/arch/ppc/kernel/pci.c Sun Oct 8 10:50:08 2000 +++ linux/arch/ppc/kernel/pci.c Tue Nov 7 11:25:00 2000 @@ -344,11 +344,6 @@ ranges->mem_end -= bus->resource[1]->start; } -unsigned long resource_fixup(struct pci_dev * dev, struct resource * res, - unsigned long start, unsigned long size) -{ - return start; -} void __init pcibios_fixup_bus(struct pci_bus *bus) { diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/ppc8260_pic.c linux/arch/ppc/kernel/ppc8260_pic.c --- v2.4.0-test10/linux/arch/ppc/kernel/ppc8260_pic.c Tue May 2 13:05:40 2000 +++ linux/arch/ppc/kernel/ppc8260_pic.c Sat Nov 11 18:14:38 2000 @@ -79,7 +79,7 @@ sipnr = &(immr->im_intctl.ic_sipnrh); ppc_cached_irq_mask[word] &= ~(1 << (31 - bit)); simr[word] = ppc_cached_irq_mask[word]; - sipnr[word] = 1 << bit; + sipnr[word] = 1 << (31 - bit); } struct hw_interrupt_type ppc8260_pic = { diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c --- v2.4.0-test10/linux/arch/ppc/kernel/ppc_ksyms.c Sun Oct 8 10:50:08 2000 +++ linux/arch/ppc/kernel/ppc_ksyms.c Sat Nov 11 18:23:10 2000 @@ -79,6 +79,7 @@ EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); EXPORT_SYMBOL(disable_irq_nosync); +EXPORT_SYMBOL(probe_irq_mask); #ifdef CONFIG_SMP EXPORT_SYMBOL(kernel_flag); #endif /* CONFIG_SMP */ @@ -222,6 +223,8 @@ #ifdef CONFIG_ADB_PMU EXPORT_SYMBOL(pmu_request); EXPORT_SYMBOL(pmu_poll); +EXPORT_SYMBOL(pmu_suspend); +EXPORT_SYMBOL(pmu_resume); #endif /* CONFIG_ADB_PMU */ #ifdef CONFIG_PMAC_PBOOK EXPORT_SYMBOL(pmu_register_sleep_notifier); @@ -298,6 +301,7 @@ EXPORT_SYMBOL(xmon); #endif EXPORT_SYMBOL(down_read_failed); +EXPORT_SYMBOL(down_write_failed); #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) extern void (*debugger)(struct pt_regs *regs); diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c --- v2.4.0-test10/linux/arch/ppc/kernel/process.c Sun Oct 8 10:50:08 2000 +++ linux/arch/ppc/kernel/process.c Sat Nov 11 18:14:38 2000 @@ -319,11 +319,8 @@ { unsigned long msr; struct pt_regs * childregs, *kregs; -#ifdef CONFIG_SMP - extern void ret_from_smpfork(void); -#else - extern void ret_from_except(void); -#endif + extern void ret_from_fork(void); + /* Copy registers */ childregs = ((struct pt_regs *) ((unsigned long)p + sizeof(union task_union) @@ -336,11 +333,7 @@ p->thread.ksp = (unsigned long) childregs - STACK_FRAME_OVERHEAD; p->thread.ksp -= sizeof(struct pt_regs ) + STACK_FRAME_OVERHEAD; kregs = (struct pt_regs *)(p->thread.ksp + STACK_FRAME_OVERHEAD); -#ifdef CONFIG_SMP - kregs->nip = (unsigned long)ret_from_smpfork; -#else - kregs->nip = (unsigned long)ret_from_except; -#endif + kregs->nip = (unsigned long)ret_from_fork; asm volatile("mfmsr %0" : "=r" (msr):); kregs->msr = msr; kregs->gpr[1] = (unsigned long)childregs - STACK_FRAME_OVERHEAD; diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c --- v2.4.0-test10/linux/arch/ppc/kernel/semaphore.c Wed Feb 9 19:43:47 2000 +++ linux/arch/ppc/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -152,7 +152,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); do { - __set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + __set_task_state(tsk, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&sem->lock); schedule(); spin_lock_irq(&sem->lock); @@ -169,7 +169,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); do { - __set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + __set_task_state(tsk, TASK_UNINTERRUPTIBLE); spin_unlock_irq(&sem->lock); schedule(); spin_lock_irq(&sem->lock); diff -u --recursive --new-file v2.4.0-test10/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c --- v2.4.0-test10/linux/arch/ppc/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/ppc/mm/init.c Wed Nov 8 19:01:34 2000 @@ -630,7 +630,7 @@ void flush_page_to_ram(struct page *page) { - unsigned long vaddr = kmap(page); + unsigned long vaddr = (unsigned long) kmap(page); __flush_page_to_ram(vaddr); kunmap(page); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/s390/config.in linux/arch/s390/config.in --- v2.4.0-test10/linux/arch/s390/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/s390/config.in Thu Nov 16 12:51:28 2000 @@ -3,6 +3,9 @@ # see Documentation/kbuild/config-language.txt. # +define_bool CONFIG_ISA n +define_bool CONFIG_EISA n +define_bool CONFIG_MCA n define_bool CONFIG_UID16 y mainmenu_name "Linux Kernel Configuration" diff -u --recursive --new-file v2.4.0-test10/linux/arch/s390/kernel/semaphore.c linux/arch/s390/kernel/semaphore.c --- v2.4.0-test10/linux/arch/s390/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/s390/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -55,7 +55,7 @@ { struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -75,7 +75,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_UNINTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_UNINTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -89,7 +89,7 @@ int retval = 0; struct task_struct *tsk = current; DECLARE_WAITQUEUE(wait, tsk); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; add_wait_queue_exclusive(&sem->wait, &wait); spin_lock_irq(&semaphore_lock); @@ -125,7 +125,7 @@ spin_unlock_irq(&semaphore_lock); schedule(); - tsk->state = TASK_INTERRUPTIBLE|TASK_EXCLUSIVE; + tsk->state = TASK_INTERRUPTIBLE; spin_lock_irq(&semaphore_lock); } spin_unlock_irq(&semaphore_lock); @@ -188,7 +188,7 @@ for (;;) { if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!sem->write_bias_granted) schedule(); } @@ -240,7 +240,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/sh/config.in linux/arch/sh/config.in --- v2.4.0-test10/linux/arch/sh/config.in Sun Oct 8 10:50:11 2000 +++ linux/arch/sh/config.in Thu Nov 16 12:51:28 2000 @@ -66,6 +66,8 @@ comment 'General setup' define_bool CONFIG_ISA n +define_bool CONFIG_EISA n +define_bool CONFIG_MCA n define_bool CONFIG_SBUS n bool 'Networking support' CONFIG_NET diff -u --recursive --new-file v2.4.0-test10/linux/arch/sh/kernel/semaphore.c linux/arch/sh/kernel/semaphore.c --- v2.4.0-test10/linux/arch/sh/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sh/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -195,7 +195,7 @@ for (;;) { if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!sem->write_bias_granted) schedule(); } @@ -251,7 +251,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (atomic_read(&sem->count) < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (atomic_read(&sem->count) >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/config.in linux/arch/sparc/config.in --- v2.4.0-test10/linux/arch/sparc/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/config.in Thu Nov 16 12:51:28 2000 @@ -1,4 +1,4 @@ -# $Id: config.in,v 1.104 2000/10/04 09:01:38 anton Exp $ +# $Id: config.in,v 1.105 2000/11/12 10:01:41 davem Exp $ # For a description of the syntax of this configuration file, # see Documentation/kbuild/config-language.txt. # @@ -31,6 +31,8 @@ # Global things across all Sun machines. define_bool CONFIG_ISA n +define_bool CONFIG_EISA n +define_bool CONFIG_MCA n define_bool CONFIG_PCMCIA n define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c --- v2.4.0-test10/linux/arch/sparc/kernel/ebus.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/kernel/ebus.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.11 2000/10/10 01:07:38 davem Exp $ +/* $Id: ebus.c,v 1.15 2000/11/08 05:06:21 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -24,18 +24,9 @@ struct linux_ebus *ebus_chain = 0; -#ifdef CONFIG_SUN_OPENPROMIO -extern int openprom_init(void); -#endif #ifdef CONFIG_SUN_AUXIO extern void auxio_probe(void); #endif -#ifdef CONFIG_OBP_FLASH -extern int flash_init(void); -#endif -#ifdef CONFIG_ENVCTRL -extern int envctrl_init(void); -#endif /* We are together with pcic.c under CONFIG_PCI. */ extern unsigned int pcic_pin_to_irq(unsigned int, char *name); @@ -367,20 +358,7 @@ ++num_ebus; } -#ifdef CONFIG_SUN_OPENPROMIO - openprom_init(); -#endif - -#ifdef CONFIG_SUN_BPP - bpp_init(); -#endif #ifdef CONFIG_SUN_AUXIO auxio_probe(); -#endif -#ifdef CONFIG_ENVCTRL - envctrl_init(); -#endif -#ifdef CONFIG_OBP_FLASH - flash_init(); #endif } diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c --- v2.4.0-test10/linux/arch/sparc/kernel/pcic.c Sun Oct 8 10:50:11 2000 +++ linux/arch/sparc/kernel/pcic.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: pcic.c,v 1.18 2000/09/25 06:09:12 anton Exp $ +/* $Id: pcic.c,v 1.19 2000/11/08 04:49:17 davem Exp $ * pcic.c: Sparc/PCI controller support * * Copyright (C) 1998 V. Roganov and G. Raiko @@ -865,23 +865,6 @@ struct resource *res2, int index) { } - -#if 0 -void pcibios_update_irq(struct pci_dev *pdev, int irq) -{ -} - -unsigned long resource_fixup(struct pci_dev *pdev, struct resource *res, - unsigned long start, unsigned long size) -{ - return start; -} - -void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, - struct pbus_set_ranges_data *pranges) -{ -} -#endif void pcibios_align_resource(void *data, struct resource *res, unsigned long size) { diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/kernel/semaphore.c linux/arch/sparc/kernel/semaphore.c --- v2.4.0-test10/linux/arch/sparc/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -1,4 +1,4 @@ -/* $Id: semaphore.c,v 1.3 2000/10/14 10:09:00 davem Exp $ +/* $Id: semaphore.c,v 1.4 2000/11/10 04:02:03 davem Exp $ * Generic semaphore code. Buyer beware. Do your own * specific changes in */ @@ -166,7 +166,7 @@ for (;;) { if (!ldstub(&sem->write_not_granted)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (sem->write_not_granted) schedule(); } @@ -216,7 +216,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (sem->count < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (sem->count >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c --- v2.4.0-test10/linux/arch/sparc/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/mm/init.c Sun Nov 12 20:37:16 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.94 2000/10/19 00:49:51 davem Exp $ +/* $Id: init.c,v 1.95 2000/11/10 04:49:56 davem Exp $ * linux/arch/sparc/mm/init.c * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -579,8 +579,7 @@ void flush_page_to_ram(struct page *page) { - unsigned long vaddr; - vaddr = kmap(page); - __flush_page_to_ram((unsigned long)page_address(page)); + unsigned long vaddr = (unsigned long) kmap(page); + __flush_page_to_ram(vaddr); kunmap(page); } diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c --- v2.4.0-test10/linux/arch/sparc/mm/srmmu.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/mm/srmmu.c Thu Nov 9 17:17:01 2000 @@ -1,4 +1,4 @@ -/* $Id: srmmu.c,v 1.223 2000/10/16 14:32:49 anton Exp $ +/* $Id: srmmu.c,v 1.224 2000/11/09 22:40:05 davem Exp $ * srmmu.c: SRMMU specific routines for memory management. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -1163,7 +1163,7 @@ void (*poke_srmmu)(void) __initdata = NULL; -extern unsigned long bootmem_init(void); +extern void bootmem_init(void); extern void sun_serial_setup(void); void __init srmmu_paging_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c --- v2.4.0-test10/linux/arch/sparc/mm/sun4c.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc/mm/sun4c.c Thu Nov 9 17:17:01 2000 @@ -1,4 +1,4 @@ -/* $Id: sun4c.c,v 1.200 2000/10/16 14:32:49 anton Exp $ +/* $Id: sun4c.c,v 1.201 2000/11/09 22:39:36 davem Exp $ * sun4c.c: Doing in software what should be done in hardware. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -2509,7 +2509,7 @@ extern void sparc_context_init(int); extern unsigned long end; -extern unsigned long bootmem_init(void); +extern void bootmem_init(void); extern unsigned long last_valid_pfn; extern void sun_serial_setup(void); @@ -2524,7 +2524,8 @@ kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4); kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end); - last_valid_pfn = end_pfn = bootmem_init(); + bootmem_init(); + end_pfn = last_valid_pfn; /* This does not logically belong here, but we need to * call it at the moment we are able to use the bootmem diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds --- v2.4.0-test10/linux/arch/sparc/vmlinux.lds Wed Jul 5 22:15:24 2000 +++ linux/arch/sparc/vmlinux.lds Thu Nov 9 15:57:41 2000 @@ -31,6 +31,9 @@ __start___ksymtab = .; __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; . = ALIGN(4096); __init_begin = .; diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/config.in linux/arch/sparc64/config.in --- v2.4.0-test10/linux/arch/sparc64/config.in Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/config.in Thu Nov 16 12:51:28 2000 @@ -29,6 +29,8 @@ # Global things across all Sun machines. define_bool CONFIG_HAVE_DEC_LOCK y define_bool CONFIG_ISA n +define_bool CONFIG_EISA n +define_bool CONFIG_MCA n define_bool CONFIG_PCMCIA n define_bool CONFIG_SBUS y define_bool CONFIG_SBUSCHAR y diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/dtlb_base.S linux/arch/sparc64/kernel/dtlb_base.S --- v2.4.0-test10/linux/arch/sparc64/kernel/dtlb_base.S Mon Mar 27 10:35:56 2000 +++ linux/arch/sparc64/kernel/dtlb_base.S Sun Nov 12 20:37:16 2000 @@ -1,4 +1,4 @@ -/* $Id: dtlb_base.S,v 1.7 2000/03/26 09:13:48 davem Exp $ +/* $Id: dtlb_base.S,v 1.8 2000/11/10 08:28:45 davem Exp $ * dtlb_base.S: Front end to DTLB miss replacement strategy. * This is included directly into the trap table. * @@ -57,7 +57,7 @@ srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset ldxa [%g3 + %g6] ASI_S, %g5 ! Load VPTE 1: brlz,pt %g5, 9f ! Valid, load into TLB - and %g5, (_PAGE_PRESENT|_PAGE_READ), %g4 ! Mask readable bits + nop ! Delay-slot ba,a,pt %xcc, 4f ! Invalid, branch out /* DTLB ** ICACHE line 2: Quick kernel TLB misses */ @@ -68,27 +68,27 @@ nop 9: stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Reload TLB retry ! Trap return - nop +4: rdpr %pstate, %g5 ! Move into alternate globals /* DTLB ** ICACHE line 3: winfixups+real_faults */ -4: cmp %g4, (_PAGE_PRESENT|_PAGE_READ) ! Readable page? - be,pn %xcc, 5f ! Yep, refbit update - sllx %g1, 60, %g4 ! Get valid bit - rdpr %pstate, %g5 ! Move into alternate globals wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate rdpr %tl, %g4 ! See where we came from. cmp %g4, 1 ! Is etrap/rtrap window fault? mov TLB_TAG_ACCESS, %g4 ! Prepare for fault processing - -/* DTLB ** ICACHE line 4: padding */ ldxa [%g4] ASI_DMMU, %g5 ! Load faulting VA page be,pt %xcc, sparc64_realfault_common ! Jump to normal fault handling mov FAULT_CODE_DTLB, %g4 ! It was read from DTLB ba,a,pt %xcc, winfix_trampoline ! Call window fixup code -5: or %g5, _PAGE_ACCESSED, %g5 ! Indicate reference - or %g5, %g4, %g5 ! Set valid - stxa %g5, [%g3 + %g6] ASI_S ! Update PTE table (cant trap) - ba,a,pt %xcc, 9b ! Complete tlb miss + +/* DTLB ** ICACHE line 4: Unused... */ + nop + nop + nop + nop + nop + nop + nop + nop #undef TAG_CONTEXT_BITS #undef VPTE_SHIFT diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/dtlb_prot.S linux/arch/sparc64/kernel/dtlb_prot.S --- v2.4.0-test10/linux/arch/sparc64/kernel/dtlb_prot.S Mon Mar 27 10:35:56 2000 +++ linux/arch/sparc64/kernel/dtlb_prot.S Sun Nov 12 20:37:16 2000 @@ -1,4 +1,4 @@ -/* $Id: dtlb_prot.S,v 1.20 2000/03/26 09:13:48 davem Exp $ +/* $Id: dtlb_prot.S,v 1.21 2000/11/10 08:28:45 davem Exp $ * dtlb_prot.S: DTLB protection trap strategy. * This is included directly into the trap table. * @@ -6,10 +6,6 @@ * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz) */ -#define TAG_CONTEXT_BITS 0x3ff -#define VPTE_SHIFT (PAGE_SHIFT - 3) -#define MODIFIED_BITS (_PAGE_WRITE | _PAGE_W | _PAGE_MODIFIED | _PAGE_ACCESSED) - /* Ways we can get here: * * [TL == 0] 1) User stores to readonly pages. @@ -18,45 +14,41 @@ */ /* PROT ** ICACHE line 1: User DTLB protection trap */ - ldxa [%g1] ASI_DMMU, %g6 ! Primary or Secondary ctx? - and %g6, 0x10, %g6 ! Get pri/sec ctx bit stxa %g0, [%g1] ASI_DMMU ! Clear SFSR FaultValid bit membar #Sync ! Synchronize ASI stores - ldxa [%g1 + %g1] ASI_DMMU, %g4 ! Load TAG_ACCESS - andn %g4, TAG_CONTEXT_BITS, %g4 ! Clear CTX bits - stxa %g0, [%g4 + %g6] ASI_DMMU_DEMAP ! Perform TLB flush of page - membar #Sync ! Synchronize ASI stores - -/* PROT ** ICACHE line 2: Further normal processing */ - srax %g4, VPTE_SHIFT, %g6 ! Compute VPTE offset - ldxa [%g3 + %g6] ASI_S, %g5 ! Load PTE entry - andcc %g5, _PAGE_WRITE, %g0 ! Writable page? - be,pt %xcc, 1f ! Nope, real fault - or %g5, (MODIFIED_BITS), %g5 ! Mark as writable/modified - stxa %g5, [%g3 + %g6] ASI_S ! Update PTE entry - stxa %g5, [%g0] ASI_DTLB_DATA_IN ! Load PTE into TLB - retry ! Trap return - -/* PROT ** ICACHE line 3: Real user faults */ -1: rdpr %pstate, %g5 ! Move into alternate globals + rdpr %pstate, %g5 ! Move into alternate globals wrpr %g5, PSTATE_AG|PSTATE_MG, %pstate rdpr %tl, %g1 ! Need to do a winfixup? cmp %g1, 1 ! Trap level >1? mov TLB_TAG_ACCESS, %g4 ! Prepare reload of vaddr + nop + +/* PROT ** ICACHE line 2: More real fault processing */ bgu,pn %xcc, winfix_trampoline ! Yes, perform winfixup ldxa [%g4] ASI_DMMU, %g5 ! Put tagaccess in %g5 ba,pt %xcc, sparc64_realfault_common ! Nope, normal fault - -/* PROT ** ICACHE line 4: More real fault processing */ mov FAULT_CODE_DTLB | FAULT_CODE_WRITE, %g4 nop nop nop nop + +/* PROT ** ICACHE line 3: Unused... */ + nop + nop + nop + nop + nop nop nop nop -#undef TAG_CONTEXT_BITS -#undef VPTE_SHIFT -#undef MODIFIED_BITS +/* PROT ** ICACHE line 3: Unused... */ + nop + nop + nop + nop + nop + nop + nop + nop diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c --- v2.4.0-test10/linux/arch/sparc64/kernel/ebus.c Fri Aug 4 18:16:11 2000 +++ linux/arch/sparc64/kernel/ebus.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: ebus.c,v 1.48 2000/08/02 06:22:35 davem Exp $ +/* $Id: ebus.c,v 1.53 2000/11/08 05:08:23 davem Exp $ * ebus.c: PCI to EBus bridge device. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -22,21 +22,9 @@ struct linux_ebus *ebus_chain = 0; -#ifdef CONFIG_SUN_OPENPROMIO -extern int openprom_init(void); -#endif #ifdef CONFIG_SUN_AUXIO extern void auxio_probe(void); #endif -#ifdef CONFIG_OBP_FLASH -extern int flash_init(void); -#endif -#ifdef CONFIG_ENVCTRL -extern int envctrl_init(void); -#endif -#ifdef CONFIG_DISPLAY7SEG -extern int d7s_init(void); -#endif static inline void *ebus_alloc(size_t size) { @@ -372,23 +360,8 @@ ++num_ebus; } -#ifdef CONFIG_SUN_OPENPROMIO - openprom_init(); -#endif -#ifdef CONFIG_SUN_BPP - bpp_init(); -#endif #ifdef CONFIG_SUN_AUXIO auxio_probe(); -#endif -#ifdef CONFIG_ENVCTRL - envctrl_init(); -#endif -#ifdef CONFIG_OBP_FLASH - flash_init(); -#endif -#ifdef CONFIG_DISPLAY7SEG - d7s_init(); #endif clock_probe(); power_init(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c --- v2.4.0-test10/linux/arch/sparc64/kernel/ioctl32.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/kernel/ioctl32.c Sat Nov 11 19:02:40 2000 @@ -1,4 +1,4 @@ -/* $Id: ioctl32.c,v 1.99 2000/10/17 16:20:33 davem Exp $ +/* $Id: ioctl32.c,v 1.103 2000/11/10 05:44:33 davem Exp $ * ioctl32.c: Conversion between 32bit and 64bit native ioctls. * * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com) @@ -71,8 +71,9 @@ #include #include #include -#include +#include #include +#include #include #include @@ -3230,6 +3231,7 @@ COMPATIBLE_IOCTL(ENVCTRL_RD_ETHERNET_TEMPERATURE) COMPATIBLE_IOCTL(ENVCTRL_RD_MTHRBD_TEMPERATURE) COMPATIBLE_IOCTL(ENVCTRL_RD_CPU_VOLTAGE) +COMPATIBLE_IOCTL(ENVCTRL_RD_GLOBALADDRESS) /* COMPATIBLE_IOCTL(D7SIOCRD) same value as ENVCTRL_RD_VOLTAGE_STATUS */ COMPATIBLE_IOCTL(D7SIOCWR) COMPATIBLE_IOCTL(D7SIOCTM) @@ -3467,6 +3469,14 @@ COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1) COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2) COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO)) +COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR)) COMPATIBLE_IOCTL(SOUND_MIXER_READ_MUTE) /* SOUND_MIXER_READ_ENHANCE, same value as READ_MUTE */ /* SOUND_MIXER_READ_LOUD, same value as READ_MUTE */ @@ -3492,6 +3502,14 @@ COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1) COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2) COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO)) +COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR)) COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE) /* SOUND_MIXER_WRITE_ENHANCE, same value as WRITE_MUTE */ /* SOUND_MIXER_WRITE_LOUD, same value as WRITE_MUTE */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/itlb_base.S linux/arch/sparc64/kernel/itlb_base.S --- v2.4.0-test10/linux/arch/sparc64/kernel/itlb_base.S Mon Mar 27 10:35:56 2000 +++ linux/arch/sparc64/kernel/itlb_base.S Sun Nov 12 20:37:16 2000 @@ -1,4 +1,4 @@ -/* $Id: itlb_base.S,v 1.9 2000/03/26 09:13:48 davem Exp $ +/* $Id: itlb_base.S,v 1.10 2000/11/10 08:28:45 davem Exp $ * itlb_base.S: Front end to ITLB miss replacement strategy. * This is included directly into the trap table. * @@ -23,22 +23,13 @@ srax %g4, VPTE_SHIFT, %g6 ! Create VPTE offset ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE 1: brgez,pn %g5, 3f ! Not valid, branch out - and %g5, (_PAGE_PRESENT|_PAGE_READ), %g4 ! Mask readable bits + nop ! Delay-slot 2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB retry ! Trap return -3: cmp %g4, (_PAGE_PRESENT|_PAGE_READ) ! Readable page? +3: rdpr %pstate, %g4 ! Move into alternate globals -/* ITLB ** ICACHE line 2: Quick user ref updates */ - bne,pn %xcc, 4f ! Nope, real missing page - sllx %g1, 60, %g4 ! Sliiickkk... - or %g5, _PAGE_ACCESSED, %g5 ! Mark as touched - or %g5, %g4, %g5 ! Allow user to see it - ba,pt %xcc, 2b ! Branch to load TLB - stxa %g5, [%g3 + %g6] ASI_S ! Update PTE table -4: rdpr %pstate, %g4 ! Move into alternate globals +/* ITLB ** ICACHE line 2: Real faults */ wrpr %g4, PSTATE_AG|PSTATE_MG, %pstate - -/* ITLB ** ICACHE line 3: Real faults */ rdpr %tpc, %g5 ! And load faulting VA mov FAULT_CODE_ITLB, %g4 ! It was read from ITLB sparc64_realfault_common: ! Called by TL0 dtlb_miss too @@ -46,10 +37,11 @@ stx %g5, [%g6 + AOFF_task_thread + AOFF_thread_fault_address] ba,pt %xcc, etrap ! Save state 1: rd %pc, %g7 ! ... + nop + +/* ITLB ** ICACHE line 3: Finish faults + window fixups */ call do_sparc64_fault ! Call fault handler add %sp, STACK_BIAS + REGWIN_SZ, %o0! Compute pt_regs arg - -/* ITLB ** ICACHE line 4: Finish faults + window fixups */ ba,pt %xcc, rtrap_clr_l6 ! Restore cpu state nop winfix_trampoline: @@ -57,6 +49,14 @@ or %g3, 0x7c, %g3 ! Compute offset to branch wrpr %g3, %tnpc ! Write it into TNPC done ! Do it to it + +/* ITLB ** ICACHE line 4: Unused... */ + nop + nop + nop + nop + nop + nop nop nop diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c --- v2.4.0-test10/linux/arch/sparc64/kernel/pci.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/kernel/pci.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: pci.c,v 1.18 2000/10/03 11:31:42 anton Exp $ +/* $Id: pci.c,v 1.19 2000/11/08 04:49:17 davem Exp $ * pci.c: UltraSparc PCI controller support. * * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com) @@ -200,12 +200,6 @@ void pcibios_update_irq(struct pci_dev *pdev, int irq) { -} - -unsigned long resource_fixup(struct pci_dev *pdev, struct resource *res, - unsigned long start, unsigned long size) -{ - return start; } void pcibios_fixup_pbus_ranges(struct pci_bus *pbus, diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c --- v2.4.0-test10/linux/arch/sparc64/kernel/process.c Thu Sep 7 08:32:00 2000 +++ linux/arch/sparc64/kernel/process.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.112 2000/09/06 00:45:01 davem Exp $ +/* $Id: process.c,v 1.113 2000/11/08 08:14:58 davem Exp $ * arch/sparc64/kernel/process.c * * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) @@ -647,14 +647,21 @@ { long retval; - __asm__ __volatile("mov %1, %%g1\n\t" + /* If the parent runs before fn(arg) is called by the child, + * the input registers of this function can be clobbered. + * So we stash 'fn' and 'arg' into global registers which + * will not be modified by the parent. + */ + __asm__ __volatile("mov %4, %%g2\n\t" /* Save FN into global */ + "mov %5, %%g3\n\t" /* Save ARG into global */ + "mov %1, %%g1\n\t" /* Clone syscall nr. */ "mov %2, %%o0\n\t" /* Clone flags. */ "mov 0, %%o1\n\t" /* usp arg == 0 */ "t 0x6d\n\t" /* Linux/Sparc clone(). */ "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */ " mov %%o0, %0\n\t" - "jmpl %4, %%o7\n\t" /* Call the function. */ - " mov %5, %%o0\n\t" /* Set arg in delay. */ + "jmpl %%g2, %%o7\n\t" /* Call the function. */ + " mov %%g3, %%o0\n\t" /* Set arg in delay. */ "mov %3, %%g1\n\t" "t 0x6d\n\t" /* Linux/Sparc exit(). */ /* Notreached by child. */ @@ -662,7 +669,7 @@ "=r" (retval) : "i" (__NR_clone), "r" (flags | CLONE_VM), "i" (__NR_exit), "r" (fn), "r" (arg) : - "g1", "o0", "o1", "memory", "cc"); + "g1", "g2", "g3", "o0", "o1", "memory", "cc"); return retval; } diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/semaphore.c linux/arch/sparc64/kernel/semaphore.c --- v2.4.0-test10/linux/arch/sparc64/kernel/semaphore.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/kernel/semaphore.c Sat Nov 11 19:02:40 2000 @@ -1,4 +1,4 @@ -/* $Id: semaphore.c,v 1.4 2000/10/14 10:09:00 davem Exp $ +/* $Id: semaphore.c,v 1.5 2000/11/10 04:02:03 davem Exp $ * Generic semaphore code. Buyer beware. Do your own * specific changes in */ @@ -223,7 +223,7 @@ for (;;) { if (test_and_clear_le_bit(1, &sem->granted)) break; - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (!test_le_bit(1, &sem->granted)) schedule(); } @@ -273,7 +273,7 @@ add_wait_queue_exclusive(&sem->wait, &wait); while (sem->count < 0) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + set_task_state(tsk, TASK_UNINTERRUPTIBLE); if (sem->count >= 0) break; /* we must attempt to acquire or bias the lock */ schedule(); diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c --- v2.4.0-test10/linux/arch/sparc64/kernel/sparc64_ksyms.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/kernel/sparc64_ksyms.c Fri Nov 17 16:48:51 2000 @@ -1,4 +1,4 @@ -/* $Id: sparc64_ksyms.c,v 1.95 2000/10/30 21:01:40 davem Exp $ +/* $Id: sparc64_ksyms.c,v 1.98 2000/11/13 10:03:32 davem Exp $ * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support. * * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) @@ -87,7 +87,6 @@ extern int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *)); extern int unregister_ioctl32_conversion(unsigned int cmd); extern int io_remap_page_range(unsigned long from, unsigned long offset, unsigned long size, pgprot_t prot, int space); -extern void __flush_dcache_page(void *addr); extern int __ashrdi3(int, int); @@ -110,25 +109,14 @@ extern unsigned long phys_base; -/* One thing to note is that the way the symbols of the mul/div - * support routines are named is a mess, they all start with - * a '.' which makes it a bitch to export, here is the trick: - */ - -#define EXPORT_SYMBOL_PRIVATE(sym) \ -extern int __sparc_priv_ ## sym (int) __asm__("__" #sym); \ -const struct module_symbol __export_priv_##sym \ -__attribute__((section("__ksymtab"))) = \ -{ (unsigned long) &__sparc_priv_ ## sym, "__" #sym } - /* used by various drivers */ #ifdef CONFIG_SMP #ifndef SPIN_LOCK_DEBUG /* Out of line rw-locking implementation. */ -EXPORT_SYMBOL_PRIVATE(read_lock); -EXPORT_SYMBOL_PRIVATE(read_unlock); -EXPORT_SYMBOL_PRIVATE(write_lock); -EXPORT_SYMBOL_PRIVATE(write_unlock); +EXPORT_SYMBOL(__read_lock); +EXPORT_SYMBOL(__read_unlock); +EXPORT_SYMBOL(__write_lock); +EXPORT_SYMBOL(__write_unlock); #endif /* Kernel wide locking */ @@ -137,10 +125,10 @@ /* Hard IRQ locking */ EXPORT_SYMBOL(global_irq_holder); EXPORT_SYMBOL(synchronize_irq); -EXPORT_SYMBOL_PRIVATE(global_cli); -EXPORT_SYMBOL_PRIVATE(global_sti); -EXPORT_SYMBOL_PRIVATE(global_save_flags); -EXPORT_SYMBOL_PRIVATE(global_restore_flags); +EXPORT_SYMBOL(__global_cli); +EXPORT_SYMBOL(__global_sti); +EXPORT_SYMBOL(__global_save_flags); +EXPORT_SYMBOL(__global_restore_flags); /* Per-CPU information table */ EXPORT_SYMBOL(cpu_data); @@ -163,27 +151,33 @@ #endif +/* semaphores */ +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); +EXPORT_SYMBOL(__up); + /* rw semaphores */ EXPORT_SYMBOL_NOVERS(__down_read_failed); EXPORT_SYMBOL_NOVERS(__down_write_failed); EXPORT_SYMBOL_NOVERS(__rwsem_wake); /* Atomic counter implementation. */ -EXPORT_SYMBOL_PRIVATE(atomic_add); -EXPORT_SYMBOL_PRIVATE(atomic_sub); +EXPORT_SYMBOL(__atomic_add); +EXPORT_SYMBOL(__atomic_sub); /* Atomic bit operations. */ -EXPORT_SYMBOL_PRIVATE(test_and_set_bit); -EXPORT_SYMBOL_PRIVATE(test_and_clear_bit); -EXPORT_SYMBOL_PRIVATE(test_and_change_bit); -EXPORT_SYMBOL_PRIVATE(test_and_set_le_bit); -EXPORT_SYMBOL_PRIVATE(test_and_clear_le_bit); +EXPORT_SYMBOL(__test_and_set_bit); +EXPORT_SYMBOL(__test_and_clear_bit); +EXPORT_SYMBOL(__test_and_change_bit); +EXPORT_SYMBOL(__test_and_set_le_bit); +EXPORT_SYMBOL(__test_and_clear_le_bit); EXPORT_SYMBOL(ivector_table); EXPORT_SYMBOL(enable_irq); EXPORT_SYMBOL(disable_irq); -EXPORT_SYMBOL_PRIVATE(flushw_user); +EXPORT_SYMBOL(__flushw_user); EXPORT_SYMBOL(__flush_dcache_page); diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c --- v2.4.0-test10/linux/arch/sparc64/kernel/sys_sparc32.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/kernel/sys_sparc32.c Sun Nov 12 20:37:16 2000 @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.165 2000/10/10 04:47:31 davem Exp $ +/* $Id: sys_sparc32.c,v 1.166 2000/11/10 04:49:56 davem Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -2952,7 +2952,7 @@ return -ENOMEM; new = 1; } - kaddr = (char *)kmap(page); + kaddr = kmap(page); if (new && offset) memset(kaddr, 0, offset); @@ -2967,7 +2967,7 @@ err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy); flush_page_to_ram(page); - kunmap((unsigned long)kaddr); + kunmap(page); if (err) return -EFAULT; diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c --- v2.4.0-test10/linux/arch/sparc64/kernel/sys_sunos32.c Sat Aug 12 12:08:49 2000 +++ linux/arch/sparc64/kernel/sys_sunos32.c Fri Nov 17 11:36:27 2000 @@ -601,7 +601,6 @@ int try_port; int ret; struct socket *socket; - struct dentry *dentry; struct inode *inode; struct file *file; @@ -609,8 +608,7 @@ if(!file) return 0; - dentry = file->f_dentry; - inode = dentry->d_inode; + inode = file->f_dentry->d_inode; socket = &inode->u.socket_i; local.sin_family = AF_INET; diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/lib/Makefile linux/arch/sparc64/lib/Makefile --- v2.4.0-test10/linux/arch/sparc64/lib/Makefile Tue Jul 11 11:07:55 2000 +++ linux/arch/sparc64/lib/Makefile Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.23 2000/07/10 20:57:34 davem Exp $ +# $Id: Makefile,v 1.24 2000/11/01 07:33:47 davem Exp $ # Makefile for Sparc64 library files.. # @@ -8,7 +8,8 @@ memscan.o strncpy_from_user.o strlen_user.o memcmp.o checksum.o \ VIScopy.o VISbzero.o VISmemset.o VIScsum.o VIScsumcopy.o \ VIScsumcopyusr.o VISsave.o atomic.o rwlock.o bitops.o \ - dec_and_lock.o + dec_and_lock.o U3memcpy.o U3copy_from_user.o U3copy_to_user.o \ + U3copy_in_user.o lib.a: $(OBJS) $(AR) rcs lib.a $(OBJS) diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/lib/U3copy_from_user.S linux/arch/sparc64/lib/U3copy_from_user.S --- v2.4.0-test10/linux/arch/sparc64/lib/U3copy_from_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/U3copy_from_user.S Thu Nov 9 15:57:41 2000 @@ -0,0 +1,500 @@ +/* $Id: U3copy_from_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $ + * U3memcpy.S: UltraSparc-III optimized copy from userspace. + * + * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + */ + +#ifdef __KERNEL__ +#include +#include +#undef SMALL_COPY_USES_FPU +#define EXNV(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + ba,pt %xcc, U3cfu_fixup; \ + a, b, %o1; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EX(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + ba,pt %xcc, U3cfu_fixup; \ + a, b, %o1; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EX2(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o1; \ + add %o1, %o4, %o1; \ + ba,pt %xcc, U3cfu_fixup; \ + add %o1, 0x1c0, %o1; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EX3(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o1; \ + sll %g3, 6, %g3; \ + add %o1, 0x80, %o1; \ + ba,pt %xcc, U3cfu_fixup; \ + add %o1, %g3, %o1; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EX4(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o1; \ + add %o1, 0x40, %o1; \ + ba,pt %xcc, U3cfu_fixup; \ + add %o1, %g3, %o1; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#else +#define ASI_BLK_P 0xf0 +#define FPRS_FEF 0x04 +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#define SMALL_COPY_USES_FPU +#define EXNV(x,y,a,b) x,y; +#define EX(x,y,a,b) x,y; +#define EX2(x,y) x,y; +#define EX3(x,y) x,y; +#define EX4(x,y) x,y; +#endif + + /* Special/non-trivial issues of this code: + * + * 1) %o5 is preserved from VISEntryHalf to VISExitHalf + * 2) Only low 32 FPU registers are used so that only the + * lower half of the FPU register set is dirtied by this + * code. This is especially important in the kernel. + * 3) This code never prefetches cachelines past the end + * of the source buffer. + */ + + .text + .align 32 + + /* The cheetah's flexible spine, oversized liver, enlarged heart, + * slender muscular body, and claws make it the swiftest hunter + * in Africa and the fastest animal on land. Can reach speeds + * of up to 2.4GB per second. + */ + + .globl U3copy_from_user +U3copy_from_user: /* %o0=dst, %o1=src, %o2=len */ +#ifndef __KERNEL__ + /* Save away original 'dst' for memcpy return value. */ + mov %o0, %g3 ! A0 Group +#endif + /* Anything to copy at all? */ + cmp %o2, 0 ! A1 + ble,pn %icc, U3copy_from_user_short_ret! BR + + /* Extremely small copy? */ + cmp %o2, 31 ! A0 Group + ble,pn %icc, U3copy_from_user_short ! BR + + /* Large enough to use unrolled prefetch loops? */ + cmp %o2, 0x100 ! A1 + bge,a,pt %icc, U3copy_from_user_enter ! BR Group + andcc %o0, 0x3f, %g2 ! A0 + + ba,pt %xcc, U3copy_from_user_toosmall ! BR Group + andcc %o0, 0x7, %g2 ! A0 + + .align 32 +U3copy_from_user_short: + /* Copy %o2 bytes from src to dst, one byte at a time. */ + EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS Group + add %o1, 0x1, %o1 ! A0 + add %o0, 0x1, %o0 ! A1 + subcc %o2, 1, %o2 ! A0 Group + + bg,pt %icc, U3copy_from_user_short ! BR + stb %o3, [%o0 + -1] ! MS Group (1-cycle stall) + +U3copy_from_user_short_ret: +#ifdef __KERNEL__ + retl ! BR Group (0-4 cycle stall) + clr %o0 ! A0 +#else + retl ! BR Group (0-4 cycle stall) + mov %g3, %o0 ! A0 +#endif + + /* Here len >= (6 * 64) and condition codes reflect execution + * of "andcc %o0, 0x7, %g2", done by caller. + */ + .align 64 +U3copy_from_user_enter: + /* Is 'dst' already aligned on an 64-byte boundary? */ + be,pt %xcc, 2f ! BR + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x40, %g2 ! A0 Group + sub %g0, %g2, %g2 ! A0 Group + sub %o2, %g2, %o2 ! A0 Group + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + stb %o3, [%o0 + -1] ! MS Group + +2: VISEntryHalf ! MS+MS + and %o1, 0x7, %g1 ! A1 + ba,pt %xcc, U3copy_from_user_begin ! BR + alignaddr %o1, %g0, %o1 ! MS (Break-after) + + .align 64 +U3copy_from_user_begin: + prefetcha [%o1 + 0x000] %asi, #one_read ! MS Group1 + prefetcha [%o1 + 0x040] %asi, #one_read ! MS Group2 + andn %o2, (0x40 - 1), %o4 ! A0 + prefetcha [%o1 + 0x080] %asi, #one_read ! MS Group3 + cmp %o4, 0x140 ! A0 + prefetcha [%o1 + 0x0c0] %asi, #one_read ! MS Group4 + EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0) ! MS Group5 (%f0 results at G8) + bge,a,pt %icc, 1f ! BR + + prefetcha [%o1 + 0x100] %asi, #one_read ! MS Group6 +1: EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0) ! AX (%f2 results at G9) + cmp %o4, 0x180 ! A1 + bge,a,pt %icc, 1f ! BR + prefetcha [%o1 + 0x140] %asi, #one_read ! MS Group7 +1: EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0) ! AX (%f4 results at G10) + cmp %o4, 0x1c0 ! A1 + bge,a,pt %icc, 1f ! BR + + prefetcha [%o1 + 0x180] %asi, #one_read ! MS Group8 +1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) + EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0) ! AX (%f6 results at G12) + faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) + EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0) ! MS (%f8 results at G13) + faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) + EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS (%f10 results at G15) + faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) + + EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS (%f12 results at G16) + faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) + EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS (%f14 results at G18) + faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) + EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0) ! MS (%f0 results at G19) + + /* We only use the first loop if len > (7 * 64). */ + subcc %o4, 0x1c0, %o4 ! A0 Group17 + bg,pt %icc, U3copy_from_user_loop1 ! BR + add %o1, 0x40, %o1 ! A1 + + add %o4, 0x140, %o4 ! A0 Group18 + ba,pt %xcc, U3copy_from_user_loop2 ! BR + srl %o4, 6, %o3 ! A0 Group19 + nop + nop + nop + nop + nop + + nop + nop + + /* This loop performs the copy and queues new prefetches. + * We drop into the second loop when len <= (5 * 64). Note + * that this (5 * 64) factor has been subtracted from len + * already. + */ +U3copy_from_user_loop1: + EX2(ldda [%o1 + 0x008] %asi, %f2) ! MS Group2 (%f2 results at G5) + faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) + EX2(ldda [%o1 + 0x010] %asi, %f4) ! MS Group3 (%f4 results at G6) + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) + stda %f16, [%o0] ASI_BLK_P ! MS + EX2(ldda [%o1 + 0x018] %asi, %f6) ! AX (%f6 results at G7) + + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + EX2(ldda [%o1 + 0x020] %asi, %f8) ! MS (%f8 results at G15) + faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) + EX2(ldda [%o1 + 0x028] %asi, %f10) ! MS (%f10 results at G16) + faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) + EX2(ldda [%o1 + 0x030] %asi, %f12) ! MS (%f12 results at G17) + faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) + EX2(ldda [%o1 + 0x038] %asi, %f14) ! MS (%f14 results at G18) + + faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) + EX2(ldda [%o1 + 0x040] %asi, %f0) ! AX (%f0 results at G19) + prefetcha [%o1 + 0x180] %asi, #one_read ! MS + faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) + subcc %o4, 0x40, %o4 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3copy_from_user_loop1 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + +U3copy_from_user_loop2_enter: + mov 5, %o3 ! A1 + + /* This loop performs on the copy, no new prefetches are + * queued. We do things this way so that we do not perform + * any spurious prefetches past the end of the src buffer. + */ +U3copy_from_user_loop2: + EX3(ldda [%o1 + 0x008] %asi, %f2) ! MS + faligndata %f12, %f14, %f28 ! FGA Group2 + EX3(ldda [%o1 + 0x010] %asi, %f4) ! MS + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) + stda %f16, [%o0] ASI_BLK_P ! MS + EX3(ldda [%o1 + 0x018] %asi, %f6) ! AX + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + + EX3(ldda [%o1 + 0x020] %asi, %f8) ! MS + faligndata %f2, %f4, %f18 ! FGA Group13 + EX3(ldda [%o1 + 0x028] %asi, %f10) ! MS + faligndata %f4, %f6, %f20 ! FGA Group14 + EX3(ldda [%o1 + 0x030] %asi, %f12) ! MS + faligndata %f6, %f8, %f22 ! FGA Group15 + EX3(ldda [%o1 + 0x038] %asi, %f14) ! MS + faligndata %f8, %f10, %f24 ! FGA Group16 + + EX3(ldda [%o1 + 0x040] %asi, %f0) ! AX + faligndata %f10, %f12, %f26 ! FGA Group17 + subcc %o3, 0x01, %o3 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3copy_from_user_loop2 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + + /* Finally we copy the last full 64-byte block. */ +U3copy_from_user_loopfini: + EX3(ldda [%o1 + 0x008] %asi, %f2) ! MS + faligndata %f12, %f14, %f28 ! FGA + EX3(ldda [%o1 + 0x010] %asi, %f4) ! MS Group19 + faligndata %f14, %f0, %f30 ! FGA + stda %f16, [%o0] ASI_BLK_P ! MS Group20 + EX3(ldda [%o1 + 0x018] %asi, %f6) ! AX + faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) + EX3(ldda [%o1 + 0x020] %asi, %f8) ! MS + faligndata %f2, %f4, %f18 ! FGA Group12 + EX3(ldda [%o1 + 0x028] %asi, %f10) ! MS + faligndata %f4, %f6, %f20 ! FGA Group13 + EX3(ldda [%o1 + 0x030] %asi, %f12) ! MS + faligndata %f6, %f8, %f22 ! FGA Group14 + EX3(ldda [%o1 + 0x038] %asi, %f14) ! MS + faligndata %f8, %f10, %f24 ! FGA Group15 + cmp %g1, 0 ! A0 + be,pt %icc, 1f ! BR + add %o0, 0x40, %o0 ! A1 + EX4(ldda [%o1 + 0x040] %asi, %f0) ! MS +1: faligndata %f10, %f12, %f26 ! FGA Group16 + faligndata %f12, %f14, %f28 ! FGA Group17 + faligndata %f14, %f0, %f30 ! FGA Group18 + stda %f16, [%o0] ASI_BLK_P ! MS + add %o0, 0x40, %o0 ! A0 + add %o1, 0x40, %o1 ! A1 + membar #Sync ! MS Group26 (7-cycle stall) + + /* Now we copy the (len modulo 64) bytes at the end. + * Note how we borrow the %f0 loaded above. + * + * Also notice how this code is careful not to perform a + * load past the end of the src buffer just like similar + * code found in U3copy_from_user_toosmall processing. + */ +U3copy_from_user_loopend: + and %o2, 0x3f, %o2 ! A0 Group + andcc %o2, 0x38, %g2 ! A0 Group + be,pn %icc, U3copy_from_user_endcruft ! BR + subcc %g2, 0x8, %g2 ! A1 + be,pn %icc, U3copy_from_user_endcruft ! BR Group + cmp %g1, 0 ! A0 + + be,a,pt %icc, 1f ! BR Group + EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0) ! MS + +1: EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0) ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f0, %f2, %f8 ! FGA Group + std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) + be,pn %icc, U3copy_from_user_endcruft ! BR + add %o0, 0x8, %o0 ! A0 + EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0) ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA + std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A0 Group + + /* If anything is left, we copy it one byte at a time. + * Note that %g1 is (src & 0x3) saved above before the + * alignaddr was performed. + */ +U3copy_from_user_endcruft: + cmp %o2, 0 + add %o1, %g1, %o1 + VISExitHalf + be,pn %icc, U3copy_from_user_short_ret + nop + ba,a,pt %xcc, U3copy_from_user_short + + /* If we get here, then 32 <= len < (6 * 64) */ +U3copy_from_user_toosmall: + +#ifdef SMALL_COPY_USES_FPU + + /* Is 'dst' already aligned on an 8-byte boundary? */ + be,pt %xcc, 2f ! BR Group + + /* Compute abs((dst & 7) - 8) into %g2. This is the number + * of bytes to copy to make 'dst' 8-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x8, %g2 ! A0 + sub %g0, %g2, %g2 ! A0 Group (reg-dep) + sub %o2, %g2, %o2 ! A0 Group (reg-dep) + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) (%o3 in 3 cycles) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + stb %o3, [%o0 + -1] ! MS Group + +2: VISEntryHalf ! MS+MS + + /* Compute (len - (len % 8)) into %g2. This is guarenteed + * to be nonzero. + */ + andn %o2, 0x7, %g2 ! A0 Group + + /* You may read this and believe that it allows reading + * one 8-byte longword past the end of src. It actually + * does not, as %g2 is subtracted as loads are done from + * src, so we always stop before running off the end. + * Also, we are guarenteed to have at least 0x10 bytes + * to move here. + */ + sub %g2, 0x8, %g2 ! A0 Group (reg-dep) + alignaddr %o1, %g0, %g1 ! MS (Break-after) + EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group (1-cycle stall) + add %g1, 0x8, %g1 ! A0 + +1: EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0) ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + + faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) + std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + be,pn %icc, 2f ! BR + + add %o0, 0x8, %o0 ! A1 + EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) + std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A1 + + /* Nothing left to copy? */ +2: cmp %o2, 0 ! A0 Group + VISExitHalf ! A0+MS + be,pn %icc, U3copy_from_user_short_ret! BR Group + nop ! A0 + ba,a,pt %xcc, U3copy_from_user_short ! BR Group + +#else /* !(SMALL_COPY_USES_FPU) */ + + xor %o1, %o0, %g2 + andcc %g2, 0x7, %g0 + bne,pn %icc, U3copy_from_user_short + andcc %o1, 0x7, %g2 + + be,pt %xcc, 2f + sub %g2, 0x8, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + +1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2) + add %o1, 0x1, %o1 + add %o0, 0x1, %o0 + subcc %g2, 0x1, %g2 + bg,pt %icc, 1b + stb %o3, [%o0 + -1] + +2: andn %o2, 0x7, %g2 + sub %o2, %g2, %o2 + +3: EXNV(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2) + add %o1, 0x8, %o1 + add %o0, 0x8, %o0 + subcc %g2, 0x8, %g2 + bg,pt %icc, 3b + stx %o3, [%o0 + -8] + + cmp %o2, 0 + bne,pn %icc, U3copy_from_user_short + nop + ba,a,pt %xcc, U3copy_from_user_short_ret + +#endif /* !(SMALL_COPY_USES_FPU) */ + +#ifdef __KERNEL__ + .globl U3cfu_fixup +U3cfu_fixup: + /* Since this is copy_from_user(), zero out the rest of the + * kernel buffer. + */ + cmp %o1, 0 + ble,pn %icc, 2f + mov %o1, %g2 + +1: subcc %g2, 1, %g2 + stb %g0, [%o0] + bne,pt %icc, 1b + add %o0, 1, %o0 + +2: retl + mov %o1, %o0 +#endif diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/lib/U3copy_in_user.S linux/arch/sparc64/lib/U3copy_in_user.S --- v2.4.0-test10/linux/arch/sparc64/lib/U3copy_in_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/U3copy_in_user.S Thu Nov 9 15:57:41 2000 @@ -0,0 +1,531 @@ +/* $Id: U3copy_in_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $ + * U3memcpy.S: UltraSparc-III optimized copy within userspace. + * + * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + */ + +#ifdef __KERNEL__ +#include +#include +#undef SMALL_COPY_USES_FPU +#define EXNV(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + a, b, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXNV2(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: a, b, %o0; \ + retl; \ + add %o0, 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXNV3(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: a, b, %o0; \ + retl; \ + add %o0, 8, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EX(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + retl; \ + a, b, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK1(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + add %o4, 0x1c0, %o1; \ + and %o2, (0x40 - 1), %o2; \ + retl; \ + add %o1, %o2, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK2(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + sll %o3, 6, %o3; \ + and %o2, (0x40 - 1), %o2; \ + add %o3, 0x80, %o1; \ + retl; \ + add %o1, %o2, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK3(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o2; \ + retl; \ + add %o2, 0x80, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK4(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o2; \ + retl; \ + add %o2, 0x40, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#else +#define ASI_AIUS 0x80 +#define ASI_BLK_AIUS 0xf0 +#define FPRS_FEF 0x04 +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#define SMALL_COPY_USES_FPU +#define EXNV(x,y,a,b) x,y; +#define EXNV2(x,y,a,b) x,y; +#define EXNV3(x,y,a,b) x,y; +#define EX(x,y,a,b) x,y; +#define EXBLK1(x,y) x,y; +#define EXBLK2(x,y) x,y; +#define EXBLK3(x,y) x,y; +#define EXBLK4(x,y) x,y; +#endif + + /* Special/non-trivial issues of this code: + * + * 1) %o5 is preserved from VISEntryHalf to VISExitHalf + * 2) Only low 32 FPU registers are used so that only the + * lower half of the FPU register set is dirtied by this + * code. This is especially important in the kernel. + * 3) This code never prefetches cachelines past the end + * of the source buffer. + * + * XXX Actually, Cheetah can buffer up to 8 concurrent + * XXX prefetches, revisit this... + */ + + .text + .align 32 + + /* The cheetah's flexible spine, oversized liver, enlarged heart, + * slender muscular body, and claws make it the swiftest hunter + * in Africa and the fastest animal on land. Can reach speeds + * of up to 2.4GB per second. + */ + + .globl U3copy_in_user +U3copy_in_user: /* %o0=dst, %o1=src, %o2=len */ + /* Writing to %asi is _expensive_ so we hardcode it. + * Reading %asi to check for KERNEL_DS is comparatively + * cheap. + */ + rd %asi, %g1 ! MS Group (4 cycles) + cmp %g1, ASI_AIUS ! A0 Group + bne U3memcpy ! BR + nop ! A1 +#ifndef __KERNEL__ + /* Save away original 'dst' for memcpy return value. */ + mov %o0, %g3 ! A0 Group +#endif + /* Anything to copy at all? */ + cmp %o2, 0 ! A1 + ble,pn %icc, U3copy_in_user_short_ret ! BR + + /* Extremely small copy? */ + cmp %o2, 31 ! A0 Group + ble,pn %icc, U3copy_in_user_short ! BR + + /* Large enough to use unrolled prefetch loops? */ + cmp %o2, 0x100 ! A1 + bge,a,pt %icc, U3copy_in_user_enter ! BR Group + andcc %o0, 0x3f, %g2 ! A0 + + ba,pt %xcc, U3copy_in_user_toosmall ! BR Group + andcc %o0, 0x7, %g2 ! A0 + + .align 32 +U3copy_in_user_short: + /* Copy %o2 bytes from src to dst, one byte at a time. */ + EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g0)! MS Group + add %o1, 0x1, %o1 ! A0 + add %o0, 0x1, %o0 ! A1 + subcc %o2, 1, %o2 ! A0 Group + + bg,pt %icc, U3copy_in_user_short ! BR + EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1) ! MS Group (1-cycle stall) + +U3copy_in_user_short_ret: +#ifdef __KERNEL__ + retl ! BR Group (0-4 cycle stall) + clr %o0 ! A0 +#else + retl ! BR Group (0-4 cycle stall) + mov %g3, %o0 ! A0 +#endif + + /* Here len >= (6 * 64) and condition codes reflect execution + * of "andcc %o0, 0x7, %g2", done by caller. + */ + .align 64 +U3copy_in_user_enter: + /* Is 'dst' already aligned on an 64-byte boundary? */ + be,pt %xcc, 2f ! BR + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x40, %g2 ! A0 Group + sub %g0, %g2, %g2 ! A0 Group + sub %o2, %g2, %o2 ! A0 Group + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: EXNV(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group + +2: VISEntryHalf ! MS+MS + and %o1, 0x7, %g1 ! A1 + ba,pt %xcc, U3copy_in_user_begin ! BR + alignaddr %o1, %g0, %o1 ! MS (Break-after) + + .align 64 +U3copy_in_user_begin: + prefetch [%o1 + 0x000], #one_read ! MS Group1 + prefetch [%o1 + 0x040], #one_read ! MS Group2 + andn %o2, (0x40 - 1), %o4 ! A0 + prefetch [%o1 + 0x080], #one_read ! MS Group3 + cmp %o4, 0x140 ! A0 + prefetch [%o1 + 0x0c0], #one_read ! MS Group4 + EX(ldda [%o1 + 0x000] %asi, %f0, add %o2, %g0) ! MS Group5 (%f0 results at G8) + bge,a,pt %icc, 1f ! BR + + prefetch [%o1 + 0x100], #one_read ! MS Group6 +1: EX(ldda [%o1 + 0x008] %asi, %f2, add %o2, %g0) ! AX (%f2 results at G9) + cmp %o4, 0x180 ! A1 + bge,a,pt %icc, 1f ! BR + prefetch [%o1 + 0x140], #one_read ! MS Group7 +1: EX(ldda [%o1 + 0x010] %asi, %f4, add %o2, %g0) ! AX (%f4 results at G10) + cmp %o4, 0x1c0 ! A1 + bge,a,pt %icc, 1f ! BR + + prefetch [%o1 + 0x180], #one_read ! MS Group8 +1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) + EX(ldda [%o1 + 0x018] %asi, %f6, add %o2, %g0) ! AX (%f6 results at G12) + faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) + EX(ldda [%o1 + 0x020] %asi, %f8, add %o2, %g0) ! MS (%f8 results at G13) + faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) + EX(ldda [%o1 + 0x028] %asi, %f10, add %o2, %g0) ! MS (%f10 results at G15) + faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) + + EX(ldda [%o1 + 0x030] %asi, %f12, add %o2, %g0) ! MS (%f12 results at G16) + faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) + EX(ldda [%o1 + 0x038] %asi, %f14, add %o2, %g0) ! MS (%f14 results at G18) + faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) + EX(ldda [%o1 + 0x040] %asi, %f0, add %o2, %g0) ! MS (%f0 results at G19) + + /* We only use the first loop if len > (7 * 64). */ + subcc %o4, 0x1c0, %o4 ! A0 Group17 + bg,pt %icc, U3copy_in_user_loop1 ! BR + add %o1, 0x40, %o1 ! A1 + + add %o4, 0x140, %o4 ! A0 Group18 + ba,pt %xcc, U3copy_in_user_loop2 ! BR + srl %o4, 6, %o3 ! A0 Group19 + nop + nop + nop + nop + nop + + nop + nop + + /* This loop performs the copy and queues new prefetches. + * We drop into the second loop when len <= (5 * 64). Note + * that this (5 * 64) factor has been subtracted from len + * already. + */ +U3copy_in_user_loop1: + EXBLK1(ldda [%o1 + 0x008] %asi, %f2) ! MS Group2 (%f2 results at G5) + faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) + EXBLK1(ldda [%o1 + 0x010] %asi, %f4) ! MS Group3 (%f4 results at G6) + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) + EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS) ! MS + EXBLK1(ldda [%o1 + 0x018] %asi, %f6) ! AX (%f6 results at G7) + + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + EXBLK1(ldda [%o1 + 0x020] %asi, %f8) ! MS (%f8 results at G15) + faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) + EXBLK1(ldda [%o1 + 0x028] %asi, %f10) ! MS (%f10 results at G16) + faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) + EXBLK1(ldda [%o1 + 0x030] %asi, %f12) ! MS (%f12 results at G17) + faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) + EXBLK1(ldda [%o1 + 0x038] %asi, %f14) ! MS (%f14 results at G18) + + faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) + EXBLK1(ldda [%o1 + 0x040] %asi, %f0) ! AX (%f0 results at G19) + prefetch [%o1 + 0x180], #one_read ! MS + faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) + subcc %o4, 0x40, %o4 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3copy_in_user_loop1 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + +U3copy_in_user_loop2_enter: + mov 5, %o3 ! A1 + + /* This loop performs on the copy, no new prefetches are + * queued. We do things this way so that we do not perform + * any spurious prefetches past the end of the src buffer. + */ +U3copy_in_user_loop2: + EXBLK2(ldda [%o1 + 0x008] %asi, %f2) ! MS + faligndata %f12, %f14, %f28 ! FGA Group2 + EXBLK2(ldda [%o1 + 0x010] %asi, %f4) ! MS + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) + EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS) ! MS + EXBLK2(ldda [%o1 + 0x018] %asi, %f6) ! AX + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + + EXBLK2(ldda [%o1 + 0x020] %asi, %f8) ! MS + faligndata %f2, %f4, %f18 ! FGA Group13 + EXBLK2(ldda [%o1 + 0x028] %asi, %f10) ! MS + faligndata %f4, %f6, %f20 ! FGA Group14 + EXBLK2(ldda [%o1 + 0x030] %asi, %f12) ! MS + faligndata %f6, %f8, %f22 ! FGA Group15 + EXBLK2(ldda [%o1 + 0x038] %asi, %f14) ! MS + faligndata %f8, %f10, %f24 ! FGA Group16 + + EXBLK2(ldda [%o1 + 0x040] %asi, %f0) ! AX + faligndata %f10, %f12, %f26 ! FGA Group17 + subcc %o3, 0x01, %o3 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3copy_in_user_loop2 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + + /* Finally we copy the last full 64-byte block. */ +U3copy_in_user_loopfini: + EXBLK3(ldda [%o1 + 0x008] %asi, %f2) ! MS + faligndata %f12, %f14, %f28 ! FGA + EXBLK3(ldda [%o1 + 0x010] %asi, %f4) ! MS Group19 + faligndata %f14, %f0, %f30 ! FGA + EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS) ! MS Group20 + EXBLK4(ldda [%o1 + 0x018] %asi, %f6) ! AX + faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) + EXBLK4(ldda [%o1 + 0x020] %asi, %f8) ! MS + faligndata %f2, %f4, %f18 ! FGA Group12 + EXBLK4(ldda [%o1 + 0x028] %asi, %f10) ! MS + faligndata %f4, %f6, %f20 ! FGA Group13 + EXBLK4(ldda [%o1 + 0x030] %asi, %f12) ! MS + faligndata %f6, %f8, %f22 ! FGA Group14 + EXBLK4(ldda [%o1 + 0x038] %asi, %f14) ! MS + faligndata %f8, %f10, %f24 ! FGA Group15 + cmp %g1, 0 ! A0 + be,pt %icc, 1f ! BR + add %o0, 0x40, %o0 ! A1 + EXBLK4(ldda [%o1 + 0x040] %asi, %f0) ! MS +1: faligndata %f10, %f12, %f26 ! FGA Group16 + faligndata %f12, %f14, %f28 ! FGA Group17 + faligndata %f14, %f0, %f30 ! FGA Group18 + EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS) ! MS + add %o0, 0x40, %o0 ! A0 + add %o1, 0x40, %o1 ! A1 + membar #Sync ! MS Group26 (7-cycle stall) + + /* Now we copy the (len modulo 64) bytes at the end. + * Note how we borrow the %f0 loaded above. + * + * Also notice how this code is careful not to perform a + * load past the end of the src buffer just like similar + * code found in U3copy_in_user_toosmall processing. + */ +U3copy_in_user_loopend: + and %o2, 0x3f, %o2 ! A0 Group + andcc %o2, 0x38, %g2 ! A0 Group + be,pn %icc, U3copy_in_user_endcruft ! BR + subcc %g2, 0x8, %g2 ! A1 + be,pn %icc, U3copy_in_user_endcruft ! BR Group + cmp %g1, 0 ! A0 + + be,a,pt %icc, 1f ! BR Group + EX(ldda [%o1 + 0x00] %asi, %f0, add %o2, %g0) ! MS + +1: EX(ldda [%o1 + 0x08] %asi, %f2, add %o2, %g0) ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f0, %f2, %f8 ! FGA Group + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) + be,pn %icc, U3copy_in_user_endcruft ! BR + add %o0, 0x8, %o0 ! A0 + EX(ldda [%o1 + 0x08] %asi, %f0, add %o2, %g0) ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A0 Group + + /* If anything is left, we copy it one byte at a time. + * Note that %g1 is (src & 0x3) saved above before the + * alignaddr was performed. + */ +U3copy_in_user_endcruft: + cmp %o2, 0 + add %o1, %g1, %o1 + VISExitHalf + be,pn %icc, U3copy_in_user_short_ret + nop + ba,a,pt %xcc, U3copy_in_user_short + + /* If we get here, then 32 <= len < (6 * 64) */ +U3copy_in_user_toosmall: + +#ifdef SMALL_COPY_USES_FPU + + /* Is 'dst' already aligned on an 8-byte boundary? */ + be,pt %xcc, 2f ! BR Group + + /* Compute abs((dst & 7) - 8) into %g2. This is the number + * of bytes to copy to make 'dst' 8-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x8, %g2 ! A0 + sub %g0, %g2, %g2 ! A0 Group (reg-dep) + sub %o2, %g2, %o2 ! A0 Group (reg-dep) + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2)! MS (Group) (%o3 in 3 cycles) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group + +2: VISEntryHalf ! MS+MS + + /* Compute (len - (len % 8)) into %g2. This is guarenteed + * to be nonzero. + */ + andn %o2, 0x7, %g2 ! A0 Group + + /* You may read this and believe that it allows reading + * one 8-byte longword past the end of src. It actually + * does not, as %g2 is subtracted as loads are done from + * src, so we always stop before running off the end. + * Also, we are guarenteed to have at least 0x10 bytes + * to move here. + */ + sub %g2, 0x8, %g2 ! A0 Group (reg-dep) + alignaddr %o1, %g0, %g1 ! MS (Break-after) + EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group (1-cycle stall) + add %g1, 0x8, %g1 ! A0 + +1: EX(ldda [%g1 + 0x00] %asi, %f2, add %o2, %g0) ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + + faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + be,pn %icc, 2f ! BR + + add %o0, 0x8, %o0 ! A1 + EX(ldda [%g1 + 0x00] %asi, %f0, add %o2, %g0) ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A1 + + /* Nothing left to copy? */ +2: cmp %o2, 0 ! A0 Group + VISExitHalf ! A0+MS + be,pn %icc, U3copy_in_user_short_ret ! BR Group + nop ! A0 + ba,a,pt %xcc, U3copy_in_user_short ! BR Group + +#else /* !(SMALL_COPY_USES_FPU) */ + + xor %o1, %o0, %g2 + andcc %g2, 0x7, %g0 + bne,pn %icc, U3copy_in_user_short + andcc %o1, 0x7, %g2 + + be,pt %xcc, 2f + sub %g2, 0x8, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + +1: EXNV2(lduba [%o1 + 0x00] %asi, %o3, add %o2, %g2) + add %o1, 0x1, %o1 + add %o0, 0x1, %o0 + subcc %g2, 0x1, %g2 + bg,pt %icc, 1b + EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) + +2: andn %o2, 0x7, %g2 + sub %o2, %g2, %o2 + +3: EXNV3(ldxa [%o1 + 0x00] %asi, %o3, add %o2, %g2) + add %o1, 0x8, %o1 + add %o0, 0x8, %o0 + subcc %g2, 0x8, %g2 + bg,pt %icc, 3b + EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2) + + cmp %o2, 0 + bne,pn %icc, U3copy_in_user_short + nop + ba,a,pt %xcc, U3copy_in_user_short_ret + +#endif /* !(SMALL_COPY_USES_FPU) */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/lib/U3copy_to_user.S linux/arch/sparc64/lib/U3copy_to_user.S --- v2.4.0-test10/linux/arch/sparc64/lib/U3copy_to_user.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/U3copy_to_user.S Thu Nov 9 15:57:41 2000 @@ -0,0 +1,528 @@ +/* $Id: U3copy_to_user.S,v 1.3 2000/11/01 09:29:19 davem Exp $ + * U3memcpy.S: UltraSparc-III optimized copy to userspace. + * + * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + */ + +#ifdef __KERNEL__ +#include +#include +#undef SMALL_COPY_USES_FPU +#define EXNV(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: retl; \ + a, b, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXNV2(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: a, b, %o0; \ + retl; \ + add %o0, 1, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXNV3(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: a, b, %o0; \ + retl; \ + add %o0, 8, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EX(x,y,a,b) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + retl; \ + a, b, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK1(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + add %o4, 0x1c0, %o1; \ + and %o2, (0x40 - 1), %o2; \ + retl; \ + add %o1, %o2, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK2(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + sll %o3, 6, %o3; \ + and %o2, (0x40 - 1), %o2; \ + add %o3, 0x80, %o1; \ + retl; \ + add %o1, %o2, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK3(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o2; \ + retl; \ + add %o2, 0x80, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#define EXBLK4(x,y) \ +98: x,y; \ + .section .fixup; \ + .align 4; \ +99: VISExitHalf; \ + and %o2, (0x40 - 1), %o2; \ + retl; \ + add %o2, 0x40, %o0; \ + .section __ex_table; \ + .align 4; \ + .word 98b, 99b; \ + .text; \ + .align 4; +#else +#define ASI_AIUS 0x80 +#define ASI_BLK_AIUS 0xf0 +#define FPRS_FEF 0x04 +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#define SMALL_COPY_USES_FPU +#define EXNV(x,y,a,b) x,y; +#define EXNV2(x,y,a,b) x,y; +#define EXNV3(x,y,a,b) x,y; +#define EX(x,y,a,b) x,y; +#define EXBLK1(x,y) x,y; +#define EXBLK2(x,y) x,y; +#define EXBLK3(x,y) x,y; +#define EXBLK4(x,y) x,y; +#endif + + /* Special/non-trivial issues of this code: + * + * 1) %o5 is preserved from VISEntryHalf to VISExitHalf + * 2) Only low 32 FPU registers are used so that only the + * lower half of the FPU register set is dirtied by this + * code. This is especially important in the kernel. + * 3) This code never prefetches cachelines past the end + * of the source buffer. + */ + + .text + .align 32 + + /* The cheetah's flexible spine, oversized liver, enlarged heart, + * slender muscular body, and claws make it the swiftest hunter + * in Africa and the fastest animal on land. Can reach speeds + * of up to 2.4GB per second. + */ + + .globl U3copy_to_user +U3copy_to_user: /* %o0=dst, %o1=src, %o2=len */ + /* Writing to %asi is _expensive_ so we hardcode it. + * Reading %asi to check for KERNEL_DS is comparatively + * cheap. + */ + rd %asi, %g1 ! MS Group (4 cycles) + cmp %g1, ASI_AIUS ! A0 Group + bne U3memcpy ! BR + nop ! A1 +#ifndef __KERNEL__ + /* Save away original 'dst' for memcpy return value. */ + mov %o0, %g3 ! A0 Group +#endif + /* Anything to copy at all? */ + cmp %o2, 0 ! A1 + ble,pn %icc, U3copy_to_user_short_ret ! BR + + /* Extremely small copy? */ + cmp %o2, 31 ! A0 Group + ble,pn %icc, U3copy_to_user_short ! BR + + /* Large enough to use unrolled prefetch loops? */ + cmp %o2, 0x100 ! A1 + bge,a,pt %icc, U3copy_to_user_enter ! BR Group + andcc %o0, 0x3f, %g2 ! A0 + + ba,pt %xcc, U3copy_to_user_toosmall ! BR Group + andcc %o0, 0x7, %g2 ! A0 + + .align 32 +U3copy_to_user_short: + /* Copy %o2 bytes from src to dst, one byte at a time. */ + ldub [%o1 + 0x00], %o3 ! MS Group + add %o1, 0x1, %o1 ! A0 + add %o0, 0x1, %o0 ! A1 + subcc %o2, 1, %o2 ! A0 Group + + bg,pt %icc, U3copy_to_user_short ! BR + EXNV(stba %o3, [%o0 + -1] %asi, add %o2, 1) ! MS Group (1-cycle stall) + +U3copy_to_user_short_ret: +#ifdef __KERNEL__ + retl ! BR Group (0-4 cycle stall) + clr %o0 ! A0 +#else + retl ! BR Group (0-4 cycle stall) + mov %g3, %o0 ! A0 +#endif + + /* Here len >= (6 * 64) and condition codes reflect execution + * of "andcc %o0, 0x7, %g2", done by caller. + */ + .align 64 +U3copy_to_user_enter: + /* Is 'dst' already aligned on an 64-byte boundary? */ + be,pt %xcc, 2f ! BR + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x40, %g2 ! A0 Group + sub %g0, %g2, %g2 ! A0 Group + sub %o2, %g2, %o2 ! A0 Group + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: ldub [%o1 + 0x00], %o3 ! MS (Group) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group + +2: VISEntryHalf ! MS+MS + and %o1, 0x7, %g1 ! A1 + ba,pt %xcc, U3copy_to_user_begin ! BR + alignaddr %o1, %g0, %o1 ! MS (Break-after) + + .align 64 +U3copy_to_user_begin: + prefetch [%o1 + 0x000], #one_read ! MS Group1 + prefetch [%o1 + 0x040], #one_read ! MS Group2 + andn %o2, (0x40 - 1), %o4 ! A0 + prefetch [%o1 + 0x080], #one_read ! MS Group3 + cmp %o4, 0x140 ! A0 + prefetch [%o1 + 0x0c0], #one_read ! MS Group4 + ldd [%o1 + 0x000], %f0 ! MS Group5 (%f0 results at G8) + bge,a,pt %icc, 1f ! BR + + prefetch [%o1 + 0x100], #one_read ! MS Group6 +1: ldd [%o1 + 0x008], %f2 ! AX (%f2 results at G9) + cmp %o4, 0x180 ! A1 + bge,a,pt %icc, 1f ! BR + prefetch [%o1 + 0x140], #one_read ! MS Group7 +1: ldd [%o1 + 0x010], %f4 ! AX (%f4 results at G10) + cmp %o4, 0x1c0 ! A1 + bge,a,pt %icc, 1f ! BR + + prefetch [%o1 + 0x180], #one_read ! MS Group8 +1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) + ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G12) + faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) + ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G13) + faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) + ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G15) + faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) + + ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G16) + faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) + ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) + faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) + ldd [%o1 + 0x040], %f0 ! MS (%f0 results at G19) + + /* We only use the first loop if len > (7 * 64). */ + subcc %o4, 0x1c0, %o4 ! A0 Group17 + bg,pt %icc, U3copy_to_user_loop1 ! BR + add %o1, 0x40, %o1 ! A1 + + add %o4, 0x140, %o4 ! A0 Group18 + ba,pt %xcc, U3copy_to_user_loop2 ! BR + srl %o4, 6, %o3 ! A0 Group19 + nop + nop + nop + nop + nop + + nop + nop + + /* This loop performs the copy and queues new prefetches. + * We drop into the second loop when len <= (5 * 64). Note + * that this (5 * 64) factor has been subtracted from len + * already. + */ +U3copy_to_user_loop1: + ldd [%o1 + 0x008], %f2 ! MS Group2 (%f2 results at G5) + faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) + ldd [%o1 + 0x010], %f4 ! MS Group3 (%f4 results at G6) + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) + EXBLK1(stda %f16, [%o0] ASI_BLK_AIUS) ! MS + ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G7) + + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G15) + faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) + ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G16) + faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) + ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G17) + faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) + ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) + + faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) + ldd [%o1 + 0x040], %f0 ! AX (%f0 results at G19) + prefetch [%o1 + 0x180], #one_read ! MS + faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) + subcc %o4, 0x40, %o4 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3copy_to_user_loop1 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + +U3copy_to_user_loop2_enter: + mov 5, %o3 ! A1 + + /* This loop performs on the copy, no new prefetches are + * queued. We do things this way so that we do not perform + * any spurious prefetches past the end of the src buffer. + */ +U3copy_to_user_loop2: + ldd [%o1 + 0x008], %f2 ! MS + faligndata %f12, %f14, %f28 ! FGA Group2 + ldd [%o1 + 0x010], %f4 ! MS + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) + EXBLK2(stda %f16, [%o0] ASI_BLK_AIUS) ! MS + ldd [%o1 + 0x018], %f6 ! AX + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + + ldd [%o1 + 0x020], %f8 ! MS + faligndata %f2, %f4, %f18 ! FGA Group13 + ldd [%o1 + 0x028], %f10 ! MS + faligndata %f4, %f6, %f20 ! FGA Group14 + ldd [%o1 + 0x030], %f12 ! MS + faligndata %f6, %f8, %f22 ! FGA Group15 + ldd [%o1 + 0x038], %f14 ! MS + faligndata %f8, %f10, %f24 ! FGA Group16 + + ldd [%o1 + 0x040], %f0 ! AX + faligndata %f10, %f12, %f26 ! FGA Group17 + subcc %o3, 0x01, %o3 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3copy_to_user_loop2 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + + /* Finally we copy the last full 64-byte block. */ +U3copy_to_user_loopfini: + ldd [%o1 + 0x008], %f2 ! MS + faligndata %f12, %f14, %f28 ! FGA + ldd [%o1 + 0x010], %f4 ! MS Group19 + faligndata %f14, %f0, %f30 ! FGA + EXBLK3(stda %f16, [%o0] ASI_BLK_AIUS) ! MS Group20 + ldd [%o1 + 0x018], %f6 ! AX + faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) + ldd [%o1 + 0x020], %f8 ! MS + faligndata %f2, %f4, %f18 ! FGA Group12 + ldd [%o1 + 0x028], %f10 ! MS + faligndata %f4, %f6, %f20 ! FGA Group13 + ldd [%o1 + 0x030], %f12 ! MS + faligndata %f6, %f8, %f22 ! FGA Group14 + ldd [%o1 + 0x038], %f14 ! MS + faligndata %f8, %f10, %f24 ! FGA Group15 + cmp %g1, 0 ! A0 + be,pt %icc, 1f ! BR + add %o0, 0x40, %o0 ! A1 + ldd [%o1 + 0x040], %f0 ! MS +1: faligndata %f10, %f12, %f26 ! FGA Group16 + faligndata %f12, %f14, %f28 ! FGA Group17 + faligndata %f14, %f0, %f30 ! FGA Group18 + EXBLK4(stda %f16, [%o0] ASI_BLK_AIUS) ! MS + add %o0, 0x40, %o0 ! A0 + add %o1, 0x40, %o1 ! A1 + membar #Sync ! MS Group26 (7-cycle stall) + + /* Now we copy the (len modulo 64) bytes at the end. + * Note how we borrow the %f0 loaded above. + * + * Also notice how this code is careful not to perform a + * load past the end of the src buffer just like similar + * code found in U3copy_to_user_toosmall processing. + */ +U3copy_to_user_loopend: + and %o2, 0x3f, %o2 ! A0 Group + andcc %o2, 0x38, %g2 ! A0 Group + be,pn %icc, U3copy_to_user_endcruft ! BR + subcc %g2, 0x8, %g2 ! A1 + be,pn %icc, U3copy_to_user_endcruft ! BR Group + cmp %g1, 0 ! A0 + + be,a,pt %icc, 1f ! BR Group + ldd [%o1 + 0x00], %f0 ! MS + +1: ldd [%o1 + 0x08], %f2 ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f0, %f2, %f8 ! FGA Group + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) + be,pn %icc, U3copy_to_user_endcruft ! BR + add %o0, 0x8, %o0 ! A0 + ldd [%o1 + 0x08], %f0 ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS (XXX does it stall here? XXX) + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A0 Group + + /* If anything is left, we copy it one byte at a time. + * Note that %g1 is (src & 0x3) saved above before the + * alignaddr was performed. + */ +U3copy_to_user_endcruft: + cmp %o2, 0 + add %o1, %g1, %o1 + VISExitHalf + be,pn %icc, U3copy_to_user_short_ret + nop + ba,a,pt %xcc, U3copy_to_user_short + + /* If we get here, then 32 <= len < (6 * 64) */ +U3copy_to_user_toosmall: + +#ifdef SMALL_COPY_USES_FPU + + /* Is 'dst' already aligned on an 8-byte boundary? */ + be,pt %xcc, 2f ! BR Group + + /* Compute abs((dst & 7) - 8) into %g2. This is the number + * of bytes to copy to make 'dst' 8-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x8, %g2 ! A0 + sub %g0, %g2, %g2 ! A0 Group (reg-dep) + sub %o2, %g2, %o2 ! A0 Group (reg-dep) + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: ldub [%o1 + 0x00], %o3 ! MS (Group) (%o3 in 3 cycles) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) ! MS Group + +2: VISEntryHalf ! MS+MS + + /* Compute (len - (len % 8)) into %g2. This is guarenteed + * to be nonzero. + */ + andn %o2, 0x7, %g2 ! A0 Group + + /* You may read this and believe that it allows reading + * one 8-byte longword past the end of src. It actually + * does not, as %g2 is subtracted as loads are done from + * src, so we always stop before running off the end. + * Also, we are guarenteed to have at least 0x10 bytes + * to move here. + */ + sub %g2, 0x8, %g2 ! A0 Group (reg-dep) + alignaddr %o1, %g0, %g1 ! MS (Break-after) + ldd [%g1 + 0x00], %f0 ! MS Group (1-cycle stall) + add %g1, 0x8, %g1 ! A0 + +1: ldd [%g1 + 0x00], %f2 ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + + faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + be,pn %icc, 2f ! BR + + add %o0, 0x8, %o0 ! A1 + ldd [%g1 + 0x00], %f0 ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) + EX(stda %f8, [%o0 + 0x00] %asi, add %o2, 0x8) ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A1 + + /* Nothing left to copy? */ +2: cmp %o2, 0 ! A0 Group + VISExitHalf ! A0+MS + be,pn %icc, U3copy_to_user_short_ret ! BR Group + nop ! A0 + ba,a,pt %xcc, U3copy_to_user_short ! BR Group + +#else /* !(SMALL_COPY_USES_FPU) */ + + xor %o1, %o0, %g2 + andcc %g2, 0x7, %g0 + bne,pn %icc, U3copy_to_user_short + andcc %o1, 0x7, %g2 + + be,pt %xcc, 2f + sub %g2, 0x8, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + +1: ldub [%o1 + 0x00], %o3 + add %o1, 0x1, %o1 + add %o0, 0x1, %o0 + subcc %g2, 0x1, %g2 + bg,pt %icc, 1b + EXNV2(stba %o3, [%o0 + -1] %asi, add %o2, %g2) + +2: andn %o2, 0x7, %g2 + sub %o2, %g2, %o2 + +3: ldx [%o1 + 0x00], %o3 + add %o1, 0x8, %o1 + add %o0, 0x8, %o0 + subcc %g2, 0x8, %g2 + bg,pt %icc, 3b + EXNV3(stxa %o3, [%o0 + -8] %asi, add %o2, %g2) + + cmp %o2, 0 + bne,pn %icc, U3copy_to_user_short + nop + ba,a,pt %xcc, U3copy_to_user_short_ret + +#endif /* !(SMALL_COPY_USES_FPU) */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/lib/U3memcpy.S linux/arch/sparc64/lib/U3memcpy.S --- v2.4.0-test10/linux/arch/sparc64/lib/U3memcpy.S Wed Dec 31 16:00:00 1969 +++ linux/arch/sparc64/lib/U3memcpy.S Thu Nov 9 15:57:41 2000 @@ -0,0 +1,409 @@ +/* $Id: U3memcpy.S,v 1.2 2000/11/01 09:29:19 davem Exp $ + * U3memcpy.S: UltraSparc-III optimized memcpy. + * + * Copyright (C) 1999, 2000 David S. Miller (davem@redhat.com) + */ + +#ifdef __KERNEL__ +#include +#include +#undef SMALL_COPY_USES_FPU +#else +#define ASI_BLK_P 0xf0 +#define FPRS_FEF 0x04 +#define VISEntryHalf rd %fprs, %o5; wr %g0, FPRS_FEF, %fprs +#define VISExitHalf and %o5, FPRS_FEF, %o5; wr %o5, 0x0, %fprs +#define SMALL_COPY_USES_FPU +#endif + + /* Special/non-trivial issues of this code: + * + * 1) %o5 is preserved from VISEntryHalf to VISExitHalf + * 2) Only low 32 FPU registers are used so that only the + * lower half of the FPU register set is dirtied by this + * code. This is especially important in the kernel. + * 3) This code never prefetches cachelines past the end + * of the source buffer. + */ + + .text + .align 32 + + /* The cheetah's flexible spine, oversized liver, enlarged heart, + * slender muscular body, and claws make it the swiftest hunter + * in Africa and the fastest animal on land. Can reach speeds + * of up to 2.4GB per second. + */ + + .globl U3memcpy +U3memcpy: /* %o0=dst, %o1=src, %o2=len */ +#ifndef __KERNEL__ + /* Save away original 'dst' for memcpy return value. */ + mov %o0, %g3 ! A0 Group +#endif + /* Anything to copy at all? */ + cmp %o2, 0 ! A1 + ble,pn %icc, U3memcpy_short_ret ! BR + + /* Extremely small copy? */ + cmp %o2, 31 ! A0 Group + ble,pn %icc, U3memcpy_short ! BR + + /* Large enough to use unrolled prefetch loops? */ + cmp %o2, 0x100 ! A1 + bge,a,pt %icc, U3memcpy_enter ! BR Group + andcc %o0, 0x3f, %g2 ! A0 + + ba,pt %xcc, U3memcpy_toosmall ! BR Group + andcc %o0, 0x7, %g2 ! A0 + + .align 32 +U3memcpy_short: + /* Copy %o2 bytes from src to dst, one byte at a time. */ + ldub [%o1 + 0x00], %o3 ! MS Group + add %o1, 0x1, %o1 ! A0 + add %o0, 0x1, %o0 ! A1 + subcc %o2, 1, %o2 ! A0 Group + + bg,pt %icc, U3memcpy_short ! BR + stb %o3, [%o0 + -1] ! MS Group (1-cycle stall) + +U3memcpy_short_ret: +#ifdef __KERNEL__ + retl ! BR Group (0-4 cycle stall) + clr %o0 ! A0 +#else + retl ! BR Group (0-4 cycle stall) + mov %g3, %o0 ! A0 +#endif + + /* Here len >= (6 * 64) and condition codes reflect execution + * of "andcc %o0, 0x7, %g2", done by caller. + */ + .align 64 +U3memcpy_enter: + /* Is 'dst' already aligned on an 64-byte boundary? */ + be,pt %xcc, 2f ! BR + + /* Compute abs((dst & 0x3f) - 0x40) into %g2. This is the number + * of bytes to copy to make 'dst' 64-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x40, %g2 ! A0 Group + sub %g0, %g2, %g2 ! A0 Group + sub %o2, %g2, %o2 ! A0 Group + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: ldub [%o1 + 0x00], %o3 ! MS (Group) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + stb %o3, [%o0 + -1] ! MS Group + +2: VISEntryHalf ! MS+MS + and %o1, 0x7, %g1 ! A1 + ba,pt %xcc, U3memcpy_begin ! BR + alignaddr %o1, %g0, %o1 ! MS (Break-after) + + .align 64 +U3memcpy_begin: + prefetch [%o1 + 0x000], #one_read ! MS Group1 + prefetch [%o1 + 0x040], #one_read ! MS Group2 + andn %o2, (0x40 - 1), %o4 ! A0 + prefetch [%o1 + 0x080], #one_read ! MS Group3 + cmp %o4, 0x140 ! A0 + prefetch [%o1 + 0x0c0], #one_read ! MS Group4 + ldd [%o1 + 0x000], %f0 ! MS Group5 (%f0 results at G8) + bge,a,pt %icc, 1f ! BR + + prefetch [%o1 + 0x100], #one_read ! MS Group6 +1: ldd [%o1 + 0x008], %f2 ! AX (%f2 results at G9) + cmp %o4, 0x180 ! A1 + bge,a,pt %icc, 1f ! BR + prefetch [%o1 + 0x140], #one_read ! MS Group7 +1: ldd [%o1 + 0x010], %f4 ! AX (%f4 results at G10) + cmp %o4, 0x1c0 ! A1 + bge,a,pt %icc, 1f ! BR + + prefetch [%o1 + 0x180], #one_read ! MS Group8 +1: faligndata %f0, %f2, %f16 ! FGA Group9 (%f16 at G12) + ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G12) + faligndata %f2, %f4, %f18 ! FGA Group10 (%f18 results at G13) + ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G13) + faligndata %f4, %f6, %f20 ! FGA Group12 (1-cycle stall,%f20 at G15) + ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G15) + faligndata %f6, %f8, %f22 ! FGA Group13 (%f22 results at G16) + + ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G16) + faligndata %f8, %f10, %f24 ! FGA Group15 (1-cycle stall,%f24 at G18) + ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) + faligndata %f10, %f12, %f26 ! FGA Group16 (%f26 results at G19) + ldd [%o1 + 0x040], %f0 ! MS (%f0 results at G19) + + /* We only use the first loop if len > (7 * 64). */ + subcc %o4, 0x1c0, %o4 ! A0 Group17 + bg,pt %icc, U3memcpy_loop1 ! BR + add %o1, 0x40, %o1 ! A1 + + add %o4, 0x140, %o4 ! A0 Group18 + ba,pt %xcc, U3memcpy_loop2 ! BR + srl %o4, 6, %o3 ! A0 Group19 + nop + nop + nop + nop + nop + + nop + nop + + /* This loop performs the copy and queues new prefetches. + * We drop into the second loop when len <= (5 * 64). Note + * that this (5 * 64) factor has been subtracted from len + * already. + */ +U3memcpy_loop1: + ldd [%o1 + 0x008], %f2 ! MS Group2 (%f2 results at G5) + faligndata %f12, %f14, %f28 ! FGA (%f28 results at G5) + ldd [%o1 + 0x010], %f4 ! MS Group3 (%f4 results at G6) + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall, %f30 at G7) + stda %f16, [%o0] ASI_BLK_P ! MS + ldd [%o1 + 0x018], %f6 ! AX (%f6 results at G7) + + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + ldd [%o1 + 0x020], %f8 ! MS (%f8 results at G15) + faligndata %f2, %f4, %f18 ! FGA Group13 (%f18 results at G16) + ldd [%o1 + 0x028], %f10 ! MS (%f10 results at G16) + faligndata %f4, %f6, %f20 ! FGA Group14 (%f20 results at G17) + ldd [%o1 + 0x030], %f12 ! MS (%f12 results at G17) + faligndata %f6, %f8, %f22 ! FGA Group15 (%f22 results at G18) + ldd [%o1 + 0x038], %f14 ! MS (%f14 results at G18) + + faligndata %f8, %f10, %f24 ! FGA Group16 (%f24 results at G19) + ldd [%o1 + 0x040], %f0 ! AX (%f0 results at G19) + prefetch [%o1 + 0x180], #one_read ! MS + faligndata %f10, %f12, %f26 ! FGA Group17 (%f26 results at G20) + subcc %o4, 0x40, %o4 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3memcpy_loop1 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + +U3memcpy_loop2_enter: + mov 5, %o3 ! A1 + + /* This loop performs on the copy, no new prefetches are + * queued. We do things this way so that we do not perform + * any spurious prefetches past the end of the src buffer. + */ +U3memcpy_loop2: + ldd [%o1 + 0x008], %f2 ! MS + faligndata %f12, %f14, %f28 ! FGA Group2 + ldd [%o1 + 0x010], %f4 ! MS + faligndata %f14, %f0, %f30 ! FGA Group4 (1-cycle stall) + stda %f16, [%o0] ASI_BLK_P ! MS + ldd [%o1 + 0x018], %f6 ! AX + faligndata %f0, %f2, %f16 ! FGA Group12 (7-cycle stall) + + ldd [%o1 + 0x020], %f8 ! MS + faligndata %f2, %f4, %f18 ! FGA Group13 + ldd [%o1 + 0x028], %f10 ! MS + faligndata %f4, %f6, %f20 ! FGA Group14 + ldd [%o1 + 0x030], %f12 ! MS + faligndata %f6, %f8, %f22 ! FGA Group15 + ldd [%o1 + 0x038], %f14 ! MS + faligndata %f8, %f10, %f24 ! FGA Group16 + + ldd [%o1 + 0x040], %f0 ! AX + faligndata %f10, %f12, %f26 ! FGA Group17 + subcc %o3, 0x01, %o3 ! A0 + add %o1, 0x40, %o1 ! A1 + bg,pt %xcc, U3memcpy_loop2 ! BR + add %o0, 0x40, %o0 ! A0 Group18 + + /* Finally we copy the last full 64-byte block. */ +U3memcpy_loopfini: + ldd [%o1 + 0x008], %f2 ! MS + faligndata %f12, %f14, %f28 ! FGA + ldd [%o1 + 0x010], %f4 ! MS Group19 + faligndata %f14, %f0, %f30 ! FGA + stda %f16, [%o0] ASI_BLK_P ! MS Group20 + ldd [%o1 + 0x018], %f6 ! AX + faligndata %f0, %f2, %f16 ! FGA Group11 (7-cycle stall) + ldd [%o1 + 0x020], %f8 ! MS + faligndata %f2, %f4, %f18 ! FGA Group12 + ldd [%o1 + 0x028], %f10 ! MS + faligndata %f4, %f6, %f20 ! FGA Group13 + ldd [%o1 + 0x030], %f12 ! MS + faligndata %f6, %f8, %f22 ! FGA Group14 + ldd [%o1 + 0x038], %f14 ! MS + faligndata %f8, %f10, %f24 ! FGA Group15 + cmp %g1, 0 ! A0 + be,pt %icc, 1f ! BR + add %o0, 0x40, %o0 ! A1 + ldd [%o1 + 0x040], %f0 ! MS +1: faligndata %f10, %f12, %f26 ! FGA Group16 + faligndata %f12, %f14, %f28 ! FGA Group17 + faligndata %f14, %f0, %f30 ! FGA Group18 + stda %f16, [%o0] ASI_BLK_P ! MS + add %o0, 0x40, %o0 ! A0 + add %o1, 0x40, %o1 ! A1 + membar #Sync ! MS Group26 (7-cycle stall) + + /* Now we copy the (len modulo 64) bytes at the end. + * Note how we borrow the %f0 loaded above. + * + * Also notice how this code is careful not to perform a + * load past the end of the src buffer just like similar + * code found in U3memcpy_toosmall processing. + */ +U3memcpy_loopend: + and %o2, 0x3f, %o2 ! A0 Group + andcc %o2, 0x38, %g2 ! A0 Group + be,pn %icc, U3memcpy_endcruft ! BR + subcc %g2, 0x8, %g2 ! A1 + be,pn %icc, U3memcpy_endcruft ! BR Group + cmp %g1, 0 ! A0 + + be,a,pt %icc, 1f ! BR Group + ldd [%o1 + 0x00], %f0 ! MS + +1: ldd [%o1 + 0x08], %f2 ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f0, %f2, %f8 ! FGA Group + std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) + be,pn %icc, U3memcpy_endcruft ! BR + add %o0, 0x8, %o0 ! A0 + ldd [%o1 + 0x08], %f0 ! MS Group + add %o1, 0x8, %o1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA + std %f8, [%o0 + 0x00] ! MS (XXX does it stall here? XXX) + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A0 Group + + /* If anything is left, we copy it one byte at a time. + * Note that %g1 is (src & 0x3) saved above before the + * alignaddr was performed. + */ +U3memcpy_endcruft: + cmp %o2, 0 + add %o1, %g1, %o1 + VISExitHalf + be,pn %icc, U3memcpy_short_ret + nop + ba,a,pt %xcc, U3memcpy_short + + /* If we get here, then 32 <= len < (6 * 64) */ +U3memcpy_toosmall: + +#ifdef SMALL_COPY_USES_FPU + + /* Is 'dst' already aligned on an 8-byte boundary? */ + be,pt %xcc, 2f ! BR Group + + /* Compute abs((dst & 7) - 8) into %g2. This is the number + * of bytes to copy to make 'dst' 8-byte aligned. We pre- + * subtract this from 'len'. + */ + sub %g2, 0x8, %g2 ! A0 + sub %g0, %g2, %g2 ! A0 Group (reg-dep) + sub %o2, %g2, %o2 ! A0 Group (reg-dep) + + /* Copy %g2 bytes from src to dst, one byte at a time. */ +1: ldub [%o1 + 0x00], %o3 ! MS (Group) (%o3 in 3 cycles) + add %o1, 0x1, %o1 ! A1 + add %o0, 0x1, %o0 ! A0 Group + subcc %g2, 0x1, %g2 ! A1 + + bg,pt %icc, 1b ! BR Group + stb %o3, [%o0 + -1] ! MS Group + +2: VISEntryHalf ! MS+MS + + /* Compute (len - (len % 8)) into %g2. This is guarenteed + * to be nonzero. + */ + andn %o2, 0x7, %g2 ! A0 Group + + /* You may read this and believe that it allows reading + * one 8-byte longword past the end of src. It actually + * does not, as %g2 is subtracted as loads are done from + * src, so we always stop before running off the end. + * Also, we are guarenteed to have at least 0x10 bytes + * to move here. + */ + sub %g2, 0x8, %g2 ! A0 Group (reg-dep) + alignaddr %o1, %g0, %g1 ! MS (Break-after) + ldd [%g1 + 0x00], %f0 ! MS Group (1-cycle stall) + add %g1, 0x8, %g1 ! A0 + +1: ldd [%g1 + 0x00], %f2 ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + subcc %g2, 0x8, %g2 ! A0 Group + + faligndata %f0, %f2, %f8 ! FGA Group (1-cycle stall) + std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + be,pn %icc, 2f ! BR + + add %o0, 0x8, %o0 ! A1 + ldd [%g1 + 0x00], %f0 ! MS Group + add %g1, 0x8, %g1 ! A0 + sub %o2, 0x8, %o2 ! A1 + + subcc %g2, 0x8, %g2 ! A0 Group + faligndata %f2, %f0, %f8 ! FGA Group (1-cycle stall) + std %f8, [%o0 + 0x00] ! MS Group (2-cycle stall) + add %o1, 0x8, %o1 ! A0 + + bne,pn %icc, 1b ! BR + add %o0, 0x8, %o0 ! A1 + + /* Nothing left to copy? */ +2: cmp %o2, 0 ! A0 Group + VISExitHalf ! A0+MS + be,pn %icc, U3memcpy_short_ret ! BR Group + nop ! A0 + ba,a,pt %xcc, U3memcpy_short ! BR Group + +#else /* !(SMALL_COPY_USES_FPU) */ + + xor %o1, %o0, %g2 + andcc %g2, 0x7, %g0 + bne,pn %icc, U3memcpy_short + andcc %o1, 0x7, %g2 + + be,pt %xcc, 2f + sub %g2, 0x8, %g2 + sub %g0, %g2, %g2 + sub %o2, %g2, %o2 + +1: ldub [%o1 + 0x00], %o3 + add %o1, 0x1, %o1 + add %o0, 0x1, %o0 + subcc %g2, 0x1, %g2 + bg,pt %icc, 1b + stb %o3, [%o0 + -1] + +2: andn %o2, 0x7, %g2 + sub %o2, %g2, %o2 + +3: ldx [%o1 + 0x00], %o3 + add %o1, 0x8, %o1 + add %o0, 0x8, %o0 + subcc %g2, 0x8, %g2 + bg,pt %icc, 3b + stx %o3, [%o0 + -8] + + cmp %o2, 0 + bne,pn %icc, U3memcpy_short + nop + ba,a,pt %xcc, U3memcpy_short_ret + +#endif /* !(SMALL_COPY_USES_FPU) */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/lib/VIScopy.S linux/arch/sparc64/lib/VIScopy.S --- v2.4.0-test10/linux/arch/sparc64/lib/VIScopy.S Mon Mar 27 10:35:56 2000 +++ linux/arch/sparc64/lib/VIScopy.S Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: VIScopy.S,v 1.23 2000/03/26 09:13:49 davem Exp $ +/* $Id: VIScopy.S,v 1.25 2000/11/01 09:29:19 davem Exp $ * VIScopy.S: High speed copy operations utilizing the UltraSparc * Visual Instruction Set. * @@ -360,6 +360,38 @@ retl ! CTI Group brk forced clr %o0 ! IEU0 + +#ifdef __KERNEL__ +#define BRANCH_ALWAYS 0x10680000 +#define NOP 0x01000000 +#define ULTRA3_DO_PATCH(OLD, NEW) \ + sethi %hi(NEW), %g1; \ + or %g1, %lo(NEW), %g1; \ + sethi %hi(OLD), %g2; \ + or %g2, %lo(OLD), %g2; \ + sub %g1, %g2, %g1; \ + sethi %hi(BRANCH_ALWAYS), %g3; \ + srl %g1, 2, %g1; \ + or %g3, %lo(BRANCH_ALWAYS), %g3; \ + or %g3, %g1, %g3; \ + stw %g3, [%g2]; \ + sethi %hi(NOP), %g3; \ + or %g3, %lo(NOP), %g3; \ + stw %g3, [%g2 + 0x4]; \ + flush %g2; + + .globl cheetah_patch_copyops +cheetah_patch_copyops: + ULTRA3_DO_PATCH(memcpy, U3memcpy) + ULTRA3_DO_PATCH(__copy_from_user, U3copy_from_user) + ULTRA3_DO_PATCH(__copy_to_user, U3copy_to_user) + ULTRA3_DO_PATCH(__copy_in_user, U3copy_in_user) + retl + nop +#undef BRANCH_ALWAYS +#undef NOP +#undef ULTRA3_DO_PATCH +#endif /* __KERNEL__ */ .align 32 #ifdef __KERNEL__ diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c --- v2.4.0-test10/linux/arch/sparc64/mm/init.c Tue Oct 31 12:42:26 2000 +++ linux/arch/sparc64/mm/init.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: init.c,v 1.157 2000/10/19 00:49:52 davem Exp $ +/* $Id: init.c,v 1.159 2000/11/06 06:59:04 davem Exp $ * arch/sparc64/mm/init.c * * Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu) @@ -97,6 +97,20 @@ } #endif return freed; +} + +extern void __update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); + +void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte) +{ + struct page *page = pte_page(pte); + + if (VALID_PAGE(page) && page->mapping && + test_bit(PG_dcache_dirty, &page->flags)) { + __flush_dcache_page(page->virtual, 1); + clear_bit(PG_dcache_dirty, &page->flags); + } + __update_mmu_cache(vma, address, pte); } /* diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S --- v2.4.0-test10/linux/arch/sparc64/mm/ultra.S Sun Aug 6 11:43:17 2000 +++ linux/arch/sparc64/mm/ultra.S Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: ultra.S,v 1.46 2000/08/05 13:30:33 davem Exp $ +/* $Id: ultra.S,v 1.48 2000/11/06 06:59:04 davem Exp $ * ultra.S: Don't expand these all over the place... * * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com) @@ -208,27 +208,58 @@ .align 64 .globl __flush_dcache_page -__flush_dcache_page: +__flush_dcache_page: /* %o0=kaddr, %o1=flush_icache */ sub %o0, %g4, %o0 - clr %o1 + clr %o4 srlx %o0, 11, %o0 sethi %hi(1 << 14), %o2 -1: ldxa [%o1] ASI_DCACHE_TAG, %o3 - andn %o3, 0x3, %o3 - cmp %o0, %o3 - bne,pt %xcc, 2f - nop - stxa %g0, [%o1] ASI_DCACHE_TAG - membar #Sync -2: add %o1, (1 << 5), %o1 - cmp %o1, %o2 - bne,pt %xcc, 1b - nop +1: ldxa [%o4] ASI_DCACHE_TAG, %o3 ! LSU Group + add %o4, (1 << 5), %o4 ! IEU0 + ldxa [%o4] ASI_DCACHE_TAG, %g1 ! LSU Group + add %o4, (1 << 5), %o4 ! IEU0 + ldxa [%o4] ASI_DCACHE_TAG, %g2 ! LSU Group o3 available + add %o4, (1 << 5), %o4 ! IEU0 + andn %o3, 0x3, %o3 ! IEU1 + ldxa [%o4] ASI_DCACHE_TAG, %g3 ! LSU Group + add %o4, (1 << 5), %o4 ! IEU0 + andn %g1, 0x3, %g1 ! IEU1 + cmp %o0, %o3 ! IEU1 Group + be,a,pn %xcc, dflush1 ! CTI + sub %o4, (4 << 5), %o4 ! IEU0 (Group) + cmp %o0, %g1 ! IEU1 Group + andn %g2, 0x3, %g2 ! IEU0 + be,a,pn %xcc, dflush2 ! CTI + sub %o4, (3 << 5), %o4 ! IEU0 (Group) + cmp %o0, %g2 ! IEU1 Group + andn %g3, 0x3, %g3 ! IEU0 + be,a,pn %xcc, dflush3 ! CTI + sub %o4, (2 << 5), %o4 ! IEU0 (Group) + cmp %o0, %g3 ! IEU1 Group + be,a,pn %xcc, dflush4 ! CTI + sub %o4, (1 << 5), %o4 ! IEU0 +2: cmp %o4, %o2 ! IEU1 Group + bne,pt %xcc, 1b ! CTI + nop ! IEU0 + /* The I-cache does not snoop local stores so we - * better flush that too. + * better flush that too when necessary. */ - ba,pt %xcc, __flush_icache_page + brnz,pt %o1, __flush_icache_page sllx %o0, 11, %o0 + retl + nop + +dflush1:stxa %g0, [%o4] ASI_DCACHE_TAG + add %o4, (1 << 5), %o4 +dflush2:stxa %g0, [%o4] ASI_DCACHE_TAG + add %o4, (1 << 5), %o4 +dflush3:stxa %g0, [%o4] ASI_DCACHE_TAG + add %o4, (1 << 5), %o4 +dflush4:stxa %g0, [%o4] ASI_DCACHE_TAG + add %o4, (1 << 5), %o4 + membar #Sync + ba,pt %xcc, 2b + nop .align 32 __prefill_dtlb: @@ -250,8 +281,8 @@ retl wrpr %g7, %pstate - .globl update_mmu_cache -update_mmu_cache: /* %o0=vma, %o1=address, %o2=pte */ + .globl __update_mmu_cache +__update_mmu_cache: /* %o0=vma, %o1=address, %o2=pte */ ldub [%g6 + AOFF_task_thread + AOFF_thread_fault_code], %o3 srlx %o1, 13, %o1 ldx [%o0 + 0x0], %o4 /* XXX vma->vm_mm */ diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/solaris/ioctl.c linux/arch/sparc64/solaris/ioctl.c --- v2.4.0-test10/linux/arch/sparc64/solaris/ioctl.c Fri Aug 4 18:16:11 2000 +++ linux/arch/sparc64/solaris/ioctl.c Fri Nov 17 11:36:27 2000 @@ -464,8 +464,8 @@ struct sol_socket_struct *sock; struct module_info *mi; - if (! (ino = filp->f_dentry->d_inode) || - ! ino->i_sock) + ino = filp->f_dentry->d_inode; + if (! ino->i_sock) return -EBADF; sock = filp->private_data; if (! sock) { diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/solaris/socket.c linux/arch/sparc64/solaris/socket.c --- v2.4.0-test10/linux/arch/sparc64/solaris/socket.c Fri Aug 18 10:26:25 2000 +++ linux/arch/sparc64/solaris/socket.c Fri Nov 17 11:36:27 2000 @@ -265,7 +265,7 @@ } inode = file->f_dentry->d_inode; - if (!inode || !inode->i_sock || !socki_lookup(inode)) { + if (!inode->i_sock || !socki_lookup(inode)) { *err = -ENOTSOCK; fput(file); return NULL; diff -u --recursive --new-file v2.4.0-test10/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds --- v2.4.0-test10/linux/arch/sparc64/vmlinux.lds Wed Jul 5 22:15:25 2000 +++ linux/arch/sparc64/vmlinux.lds Thu Nov 9 15:57:41 2000 @@ -35,6 +35,9 @@ __ksymtab : { *(__ksymtab) } __stop___ksymtab = .; __kstrtab : { *(.kstrtab) } + __start___kallsyms = .; /* All kernel symbols */ + __kallsyms : { *(__kallsyms) } + __stop___kallsyms = .; . = ALIGN(8192); __init_begin = .; .text.init : { *(.text.init) } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c --- v2.4.0-test10/linux/drivers/acorn/net/etherh.c Sun Oct 8 10:50:13 2000 +++ linux/drivers/acorn/net/etherh.c Tue Nov 7 10:59:42 2000 @@ -622,9 +622,6 @@ { int i, ret = -ENODEV; - if (load_8390_module("etherh.c")) - return -ENOSYS; - ecard_startfind(); for (i = 0; i < MAX_ECARDS; i++) { @@ -644,9 +641,6 @@ ret = 0; } - if (ret) - unload_8390_module(); - return ret; } @@ -667,7 +661,6 @@ e_card[i] = NULL; } } - unload_8390_module(); } module_init(etherh_init); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c --- v2.4.0-test10/linux/drivers/acpi/driver.c Sun Oct 8 10:50:13 2000 +++ linux/drivers/acpi/driver.c Wed Nov 8 17:09:50 2000 @@ -284,7 +284,7 @@ /* * initialize */ - exit_files(current); + daemonize(); strcpy(current->comm, "acpi"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/atm/atmtcp.c linux/drivers/atm/atmtcp.c --- v2.4.0-test10/linux/drivers/atm/atmtcp.c Tue Jun 20 13:58:42 2000 +++ linux/drivers/atm/atmtcp.c Tue Nov 14 23:36:01 2000 @@ -77,6 +77,7 @@ set_current_state(TASK_UNINTERRUPTIBLE); schedule(); } + current->state = TASK_RUNNING; remove_wait_queue(&vcc->sleep,&wait); return error; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c --- v2.4.0-test10/linux/drivers/atm/nicstar.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/atm/nicstar.c Tue Nov 14 13:16:33 2000 @@ -271,24 +271,8 @@ proc_read: ns_proc_read }; static struct timer_list ns_timer; -static char *mac[NS_MAX_CARDS] = { NULL -#if NS_MAX_CARDS > 1 - , NULL -#endif /* NS_MAX_CARDS > 1 */ -#if NS_MAX_CARDS > 2 - , NULL -#endif /* NS_MAX_CARDS > 2 */ -#if NS_MAX_CARDS > 3 - , NULL -#endif /* NS_MAX_CARDS > 3 */ -#if NS_MAX_CARDS > 4 - , NULL -#endif /* NS_MAX_CARDS > 4 */ - }; - -#ifdef MODULE +static char *mac[NS_MAX_CARDS]; MODULE_PARM(mac, "1-" __MODULE_STRING(NS_MAX_CARDS) "s"); -#endif /* MODULE */ /* Functions*******************************************************************/ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c --- v2.4.0-test10/linux/drivers/block/cpqarray.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/block/cpqarray.c Thu Nov 16 11:30:29 2000 @@ -44,8 +44,8 @@ #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin)) -#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.0)" -#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,0) +#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.1)" +#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,1) /* Embedded module documentation macros - see modules.h */ /* Original author Chris Frantz - Compaq Computer Corporation */ @@ -1664,6 +1664,7 @@ int ret_code, size; drv_info_t *drv; ctlr_info_t *info_p = hba[ctlr]; + int i; info_p->log_drv_map = 0; @@ -1729,7 +1730,8 @@ } info_p->log_drives = id_ctlr_buf->nr_drvs;; - *(__u32*)(info_p->firm_rev) = *(__u32*)(id_ctlr_buf->firm_rev); + for(i=0;i<4;i++) + info_p->firm_rev[i] = id_ctlr_buf->firm_rev[i]; info_p->ctlr_sig = id_ctlr_buf->cfg_sig; printk(" (%s)\n", info_p->product_name); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c --- v2.4.0-test10/linux/drivers/block/ll_rw_blk.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/block/ll_rw_blk.c Thu Nov 16 13:59:06 2000 @@ -347,10 +347,9 @@ */ static inline void __generic_unplug_device(request_queue_t *q) { - if (q->plugged) { + if (!list_empty(&q->queue_head)) { q->plugged = 0; - if (!list_empty(&q->queue_head)) - q->request_fn(q); + q->request_fn(q); } } @@ -496,7 +495,7 @@ add_wait_queue_exclusive(&q->wait_for_request, &wait); for (;;) { - __set_current_state(TASK_UNINTERRUPTIBLE | TASK_EXCLUSIVE); + __set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_irq(&io_request_lock); rq = get_request(q, rw); spin_unlock_irq(&io_request_lock); @@ -683,7 +682,7 @@ { unsigned int sector, count; int max_segments = MAX_SEGMENTS; - struct request * req = NULL; + struct request * req = NULL, *freereq = NULL; int rw_ahead, max_sectors, el_ret; struct list_head *head = &q->queue_head; int latency; @@ -733,6 +732,7 @@ * Now we acquire the request spinlock, we have to be mega careful * not to schedule or do something nonatomic */ +again: spin_lock_irq(&io_request_lock); /* @@ -791,19 +791,16 @@ * are not crucial. */ get_rq: - if ((req = get_request(q, rw)) == NULL) { + if (freereq) { + req = freereq; + freereq = NULL; + } else if ((req = get_request(q, rw)) == NULL) { spin_unlock_irq(&io_request_lock); if (rw_ahead) goto end_io; - req = __get_request_wait(q, rw); - spin_lock_irq(&io_request_lock); - - if (q->head_active) { - head = &q->queue_head; - if (!q->plugged) - head = head->next; - } + freereq = __get_request_wait(q, rw); + goto again; } /* fill up the request-info, and add it to the queue */ @@ -824,6 +821,8 @@ out: if (!q->plugged) (q->request_fn)(q); + if (freereq) + blkdev_release_request(freereq); spin_unlock_irq(&io_request_lock); return 0; end_io: @@ -1059,7 +1058,7 @@ #endif #ifdef CONFIG_ISP16_CDI isp16_init(); -#endif CONFIG_ISP16_CDI +#endif #if defined(CONFIG_IDE) && defined(CONFIG_BLK_DEV_IDE) ide_init(); /* this MUST precede hd_init */ #endif @@ -1099,37 +1098,37 @@ #endif #ifdef CONFIG_CDU31A cdu31a_init(); -#endif CONFIG_CDU31A +#endif #ifdef CONFIG_ATARI_ACSI acsi_init(); -#endif CONFIG_ATARI_ACSI +#endif #ifdef CONFIG_MCD mcd_init(); -#endif CONFIG_MCD +#endif #ifdef CONFIG_MCDX mcdx_init(); -#endif CONFIG_MCDX +#endif #ifdef CONFIG_SBPCD sbpcd_init(); -#endif CONFIG_SBPCD +#endif #ifdef CONFIG_AZTCD aztcd_init(); -#endif CONFIG_AZTCD +#endif #ifdef CONFIG_CDU535 sony535_init(); -#endif CONFIG_CDU535 +#endif #ifdef CONFIG_GSCD gscd_init(); -#endif CONFIG_GSCD +#endif #ifdef CONFIG_CM206 cm206_init(); #endif #ifdef CONFIG_OPTCD optcd_init(); -#endif CONFIG_OPTCD +#endif #ifdef CONFIG_SJCD sjcd_init(); -#endif CONFIG_SJCD +#endif #ifdef CONFIG_APBLOCK ap_init(); #endif @@ -1150,7 +1149,7 @@ #endif #ifdef CONFIG_BLK_DEV_LVM lvm_init(); -#endif +#endif return 0; }; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/block/loop.c linux/drivers/block/loop.c --- v2.4.0-test10/linux/drivers/block/loop.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/block/loop.c Fri Nov 17 11:36:27 2000 @@ -235,7 +235,7 @@ if (size > count) size = count; - kaddr = (char*)kmap(page); + kaddr = kmap(page); if ((lo->transfer)(lo,READ,kaddr+offset,p->data,size,IV)) { size = 0; printk(KERN_ERR "loop: transfer error block %ld\n", @@ -411,10 +411,6 @@ error = -EINVAL; inode = file->f_dentry->d_inode; - if (!inode) { - printk(KERN_ERR "loop_set_fd: NULL inode?!?\n"); - goto out_putf; - } if (S_ISBLK(inode->i_mode)) { /* dentry will be wired, so... */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/block/rd.c linux/drivers/block/rd.c --- v2.4.0-test10/linux/drivers/block/rd.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/block/rd.c Fri Nov 17 16:46:55 2000 @@ -100,7 +100,7 @@ static int rd_blocksizes[NUM_RAMDISKS]; /* Size of 1024 byte blocks :) */ static int rd_kbsize[NUM_RAMDISKS]; /* Size in blocks of 1024 bytes */ static devfs_handle_t devfs_handle; -static struct inode *rd_inode[NUM_RAMDISKS]; /* Protected device inodes */ +static struct inode *rd_inode[NUM_RAMDISKS]; /* Protected device inodes */ /* * Parameters for the boot-loading of the RAM disk. These are set by @@ -108,7 +108,7 @@ * architecture-specific setup routine (from the stored boot sector * information). */ -int rd_size = 4096; /* Size of the RAM disks */ +int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */ /* * It would be very desiderable to have a soft-blocksize (that in the case * of the ramdisk driver is also the hardblocksize ;) of PAGE_SIZE because @@ -120,7 +120,7 @@ * behaviour. The default is still BLOCK_SIZE (needed by rd_load_image that * supposes the filesystem in the image uses a BLOCK_SIZE blocksize). */ -int rd_blocksize = BLOCK_SIZE; /* Size of the RAM disks */ +int rd_blocksize = BLOCK_SIZE; /* blocksize of the RAM disks */ #ifndef MODULE @@ -194,50 +194,53 @@ * 19-JAN-1998 Richard Gooch Added devfs support * */ -static void rd_request(request_queue_t * q) +static int rd_make_request(request_queue_t * q, int rw, struct buffer_head *sbh) { unsigned int minor; unsigned long offset, len; struct buffer_head *rbh; - struct buffer_head *sbh; + char *bdata; -repeat: - INIT_REQUEST; - minor = MINOR(CURRENT->rq_dev); + minor = MINOR(sbh->b_rdev); + + if (minor >= NUM_RAMDISKS) + goto fail; - if (minor >= NUM_RAMDISKS) { - end_request(0); - goto repeat; - } - offset = CURRENT->sector << 9; - len = CURRENT->current_nr_sectors << 9; + offset = sbh->b_rsector << 9; + len = sbh->b_size; - if ((offset + len) > rd_length[minor]) { - end_request(0); - goto repeat; - } + if ((offset + len) > rd_length[minor]) + goto fail; - if ((CURRENT->cmd != READ) && (CURRENT->cmd != WRITE)) { - printk(KERN_INFO "RAMDISK: bad command: %d\n", CURRENT->cmd); - end_request(0); - goto repeat; + if (rw==READA) + rw=READ; + if ((rw != READ) && (rw != WRITE)) { + printk(KERN_INFO "RAMDISK: bad command: %d\n", rw); + goto fail; } - sbh = CURRENT->bh; - rbh = getblk(sbh->b_dev, sbh->b_blocknr, sbh->b_size); - if (CURRENT->cmd == READ) { + rbh = getblk(sbh->b_rdev, sbh->b_rsector/(sbh->b_size>>9), sbh->b_size); + /* I think that it is safe to assume that rbh is not in HighMem, though + * sbh might be - NeilBrown + */ + bdata = bh_kmap(sbh); + if (rw == READ) { if (sbh != rbh) - memcpy(CURRENT->buffer, rbh->b_data, rbh->b_size); + memcpy(bdata, rbh->b_data, rbh->b_size); } else if (sbh != rbh) - memcpy(rbh->b_data, CURRENT->buffer, rbh->b_size); + memcpy(rbh->b_data, bdata, rbh->b_size); + bh_kunmap(sbh); mark_buffer_protected(rbh); brelse(rbh); - end_request(1); - goto repeat; + sbh->b_end_io(sbh,1); + return 0; + fail: + sbh->b_end_io(sbh,0); + return 0; } static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) @@ -378,7 +381,6 @@ devfs_unregister (devfs_handle); unregister_blkdev( MAJOR_NR, "ramdisk" ); - blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); hardsect_size[MAJOR_NR] = NULL; blksize_size[MAJOR_NR] = NULL; blk_size[MAJOR_NR] = NULL; @@ -403,7 +405,7 @@ return -EIO; } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_request); + blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), &rd_make_request); for (i = 0; i < NUM_RAMDISKS; i++) { /* rd_size is given in kB */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/Config.in linux/drivers/char/Config.in --- v2.4.0-test10/linux/drivers/char/Config.in Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/Config.in Thu Nov 16 13:59:53 2000 @@ -16,7 +16,7 @@ tristate ' Dual serial port support' CONFIG_DUALSP_SERIAL fi fi -dep_bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL +dep_mbool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED $CONFIG_SERIAL if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then bool ' Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS bool ' Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ @@ -178,8 +178,8 @@ tristate '/dev/agpgart (AGP Support)' CONFIG_AGP $CONFIG_DRM_AGP if [ "$CONFIG_AGP" != "n" ]; then - bool ' Intel 440LX/BX/GX 840 support' CONFIG_AGP_INTEL - bool ' Intel I810/I815 support' CONFIG_AGP_I810 + bool ' Intel 440LX/BX/GX and I815/I840 support' CONFIG_AGP_INTEL + bool ' Intel I810/I815 (on-board) support' CONFIG_AGP_I810 bool ' VIA chipset support' CONFIG_AGP_VIA bool ' AMD Irongate support' CONFIG_AGP_AMD bool ' Generic SiS support' CONFIG_AGP_SIS diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h --- v2.4.0-test10/linux/drivers/char/agp/agp.h Sun Aug 13 19:37:15 2000 +++ linux/drivers/char/agp/agp.h Tue Nov 7 10:59:43 2000 @@ -144,8 +144,6 @@ #define min(a,b) (((a)<(b))?(a):(b)) #endif -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define AGPGART_MODULE_NAME "agpgart" #define PFX AGPGART_MODULE_NAME ": " diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c --- v2.4.0-test10/linux/drivers/char/agp/agpgart_be.c Mon Aug 21 08:08:12 2000 +++ linux/drivers/char/agp/agpgart_be.c Thu Nov 16 13:59:53 2000 @@ -2057,6 +2057,13 @@ "Intel", "440GX", intel_generic_setup }, + /* could we add support for PCI_DEVICE_ID_INTEL_815_1 too ? */ + { PCI_DEVICE_ID_INTEL_815_0, + PCI_VENDOR_ID_INTEL, + INTEL_I815, + "Intel", + "i815", + intel_generic_setup }, { PCI_DEVICE_ID_INTEL_840_0, PCI_VENDOR_ID_INTEL, INTEL_I840, @@ -2182,16 +2189,16 @@ { int i; - for (i = 0; i < arraysize (agp_bridge_info); i++) + for (i = 0; i < ARRAY_SIZE (agp_bridge_info); i++) if (pdev->vendor == agp_bridge_info[i].vendor_id) break; - if (i >= arraysize (agp_bridge_info)) { + if (i >= ARRAY_SIZE (agp_bridge_info)) { printk (KERN_DEBUG PFX "unsupported bridge\n"); return -ENODEV; } - while ((i < arraysize (agp_bridge_info)) && + while ((i < ARRAY_SIZE (agp_bridge_info)) && (agp_bridge_info[i].vendor_id == pdev->vendor)) { if (pdev->device == agp_bridge_info[i].device_id) { printk (KERN_INFO PFX "Detected %s %s chipset\n", @@ -2490,6 +2497,17 @@ extern int agp_frontend_initialize(void); extern void agp_frontend_cleanup(void); +static const drm_agp_t drm_agp = { + &agp_free_memory, + &agp_allocate_memory, + &agp_bind_memory, + &agp_unbind_memory, + &agp_enable, + &agp_backend_acquire, + &agp_backend_release, + &agp_copy_info +}; + static int __init agp_init(void) { int ret_val; @@ -2509,6 +2527,7 @@ return ret_val; } + inter_module_register("drm_agp", THIS_MODULE, &drm_agp); return 0; } @@ -2516,6 +2535,7 @@ { agp_frontend_cleanup(); agp_backend_cleanup(); + inter_module_unregister("drm_agp"); } module_init(agp_init); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/console.c linux/drivers/char/console.c --- v2.4.0-test10/linux/drivers/char/console.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/console.c Fri Nov 10 10:56:47 2000 @@ -2135,7 +2135,6 @@ } } set_cursor(currcons); - poke_blanked_console(); quit: clear_bit(0, &printing); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c --- v2.4.0-test10/linux/drivers/char/cyclades.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/cyclades.c Wed Nov 15 00:41:03 2000 @@ -2517,6 +2517,8 @@ firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); if (!ISZLOADED(*cinfo)){ + current->state = TASK_RUNNING; + remove_wait_queue(&info->open_wait, &wait); return -EINVAL; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/agpsupport.c linux/drivers/char/drm/agpsupport.c --- v2.4.0-test10/linux/drivers/char/drm/agpsupport.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/char/drm/agpsupport.c Thu Nov 16 14:05:49 2000 @@ -31,48 +31,14 @@ #define __NO_VERSION__ #include "drmP.h" #include +#if LINUX_VERSION_CODE < 0x020400 +#include "agpsupport-pre24.h" +#else +#define DRM_AGP_GET (drm_agp_t *)inter_module_get("drm_agp") +#define DRM_AGP_PUT inter_module_put("drm_agp") +#endif -drm_agp_func_t drm_agp = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - -/* The C standard says that 'void *' is not guaranteed to hold a function - pointer, so we use this union to define a generic pointer that is - guaranteed to hold any of the function pointers we care about. */ -typedef union { - void (*free_memory)(agp_memory *); - agp_memory *(*allocate_memory)(size_t, u32); - int (*bind_memory)(agp_memory *, off_t); - int (*unbind_memory)(agp_memory *); - void (*enable)(u32); - int (*acquire)(void); - void (*release)(void); - void (*copy_info)(agp_kern_info *); - unsigned long address; -} drm_agp_func_u; - -typedef struct drm_agp_fill { - const char *name; - drm_agp_func_u *f; -} drm_agp_fill_t; - -static drm_agp_fill_t drm_agp_fill[] = { - { __MODULE_STRING(agp_free_memory), - (drm_agp_func_u *)&drm_agp.free_memory }, - { __MODULE_STRING(agp_allocate_memory), - (drm_agp_func_u *)&drm_agp.allocate_memory }, - { __MODULE_STRING(agp_bind_memory), - (drm_agp_func_u *)&drm_agp.bind_memory }, - { __MODULE_STRING(agp_unbind_memory), - (drm_agp_func_u *)&drm_agp.unbind_memory }, - { __MODULE_STRING(agp_enable), - (drm_agp_func_u *)&drm_agp.enable }, - { __MODULE_STRING(agp_backend_acquire), - (drm_agp_func_u *)&drm_agp.acquire }, - { __MODULE_STRING(agp_backend_release), - (drm_agp_func_u *)&drm_agp.release }, - { __MODULE_STRING(agp_copy_info), - (drm_agp_func_u *)&drm_agp.copy_info }, - { NULL, NULL } -}; +static const drm_agp_t *drm_agp = NULL; int drm_agp_info(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) @@ -82,7 +48,7 @@ agp_kern_info *kern; drm_agp_info_t info; - if (!dev->agp->acquired || !drm_agp.copy_info) return -EINVAL; + if (!dev->agp->acquired || !drm_agp->copy_info) return -EINVAL; kern = &dev->agp->agp_info; info.agp_version_major = kern->version.major; @@ -107,8 +73,8 @@ drm_device_t *dev = priv->dev; int retcode; - if (dev->agp->acquired || !drm_agp.acquire) return -EINVAL; - if ((retcode = (*drm_agp.acquire)())) return retcode; + if (dev->agp->acquired || !drm_agp->acquire) return -EINVAL; + if ((retcode = drm_agp->acquire())) return retcode; dev->agp->acquired = 1; return 0; } @@ -119,13 +85,18 @@ drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - if (!dev->agp->acquired || !drm_agp.release) return -EINVAL; - (*drm_agp.release)(); + if (!dev->agp->acquired || !drm_agp->release) return -EINVAL; + drm_agp->release(); dev->agp->acquired = 0; return 0; } +void _drm_agp_release(void) +{ + if (drm_agp->release) drm_agp->release(); +} + int drm_agp_enable(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { @@ -133,13 +104,13 @@ drm_device_t *dev = priv->dev; drm_agp_mode_t mode; - if (!dev->agp->acquired || !drm_agp.enable) return -EINVAL; + if (!dev->agp->acquired || !drm_agp->enable) return -EINVAL; if (copy_from_user(&mode, (drm_agp_mode_t *)arg, sizeof(mode))) return -EFAULT; dev->agp->mode = mode.mode; - (*drm_agp.enable)(mode.mode); + drm_agp->enable(mode.mode); dev->agp->base = dev->agp->agp_info.aper_base; dev->agp->enabled = 1; return 0; @@ -231,7 +202,7 @@ int retcode; int page; - if (!dev->agp->acquired || !drm_agp.bind_memory) return -EINVAL; + if (!dev->agp->acquired || !drm_agp->bind_memory) return -EINVAL; if (copy_from_user(&request, (drm_agp_binding_t *)arg, sizeof(request))) return -EFAULT; if (!(entry = drm_agp_lookup_entry(dev, request.handle))) @@ -270,24 +241,14 @@ drm_agp_head_t *drm_agp_init(void) { - drm_agp_fill_t *fill; drm_agp_head_t *head = NULL; - int agp_available = 1; - - for (fill = &drm_agp_fill[0]; fill->name; fill++) { - char *n = (char *)fill->name; - *fill->f = (drm_agp_func_u)get_module_symbol(NULL, n); - DRM_DEBUG("%s resolves to 0x%08lx\n", n, (*fill->f).address); - if (!(*fill->f).address) agp_available = 0; - } - - DRM_DEBUG("agp_available = %d\n", agp_available); - if (agp_available) { + drm_agp = DRM_AGP_GET; + if (drm_agp) { if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS))) return NULL; memset((void *)head, 0, sizeof(*head)); - (*drm_agp.copy_info)(&head->agp_info); + drm_agp->copy_info(&head->agp_info); if (head->agp_info.chipset == NOT_SUPPORTED) { drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS); return NULL; @@ -337,12 +298,31 @@ void drm_agp_uninit(void) { - drm_agp_fill_t *fill; - - for (fill = &drm_agp_fill[0]; fill->name; fill++) { -#if LINUX_VERSION_CODE >= 0x020400 - if ((*fill->f).address) put_module_symbol((*fill->f).address); -#endif - (*fill->f).address = 0; - } + DRM_AGP_PUT; + drm_agp = NULL; +} + +agp_memory *drm_agp_allocate_memory(size_t pages, u32 type) +{ + if (!drm_agp->allocate_memory) return NULL; + return drm_agp->allocate_memory(pages, type); +} + +int drm_agp_free_memory(agp_memory *handle) +{ + if (!handle || !drm_agp->free_memory) return 0; + drm_agp->free_memory(handle); + return 1; +} + +int drm_agp_bind_memory(agp_memory *handle, off_t start) +{ + if (!handle || !drm_agp->bind_memory) return -EINVAL; + return drm_agp->bind_memory(handle, start); +} + +int drm_agp_unbind_memory(agp_memory *handle) +{ + if (!handle || !drm_agp->unbind_memory) return -EINVAL; + return drm_agp->unbind_memory(handle); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/dma.c linux/drivers/char/drm/dma.c --- v2.4.0-test10/linux/drivers/char/drm/dma.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/dma.c Wed Nov 15 00:41:03 2000 @@ -405,6 +405,7 @@ schedule(); if (signal_pending(current)) { atomic_dec(&q->use_count); + remove_wait_queue(&q->write_queue, &entry); return -EINTR; } } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/drmP.h linux/drivers/char/drm/drmP.h --- v2.4.0-test10/linux/drivers/char/drm/drmP.h Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/drmP.h Sat Nov 18 21:11:39 2000 @@ -510,19 +510,6 @@ unsigned long base; int agp_mtrr; } drm_agp_head_t; - -typedef struct { - void (*free_memory)(agp_memory *); - agp_memory *(*allocate_memory)(size_t, u32); - int (*bind_memory)(agp_memory *, off_t); - int (*unbind_memory)(agp_memory *); - void (*enable)(u32); - int (*acquire)(void); - void (*release)(void); - void (*copy_info)(agp_kern_info *); -} drm_agp_func_t; - -extern drm_agp_func_t drm_agp; #endif typedef struct drm_sigdata { @@ -824,6 +811,7 @@ extern void drm_agp_uninit(void); extern int drm_agp_acquire(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern void _drm_agp_release(void); extern int drm_agp_release(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); extern int drm_agp_enable(struct inode *inode, struct file *filp, @@ -838,6 +826,10 @@ unsigned int cmd, unsigned long arg); extern int drm_agp_bind(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +extern agp_memory *drm_agp_allocate_memory(size_t pages, u32 type); +extern int drm_agp_free_memory(agp_memory *handle); +extern int drm_agp_bind_memory(agp_memory *handle, off_t start); +extern int drm_agp_unbind_memory(agp_memory *handle); #endif #endif #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/ffb_drv.c linux/drivers/char/drm/ffb_drv.c --- v2.4.0-test10/linux/drivers/char/drm/ffb_drv.c Thu Aug 10 12:43:12 2000 +++ linux/drivers/char/drm/ffb_drv.c Sun Nov 12 20:37:16 2000 @@ -1,4 +1,4 @@ -/* $Id: ffb_drv.c,v 1.6 2000/08/10 05:26:23 davem Exp $ +/* $Id: ffb_drv.c,v 1.7 2000/11/12 10:01:41 davem Exp $ * ffb_drv.c: Creator/Creator3D direct rendering driver. * * Copyright (C) 2000 David S. Miller (davem@redhat.com) @@ -244,7 +244,7 @@ }; } -static int ffb_init_one(int prom_node, int instance) +static int __init ffb_init_one(int prom_node, int instance) { struct linux_prom64_registers regs[2*PROMREG_MAX]; drm_device_t *dev; @@ -305,7 +305,7 @@ return 0; } -static int ffb_init_dev_table(void) +static int __init ffb_init_dev_table(void) { int root, node; int total = 0; @@ -324,7 +324,7 @@ return 0; } -int ffb_init(void) +int __init ffb_init(void) { int root, node, instance, ret; @@ -345,7 +345,7 @@ return 0; } -void ffb_cleanup(void) +void __exit ffb_cleanup(void) { int instance; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/gamma_drv.c linux/drivers/char/drm/gamma_drv.c --- v2.4.0-test10/linux/drivers/char/drm/gamma_drv.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/gamma_drv.c Sat Nov 11 18:34:38 2000 @@ -339,7 +339,7 @@ /* gamma_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -static int gamma_init(void) +static int __init gamma_init(void) { int retcode; drm_device_t *dev = &gamma_device; @@ -380,7 +380,7 @@ /* gamma_cleanup is called via cleanup_module at module unload time. */ -static void gamma_cleanup(void) +static void __exit gamma_cleanup(void) { drm_device_t *dev = &gamma_device; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/i810_drv.c linux/drivers/char/drm/i810_drv.c --- v2.4.0-test10/linux/drivers/char/drm/i810_drv.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/i810_drv.c Thu Nov 16 14:05:49 2000 @@ -255,8 +255,7 @@ } dev->agp->memory = NULL; - if (dev->agp->acquired && drm_agp.release) - (*drm_agp.release)(); + if (dev->agp->acquired) _drm_agp_release(); dev->agp->acquired = 0; dev->agp->enabled = 0; @@ -338,7 +337,7 @@ /* i810_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -static int i810_init(void) +static int __init i810_init(void) { int retcode; drm_device_t *dev = &i810_device; @@ -397,7 +396,7 @@ /* i810_cleanup is called via cleanup_module at module unload time. */ -static void i810_cleanup(void) +static void __exit i810_cleanup(void) { drm_device_t *dev = &i810_device; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/memory.c linux/drivers/char/drm/memory.c --- v2.4.0-test10/linux/drivers/char/drm/memory.c Tue Aug 8 09:27:34 2000 +++ linux/drivers/char/drm/memory.c Thu Nov 16 14:05:49 2000 @@ -352,16 +352,13 @@ return NULL; } - if (drm_agp.allocate_memory) { - if ((handle = (*drm_agp.allocate_memory)(pages, - type))) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; - drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated - += pages << PAGE_SHIFT; - spin_unlock(&drm_mem_lock); - return handle; - } + if ((handle = drm_agp_allocate_memory(pages, type))) { + spin_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; + drm_mem_stats[DRM_MEM_TOTALAGP].bytes_allocated + += pages << PAGE_SHIFT; + spin_unlock(&drm_mem_lock); + return handle; } spin_lock(&drm_mem_lock); ++drm_mem_stats[DRM_MEM_TOTALAGP].fail_count; @@ -381,8 +378,7 @@ return retval;; } - if (drm_agp.free_memory) { - (*drm_agp.free_memory)(handle); + if (drm_agp_free_memory(handle)) { spin_lock(&drm_mem_lock); free_count = ++drm_mem_stats[DRM_MEM_TOTALAGP].free_count; alloc_count = drm_mem_stats[DRM_MEM_TOTALAGP].succeed_count; @@ -403,24 +399,19 @@ { int retcode = -EINVAL; - DRM_DEBUG("drm_bind_agp called\n"); if (!handle) { DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, "Attempt to bind NULL AGP handle\n"); return retcode; } - DRM_DEBUG("drm_agp.bind_memory : %p\n", drm_agp.bind_memory); - if (drm_agp.bind_memory) { - if (!(retcode = (*drm_agp.bind_memory)(handle, start))) { - spin_lock(&drm_mem_lock); - ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; - drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated - += handle->page_count << PAGE_SHIFT; - spin_unlock(&drm_mem_lock); - DRM_DEBUG("drm_agp.bind_memory: retcode %d\n", retcode); - return retcode; - } + if (!(retcode = drm_agp_bind_memory(handle, start))) { + spin_lock(&drm_mem_lock); + ++drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; + drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_allocated + += handle->page_count << PAGE_SHIFT; + spin_unlock(&drm_mem_lock); + return retcode; } spin_lock(&drm_mem_lock); ++drm_mem_stats[DRM_MEM_BOUNDAGP].fail_count; @@ -440,20 +431,17 @@ return retcode; } - if (drm_agp.unbind_memory) { - int c = handle->page_count; - if ((retcode = (*drm_agp.unbind_memory)(handle))) - return retcode; - spin_lock(&drm_mem_lock); - free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count; - alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; - drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed += c << PAGE_SHIFT; - spin_unlock(&drm_mem_lock); - if (free_count > alloc_count) { - DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, - "Excess frees: %d frees, %d allocs\n", - free_count, alloc_count); - } + if ((retcode = drm_agp_unbind_memory(handle))) return retcode; + spin_lock(&drm_mem_lock); + free_count = ++drm_mem_stats[DRM_MEM_BOUNDAGP].free_count; + alloc_count = drm_mem_stats[DRM_MEM_BOUNDAGP].succeed_count; + drm_mem_stats[DRM_MEM_BOUNDAGP].bytes_freed + += handle->page_count << PAGE_SHIFT; + spin_unlock(&drm_mem_lock); + if (free_count > alloc_count) { + DRM_MEM_ERROR(DRM_MEM_BOUNDAGP, + "Excess frees: %d frees, %d allocs\n", + free_count, alloc_count); } return retcode; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/mga_drv.c linux/drivers/char/drm/mga_drv.c --- v2.4.0-test10/linux/drivers/char/drm/mga_drv.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/mga_drv.c Thu Nov 16 14:05:49 2000 @@ -255,8 +255,7 @@ } dev->agp->memory = NULL; - if (dev->agp->acquired && drm_agp.release) - (*drm_agp.release)(); + if (dev->agp->acquired) _drm_agp_release(); dev->agp->acquired = 0; dev->agp->enabled = 0; @@ -338,7 +337,7 @@ /* mga_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -static int mga_init(void) +static int __init mga_init(void) { int retcode; drm_device_t *dev = &mga_device; @@ -398,7 +397,7 @@ /* mga_cleanup is called via cleanup_module at module unload time. */ -static void mga_cleanup(void) +static void __exit mga_cleanup(void) { drm_device_t *dev = &mga_device; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/mga_state.c linux/drivers/char/drm/mga_state.c --- v2.4.0-test10/linux/drivers/char/drm/mga_state.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/mga_state.c Thu Nov 16 14:05:49 2000 @@ -287,7 +287,7 @@ PRIMOUTREG(MGAREG_TEXCTL2, 0x80 | 0x00008000); PRIMOUTREG(MGAREG_LEN + MGAREG_MGA_EXEC, 0); - PRIMOUTREG(MGAREG_DMAPAD, 0); + PRIMOUTREG(MGAREG_TEXCTL2, 0x00008000); PRIMOUTREG(MGAREG_DMAPAD, 0); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/r128_drm.h linux/drivers/char/drm/r128_drm.h --- v2.4.0-test10/linux/drivers/char/drm/r128_drm.h Fri Jul 21 12:56:44 2000 +++ linux/drivers/char/drm/r128_drm.h Thu Nov 16 14:05:49 2000 @@ -57,9 +57,9 @@ } drm_r128_init_t; typedef struct drm_r128_packet { - unsigned long *buffer; - int count; - int flags; + unsigned int *buffer; + int count; + int flags; } drm_r128_packet_t; typedef enum drm_r128_prim { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/r128_drv.c linux/drivers/char/drm/r128_drv.c --- v2.4.0-test10/linux/drivers/char/drm/r128_drv.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/r128_drv.c Thu Nov 16 14:05:49 2000 @@ -252,8 +252,7 @@ } dev->agp->memory = NULL; - if (dev->agp->acquired && drm_agp.release) - (*drm_agp.release)(); + if (dev->agp->acquired) _drm_agp_release(); dev->agp->acquired = 0; dev->agp->enabled = 0; @@ -323,7 +322,7 @@ /* r128_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -static int r128_init(void) +static int __init r128_init(void) { int retcode; drm_device_t *dev = &r128_device; @@ -387,7 +386,7 @@ /* r128_cleanup is called via cleanup_module at module unload time. */ -static void r128_cleanup(void) +static void __exit r128_cleanup(void) { drm_device_t *dev = &r128_device; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/drm/tdfx_drv.c linux/drivers/char/drm/tdfx_drv.c --- v2.4.0-test10/linux/drivers/char/drm/tdfx_drv.c Sun Oct 8 10:50:16 2000 +++ linux/drivers/char/drm/tdfx_drv.c Thu Nov 16 14:05:49 2000 @@ -235,7 +235,7 @@ drm_free(temp, sizeof(*temp), DRM_MEM_AGPLISTS); temp = temp_next; } - if (dev->agp->acquired) (*drm_agp.release)(); + if (dev->agp->acquired) _drm_agp_release(); } #endif /* Clear vma list (only built for debugging) */ @@ -298,7 +298,7 @@ /* tdfx_init is called via init_module at module load time, or via * linux/init/main.c (this is not currently supported). */ -static int tdfx_init(void) +static int __init tdfx_init(void) { int retcode; drm_device_t *dev = &tdfx_device; @@ -346,7 +346,7 @@ /* tdfx_cleanup is called via cleanup_module at module unload time. */ -static void tdfx_cleanup(void) +static void __exit tdfx_cleanup(void) { drm_device_t *dev = &tdfx_device; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/ftape/lowlevel/ftape-ctl.c linux/drivers/char/ftape/lowlevel/ftape-ctl.c --- v2.4.0-test10/linux/drivers/char/ftape/lowlevel/ftape-ctl.c Sun Sep 3 11:47:19 2000 +++ linux/drivers/char/ftape/lowlevel/ftape-ctl.c Tue Nov 7 11:09:19 2000 @@ -40,6 +40,9 @@ #endif #include +/* ease porting between pre-2.4.x and later kernels */ +#define vma_get_pgoff(v) ((v)->vm_pgoff) + #include "../lowlevel/ftape-tracing.h" #include "../lowlevel/ftape-io.h" #include "../lowlevel/ftape-ctl.h" @@ -701,23 +704,23 @@ if (ft_failure) { TRACE_EXIT -ENODEV; } - if ((vma_get_flags(vma) & (VM_READ|VM_WRITE)) == 0) { + if (!(vma->vm_flags & (VM_READ|VM_WRITE))) { TRACE_ABORT(-EINVAL, ft_t_err, "Undefined mmap() access"); } if (vma_get_pgoff(vma) != 0) { TRACE_ABORT(-EINVAL, ft_t_err, "page offset must be 0"); } - if ((vma_get_end (vma) - vma_get_start (vma)) % FT_BUFF_SIZE != 0) { + if ((vma->vm_end - vma->vm_start) % FT_BUFF_SIZE != 0) { TRACE_ABORT(-EINVAL, ft_t_err, "size = %ld, should be a multiple of %d", - vma_get_end (vma) - vma_get_start (vma), + vma->vm_end - vma->vm_start, FT_BUFF_SIZE); } - num_buffers = (vma_get_end (vma) - vma_get_start (vma)) / FT_BUFF_SIZE; + num_buffers = (vma->vm_end - vma->vm_start) / FT_BUFF_SIZE; if (num_buffers > ft_nr_buffers) { TRACE_ABORT(-EINVAL, ft_t_err, "size = %ld, should be less than %d", - vma_get_end (vma) - vma_get_start (vma), + vma->vm_end - vma->vm_start, ft_nr_buffers * FT_BUFF_SIZE); } if (ft_driver_state != idle) { @@ -728,15 +731,15 @@ ftape_reset_buffer(); } for (i = 0; i < num_buffers; i++) { - TRACE_CATCH(remap_page_range(vma_get_start (vma) + + TRACE_CATCH(remap_page_range(vma->vm_start + i * FT_BUFF_SIZE, - virt_to_phys(ft_buffer[i]->address), + virt_to_phys(ft_buffer[i]->address), FT_BUFF_SIZE, - vma_get_page_prot (vma)), + vma->vm_page_prot), _res = -EAGAIN); TRACE(ft_t_noise, "remapped dma buffer @ %p to location @ %p", ft_buffer[i]->address, - (void *)(vma_get_start(vma) + i * FT_BUFF_SIZE)); + (void *)(vma->vm_start + i * FT_BUFF_SIZE)); } for (i = 0; i < num_buffers; i++) { memset(ft_buffer[i]->address, 0xAA, FT_BUFF_SIZE); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c --- v2.4.0-test10/linux/drivers/char/generic_serial.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/generic_serial.c Thu Nov 16 12:51:27 2000 @@ -19,21 +19,21 @@ * best to be responsive. -- REW * */ +#include +#include #include #include #include +#include #include #include -#include -#include -#include #define DEBUG static char * tmp_buf; static DECLARE_MUTEX(tmp_buf_sem); -int gs_debug; +static int gs_debug; #ifdef DEBUG @@ -57,30 +57,7 @@ #define RS_EVENT_WRITE_WAKEUP 1 -#ifdef MODULE MODULE_PARM(gs_debug, "i"); -#endif - -#ifdef DEBUG -static void my_hd (unsigned char *addr, int len) -{ - int i, j, ch; - - for (i=0;i 0x7f)?'.':ch)); - } - printk ("\n"); - } -} -#else -#define my_hd(addr,len) -#endif void gs_put_char(struct tty_struct * tty, unsigned char ch) @@ -1083,15 +1060,20 @@ copy_to_user(sp, &sio, sizeof(struct serial_struct)); } +EXPORT_SYMBOL(gs_put_char); +EXPORT_SYMBOL(gs_write); +EXPORT_SYMBOL(gs_write_room); +EXPORT_SYMBOL(gs_chars_in_buffer); +EXPORT_SYMBOL(gs_flush_buffer); +EXPORT_SYMBOL(gs_flush_chars); +EXPORT_SYMBOL(gs_stop); +EXPORT_SYMBOL(gs_start); +EXPORT_SYMBOL(gs_hangup); +EXPORT_SYMBOL(gs_do_softint); +EXPORT_SYMBOL(block_til_ready); +EXPORT_SYMBOL(gs_close); +EXPORT_SYMBOL(gs_set_termios); +EXPORT_SYMBOL(gs_init_port); +EXPORT_SYMBOL(gs_setserial); +EXPORT_SYMBOL(gs_getserial); -#ifdef MODULE -int init_module (void) -{ - return 0; -} - -int cleanup_module (void) -{ - return 0; -} -#endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c --- v2.4.0-test10/linux/drivers/char/joystick/adi.c Thu Jun 22 06:59:58 2000 +++ linux/drivers/char/joystick/adi.c Fri Nov 17 16:52:23 2000 @@ -418,7 +418,7 @@ adi->dev.private = port; adi->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); - for (i = 0; i < adi->axes10 + adi->axes8 + adi->hats * 2; i++) + for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++) set_bit(adi->abs[i], &adi->dev.absbit); for (i = 0; i < adi->buttons; i++) @@ -431,7 +431,7 @@ if (!adi->length) return; - for (i = 0; i < adi->axes10 + adi->axes8 + adi->hats * 2; i++) { + for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad > 0)) * 2; i++) { t = adi->abs[i]; x = adi->dev.abs[t]; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/joystick/analog.c linux/drivers/char/joystick/analog.c --- v2.4.0-test10/linux/drivers/char/joystick/analog.c Thu Jun 22 06:59:58 2000 +++ linux/drivers/char/joystick/analog.c Tue Nov 14 13:16:33 2000 @@ -41,17 +41,18 @@ #include MODULE_AUTHOR("Vojtech Pavlik "); +MODULE_DESCRIPTION("Analog joystick and gamepad driver for Linux"); /* * Option parsing. */ -MODULE_PARM(js,"1-16s"); - #define ANALOG_PORTS 16 static char *js[ANALOG_PORTS]; static int analog_options[ANALOG_PORTS]; +MODULE_PARM(js, "1-" __MODULE_STRING(ANALOG_PORTS) "s"); +MODULE_PARM_DESC(js, "Analog joystick options"); /* * Times, feature definitions. diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/joystick/iforce.c linux/drivers/char/joystick/iforce.c --- v2.4.0-test10/linux/drivers/char/joystick/iforce.c Tue Aug 22 11:41:14 2000 +++ linux/drivers/char/joystick/iforce.c Sat Nov 11 18:48:18 2000 @@ -54,6 +54,7 @@ struct iforce { signed char data[IFORCE_MAX_LENGTH]; + struct usb_device *usbdev; struct input_dev dev; struct urb irq; int open; @@ -113,9 +114,11 @@ { struct iforce *iforce = dev->private; - if (dev->idbus == BUS_USB && !iforce->open++) + if (dev->idbus == BUS_USB && !iforce->open++) { + iforce->irq.dev = iforce->usbdev; if (usb_submit_urb(&iforce->irq)) return -EIO; + } return 0; } @@ -177,15 +180,12 @@ iforce_process_packet(&iforce->dev, iforce->data[0], 8, iforce->data + 1); } -static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum) +static void *iforce_usb_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_endpoint_descriptor *endpoint; struct iforce *iforce; - if (dev->descriptor.idVendor != USB_VENDOR_ID_LOGITECH || - dev->descriptor.idProduct != USB_DEVICE_ID_LOGITECH_WMFORCE) - return NULL; - endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0; if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return NULL; @@ -216,10 +216,21 @@ kfree(iforce); } +static struct usb_device_id iforce_usb_ids [] = { + { + idVendor: USB_VENDOR_ID_LOGITECH, + idProduct: USB_DEVICE_ID_LOGITECH_WMFORCE + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, iforce_usb_ids); + static struct usb_driver iforce_usb_driver = { name: "iforce", probe: iforce_usb_probe, disconnect: iforce_usb_disconnect, + id_table: iforce_usb_ids, }; #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c --- v2.4.0-test10/linux/drivers/char/joystick/ns558.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/joystick/ns558.c Fri Nov 17 16:52:23 2000 @@ -58,7 +58,7 @@ }; static struct ns558 *ns558; -static int have_pci_devices; +static int ns558_pci; /* * ns558_isa_probe() tries to find an isa gameport at the @@ -188,12 +188,10 @@ } memset(port, 0, sizeof(struct ns558)); - port->next = ns558; port->type = NS558_PCI; port->gameport.io = ioport; port->gameport.size = iolen; port->dev = pdev; - ns558 = port; pdev->driver_data = port; @@ -316,9 +314,7 @@ * it is the least-invasive probe. */ - i = pci_module_init(&ns558_pci_driver); - if (i == 0) - have_pci_devices = 1; + ns558_pci = !pci_module_init(&ns558_pci_driver); /* * Probe for ISA ports. @@ -339,12 +335,12 @@ } #endif - return ns558 ? 0 : -ENODEV; + return (ns558 || ns558_pci) ? 0 : -ENODEV; } void __exit ns558_exit(void) { - struct ns558 *port = ns558; + struct ns558 *next, *port = ns558; while (port) { gameport_unregister_port(&port->gameport); @@ -365,10 +361,12 @@ break; } - port = port->next; + next = port->next; + kfree(port); + port = next; } - if (have_pci_devices) + if (ns558_pci) pci_unregister_driver(&ns558_pci_driver); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c --- v2.4.0-test10/linux/drivers/char/joystick/sidewinder.c Mon Aug 14 13:55:01 2000 +++ linux/drivers/char/joystick/sidewinder.c Fri Nov 17 16:52:23 2000 @@ -102,7 +102,7 @@ { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT }, { BTN_TRIGGER, BTN_THUMB, BTN_TOP, BTN_TOP2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4, BTN_SELECT }, { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START, BTN_MODE, BTN_SELECT }, - { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3 }}; + { BTN_TRIGGER, BTN_TOP, BTN_THUMB, BTN_THUMB2, BTN_BASE, BTN_BASE2, BTN_BASE3, BTN_BASE4 }}; static struct { int x; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/mem.c linux/drivers/char/mem.c --- v2.4.0-test10/linux/drivers/char/mem.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/mem.c Sun Nov 12 21:55:50 2000 @@ -179,8 +179,11 @@ * caching for the high addresses through the KEN pin, but * we maintain the tradition of paranoia in this code. */ - return !(boot_cpu_data.x86_capability & X86_FEATURE_MTRR) - && addr >= __pa(high_memory); + return !( test_bit(X86_FEATURE_MTRR, &boot_cpu_data.x86_capability) || + test_bit(X86_FEATURE_K6_MTRR, &boot_cpu_data.x86_capability) || + test_bit(X86_FEATURE_CYRIX_ARR, &boot_cpu_data.x86_capability) || + test_bit(X86_FEATURE_CENTAUR_MCR, &boot_cpu_data.x86_capability) ) + && addr >= __pa(high_memory); #else return addr >= __pa(high_memory); #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/mxser.c linux/drivers/char/mxser.c --- v2.4.0-test10/linux/drivers/char/mxser.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/mxser.c Sun Nov 12 20:38:38 2000 @@ -120,7 +120,7 @@ #define CI104J_ASIC_ID 5 enum { - MXSER_BOARD_C168_ISA = 1, + MXSER_BOARD_C168_ISA = 0, MXSER_BOARD_C104_ISA, MXSER_BOARD_CI104J, MXSER_BOARD_C168_PCI, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c --- v2.4.0-test10/linux/drivers/char/n_hdlc.c Thu Jul 6 19:36:20 2000 +++ linux/drivers/char/n_hdlc.c Tue Nov 7 10:36:57 2000 @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * ==FILEDATE 20000706== + * $Id: n_hdlc.c,v 3.2 2000/11/06 22:34:38 paul Exp $ * * This code is released under the GNU General Public License (GPL) * @@ -78,11 +78,12 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "1.16" +#define HDLC_VERSION "3.2" #include #include #include +#include #include #include #include @@ -93,14 +94,7 @@ #undef VERSION #define VERSION(major,minor,patch) (((((major)<<8)+(minor))<<8)+(patch)) -#if LINUX_VERSION_CODE < VERSION(2,1,14) -#include -#endif - -#if LINUX_VERSION_CODE >= VERSION(2,1,23) #include -#endif - #include #include #include @@ -118,86 +112,16 @@ #include #endif -#if LINUX_VERSION_CODE < VERSION(2,3,0) -typedef struct wait_queue *wait_queue_head_t; -#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL} -#define init_waitqueue_head(head) *(head) = NULL -#define set_current_state(a) current->state = (a) -#endif - -#if LINUX_VERSION_CODE >= VERSION(2,1,4) #include #define GET_USER(error,value,addr) error = get_user(value,addr) #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 #define PUT_USER(error,value,addr) error = put_user(value,addr) #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 -#if LINUX_VERSION_CODE >= VERSION(2,1,5) #include -#endif - -#else /* 2.0.x and 2.1.x before 2.1.4 */ - -#define GET_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ - if (error == 0) \ - value = get_user(addr); \ -} while (0) - -#define COPY_FROM_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_READ, (void *) src, size); \ - if (error == 0) \ - memcpy_fromfs (dest, src, size); \ -} while (0) - -#define PUT_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ - if (error == 0) \ - put_user (value, addr); \ -} while (0) - -#define COPY_TO_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) dest, size); \ - if (error == 0) \ - memcpy_tofs (dest, src, size); \ -} while (0) - -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,0) -#define __init -typedef int spinlock_t; -#define spin_lock_init(a) -#define spin_lock_irqsave(a,b) {save_flags((b));cli();} -#define spin_unlock_irqrestore(a,b) {restore_flags((b));} -#define spin_lock(a) -#define spin_unlock(a) -#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();} -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,37) -#define test_and_set_bit(nr, addr) set_bit(nr, addr) -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,57) -#define signal_pending(p) ((p)->signal & ~(p)->blocked) -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,25) -#define net_device_stats enet_statistics -#endif -#if LINUX_VERSION_CODE < VERSION(2,1,60) -typedef int rw_ret_t; -typedef unsigned int rw_count_t; -#else typedef ssize_t rw_ret_t; typedef size_t rw_count_t; -#endif /* * Buffers for individual HDLC frames @@ -261,10 +185,9 @@ static struct n_hdlc *n_hdlc_alloc (void); -#if LINUX_VERSION_CODE >= VERSION(2,1,19) MODULE_PARM(debuglevel, "i"); MODULE_PARM(maxframe, "i"); -#endif + /* debug level can be set by insmod for debugging purposes */ #define DEBUG_LEVEL_INFO 1 @@ -281,13 +204,8 @@ struct file *, const __u8 *, rw_count_t); static int n_hdlc_tty_ioctl(struct tty_struct *, struct file *, unsigned int, unsigned long); -#if LINUX_VERSION_CODE < VERSION(2,1,23) -static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode, - struct file *filp, int sel_type, select_table * wait); -#else static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, struct file *filp, poll_table * wait); -#endif static int n_hdlc_tty_open (struct tty_struct *); static void n_hdlc_tty_close (struct tty_struct *); static int n_hdlc_tty_room (struct tty_struct *tty); @@ -660,11 +578,8 @@ wake_up_interruptible (&n_hdlc->read_wait); wake_up_interruptible (&n_hdlc->poll_wait); if (n_hdlc->tty->fasync != NULL) -#if LINUX_VERSION_CODE < VERSION(2,3,0) - kill_fasync (n_hdlc->tty->fasync, SIGIO); -#else kill_fasync (&n_hdlc->tty->fasync, SIGIO, POLL_IN); -#endif + } /* end of n_hdlc_tty_receive() */ /* n_hdlc_tty_read() @@ -893,73 +808,6 @@ } /* end of n_hdlc_tty_ioctl() */ -#if LINUX_VERSION_CODE < VERSION(2,1,23) -/* n_hdlc_tty_select() - * - * Device select method. Determine if operation requires - * blocking and if so put appropriate wait queue in select - * table and return 0, otherwise return 1. - * - * Arguments: - * - * tty pointer to tty device instance data - * inode pointer to inode for device - * filp pointer to file object - * sel_type identified the select type (read/write/exception) - * wait select table for adding wait queue if appropriate - * - * Return Value: - * - * 1 if no need to block on operation - * 0 if must block and wait queue added to select table - */ -static int n_hdlc_tty_select (struct tty_struct *tty, struct inode *inode, - struct file *filp, int sel_type, select_table * wait) -{ - struct n_hdlc *n_hdlc = tty2n_hdlc(tty); - int result = 1; - - if (debuglevel >= DEBUG_LEVEL_INFO) - printk("%s(%d)n_hdlc_tty_select() called\n",__FILE__,__LINE__); - - /* Verify the status of the device */ - if (!n_hdlc) - return -EBADF; - - if (n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty) - return -EBADF; - - switch (sel_type) { - case SEL_IN: - if (n_hdlc->rx_buf_list.head) - break; - - case SEL_EX: /* Exceptions or read errors */ - /* Is this a pty link and the remote disconnected? */ - if (tty->flags & (1 << TTY_OTHER_CLOSED)) - break; - - /* Is this a local link and the modem disconnected? */ - if (tty_hung_up_p (filp)) - break; - - select_wait (&n_hdlc->read_wait, wait); - result = 0; - break; - - /* Write mode. A write is allowed if there is no current transmission */ - case SEL_OUT: - if (!n_hdlc->tx_free_buf_list.head) { - select_wait (&n_hdlc->write_wait, wait); - result = 0; - } - break; - } - return result; -} /* end of n_hdlc_tty_select() */ - -#else /* 2.1.23 or later */ - /* n_hdlc_tty_poll() * * TTY callback for poll system call. Determine which @@ -988,11 +836,8 @@ if (n_hdlc && n_hdlc->magic == HDLC_MAGIC && tty == n_hdlc->tty) { /* queue current process into any wait queue that */ /* may awaken in the future (read and write) */ -#if LINUX_VERSION_CODE < VERSION(2,1,89) - poll_wait(&n_hdlc->poll_wait, wait); -#else poll_wait(filp, &n_hdlc->poll_wait, wait); -#endif + /* set bits for operations that wont block */ if(n_hdlc->rx_buf_list.head) mask |= POLLIN | POLLRDNORM; /* readable */ @@ -1006,8 +851,6 @@ return mask; } /* end of n_hdlc_tty_poll() */ -#endif - /* n_hdlc_alloc() * * Allocate an n_hdlc instance data structure @@ -1135,14 +978,7 @@ } /* end of n_hdlc_buf_get() */ -/* init_module() - * - * called when module is loading to register line discipline - * - * Arguments: None - * Return Value: 0 if success, otherwise error code - */ -int init_module(void) +static int __init n_hdlc_init(void) { static struct tty_ldisc n_hdlc_ldisc; int status; @@ -1160,19 +996,13 @@ memset(&n_hdlc_ldisc, 0, sizeof (n_hdlc_ldisc)); n_hdlc_ldisc.magic = TTY_LDISC_MAGIC; -#if LINUX_VERSION_CODE >= VERSION(2,1,28) n_hdlc_ldisc.name = "hdlc"; -#endif n_hdlc_ldisc.open = n_hdlc_tty_open; n_hdlc_ldisc.close = n_hdlc_tty_close; n_hdlc_ldisc.read = n_hdlc_tty_read; n_hdlc_ldisc.write = n_hdlc_tty_write; n_hdlc_ldisc.ioctl = n_hdlc_tty_ioctl; -#if LINUX_VERSION_CODE < VERSION(2,1,23) - n_hdlc_ldisc.select = n_hdlc_tty_select; -#else n_hdlc_ldisc.poll = n_hdlc_tty_poll; -#endif n_hdlc_ldisc.receive_room = n_hdlc_tty_room; n_hdlc_ldisc.receive_buf = n_hdlc_tty_receive; n_hdlc_ldisc.write_wakeup = n_hdlc_tty_wakeup; @@ -1189,14 +1019,7 @@ } /* end of init_module() */ -/* cleanup_module() - * - * called when module is unloading to unregister line discipline - * - * Arguments: None - * Return Value: None - */ -void cleanup_module(void) +static void __exit n_hdlc_exit(void) { int status; /* Release tty registration of line discipline */ @@ -1205,3 +1028,6 @@ else printk("N_HDLC: line discipline unregistered\n"); } + +module_init(n_hdlc_init); +module_exit(n_hdlc_exit); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/random.c linux/drivers/char/random.c --- v2.4.0-test10/linux/drivers/char/random.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/random.c Sun Nov 12 21:55:50 2000 @@ -710,7 +710,7 @@ int entropy = 0; #if defined (__i386__) - if (boot_cpu_data.x86_capability & X86_FEATURE_TSC) { + if ( test_bit(X86_FEATURE_TSC, &boot_cpu_data.x86_capability) ) { __u32 high; __asm__(".byte 0x0f,0x31" :"=a" (time), "=d" (high)); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c --- v2.4.0-test10/linux/drivers/char/rio/rio_linux.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/rio/rio_linux.c Thu Nov 16 12:51:27 2000 @@ -1103,8 +1103,6 @@ #define rio_init init_module #endif -extern int gs_debug; - int rio_init(void) { int found = 0; @@ -1129,7 +1127,6 @@ func_enter(); rio_dprintk (RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug); - gs_debug = rio_debug >> 24; if (abs ((long) (&rio_debug) - rio_debug) < 0x10000) { printk (KERN_WARNING "rio: rio_debug is an address, instead of a value. " diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/rtc.c linux/drivers/char/rtc.c --- v2.4.0-test10/linux/drivers/char/rtc.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/rtc.c Tue Nov 7 11:08:09 2000 @@ -634,7 +634,7 @@ } } } - printk("rtc_init: no PC rtc found\n"); + printk(KERN_ERR "rtc_init: no PC rtc found\n"); return -EIO; found: @@ -650,7 +650,7 @@ * Standard way for sparc to print irq's is to use * __irq_itoa(). I think for EBus it's ok to use %d. */ - printk("rtc: cannot register IRQ %d\n", rtc_irq); + printk(KERN_ERR "rtc: cannot register IRQ %d\n", rtc_irq); return -EIO; } #else @@ -705,7 +705,7 @@ guess = "Digital DECstation"; } if (guess) - printk("rtc: %s epoch (%lu) detected\n", guess, epoch); + printk(KERN_INFO "rtc: %s epoch (%lu) detected\n", guess, epoch); #endif #if RTC_IRQ init_timer(&rtc_irq_timer); @@ -772,7 +772,7 @@ spin_unlock_irq(&rtc_lock); - printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", freq); + printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); /* Now we have new data */ wake_up_interruptible(&rtc_wait); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/sx.c linux/drivers/char/sx.c --- v2.4.0-test10/linux/drivers/char/sx.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/sx.c Thu Nov 16 12:51:27 2000 @@ -1756,16 +1756,12 @@ sx_initialized++; break; case SXIO_SETDEBUG: + case SXIO_SETGSDEBUG: sx_debug = arg; break; case SXIO_GETDEBUG: - rc = sx_debug; - break; - case SXIO_SETGSDEBUG: - gs_debug = arg; - break; case SXIO_GETGSDEBUG: - rc = gs_debug; + rc = sx_debug; break; case SXIO_GETNPORTS: rc = sx_nports; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/char/synclink.c linux/drivers/char/synclink.c --- v2.4.0-test10/linux/drivers/char/synclink.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/char/synclink.c Tue Nov 7 10:36:42 2000 @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * ==FILEDATE 20000707== + * $Id: synclink.c,v 3.2 2000/11/06 22:34:38 paul Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -82,13 +82,9 @@ #include -#if LINUX_VERSION_CODE >= VERSION(2,1,0) #include #include #include -#else -#include -#endif #include #include @@ -102,98 +98,21 @@ #include #include -#if LINUX_VERSION_CODE < VERSION(2,3,0) -typedef struct wait_queue *wait_queue_head_t; -#define DECLARE_WAITQUEUE(name,task) struct wait_queue (name) = {(task),NULL} -#define init_waitqueue_head(head) *(head) = NULL -#define DECLARE_MUTEX(name) struct semaphore (name) = MUTEX -#define set_current_state(a) current->state = (a) -#endif - #ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE #define CONFIG_SYNCLINK_SYNCPPP 1 #endif #ifdef CONFIG_SYNCLINK_SYNCPPP -#if LINUX_VERSION_CODE < VERSION(2,3,43) -#include "../net/syncppp.h" -#define net_device device -#define netif_stop_queue(a) (a)->tbusy = 1 -#define netif_start_queue(a) (a)->tbusy = 0 -#define netif_wake_queue(a) (a)->tbusy = 0; mark_bh(NET_BH) -#define netif_queue_stopped(a) ((a)->tbusy) -#else #include "../net/wan/syncppp.h" #endif -#endif -#if LINUX_VERSION_CODE >= VERSION(2,1,4) #include #define GET_USER(error,value,addr) error = get_user(value,addr) #define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0 #define PUT_USER(error,value,addr) error = put_user(value,addr) #define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0 -#if LINUX_VERSION_CODE >= VERSION(2,1,5) #include -#endif - -#else /* 2.0.x and 2.1.x before 2.1.4 */ - -#define GET_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_READ, (void *) addr, sizeof (value)); \ - if (error == 0) \ - value = get_user(addr); \ -} while (0) - -#define COPY_FROM_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_READ, (void *) src, size); \ - if (error == 0) \ - memcpy_fromfs (dest, src, size); \ -} while (0) - -#define PUT_USER(error,value,addr) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) addr, sizeof (value)); \ - if (error == 0) \ - put_user (value, addr); \ -} while (0) - -#define COPY_TO_USER(error,dest,src,size) \ -do { \ - error = verify_area (VERIFY_WRITE, (void *) dest, size); \ - if (error == 0) \ - memcpy_tofs (dest, src, size); \ -} while (0) - -#endif - -#if LINUX_VERSION_CODE < VERSION(2,1,0) -/* - * This is used to figure out the divisor speeds and the timeouts - */ -static int baud_table[] = { - 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, - 9600, 19200, 38400, 57600, 115200, 230400, 460800, 0 }; - -#define __init -#define ioremap(a,b) vremap((a),(b)) -#define iounmap(a) vfree((a)) -#define SERIAL_TYPE_NORMAL 1 -#define SERIAL_TYPE_CALLOUT 2 -typedef int spinlock_t; -#define spin_lock_init(a) -#define spin_lock_irqsave(a,b) {save_flags((b));cli();} -#define spin_unlock_irqrestore(a,b) {restore_flags((b));} -#define spin_lock(a) -#define spin_unlock(a) -#define schedule_timeout(a){current->timeout = jiffies + (a); schedule();} -#define signal_pending(a) ((a)->signal & ~(a)->blocked) -#endif - - #include "linux/synclink.h" @@ -365,10 +284,12 @@ u32 last_mem_alloc; unsigned char* memory_base; /* shared memory address (PCI only) */ u32 phys_memory_base; + int shared_mem_requested; unsigned char* lcr_base; /* local config registers (PCI only) */ u32 phys_lcr_base; u32 lcr_offset; + int lcr_mem_requested; u32 misc_ctrl_value; char flag_buf[MAX_ASYNC_BUFFER_SIZE]; @@ -389,10 +310,8 @@ char netname[10]; struct net_device *netdev; struct net_device_stats netstats; -#if LINUX_VERSION_CODE >= VERSION(2,2,16) struct net_device netdevice; #endif -#endif }; #define MGSL_MAGIC 0x5401 @@ -845,7 +764,7 @@ void mgsl_release_resources(struct mgsl_struct *info); void mgsl_add_device(struct mgsl_struct *info); struct mgsl_struct* mgsl_allocate_device(void); -int mgsl_enumerate_devices(void); +int mgsl_enum_isa_devices(void); /* * DMA buffer manupulation functions. @@ -952,7 +871,6 @@ static int maxframe[MAX_TOTAL_DEVICES] = {0,}; static int dosyncppp[MAX_TOTAL_DEVICES] = {0,}; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) MODULE_PARM(break_on_load,"i"); MODULE_PARM(ttymajor,"i"); MODULE_PARM(cuamajor,"i"); @@ -962,10 +880,26 @@ MODULE_PARM(debug_level,"i"); MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i"); -#endif static char *driver_name = "SyncLink serial driver"; -static char *driver_version = "1.21"; +static char *driver_version = "3.2"; + +static int __init synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent); +static void __exit synclink_remove_one (struct pci_dev *dev); + +static struct pci_device_id synclink_pci_tbl[] __devinitdata = { + { PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* terminate list */ +}; +MODULE_DEVICE_TABLE(pci, synclink_pci_tbl); + +static struct pci_driver synclink_pci_driver = { + name: "synclink", + id_table: synclink_pci_tbl, + probe: synclink_init_one, + remove: synclink_remove_one, +}; static struct tty_driver serial_driver, callout_driver; static int serial_refcount; @@ -977,9 +911,9 @@ static void mgsl_change_params(struct mgsl_struct *info); static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout); -static struct tty_struct **serial_table = NULL; -static struct termios **serial_termios = NULL; -static struct termios **serial_termios_locked = NULL; +static struct tty_struct *serial_table[MAX_TOTAL_DEVICES]; +static struct termios *serial_termios[MAX_TOTAL_DEVICES]; +static struct termios *serial_termios_locked[MAX_TOTAL_DEVICES]; #ifndef MIN #define MIN(a,b) ((a) < (b) ? (a) : (b)) @@ -1591,16 +1525,9 @@ icount->parity,icount->frame,icount->overrun); } - if ( tty->flip.count ) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) + if ( tty->flip.count ) tty_flip_buffer_push(tty); -#else - queue_task(&tty->flip.tqueue, &tq_timer); -#endif - } - - -} /* end of mgsl_isr_receive_data() */ +} /* mgsl_isr_misc() * @@ -1795,11 +1722,7 @@ retval = mgsl_adapter_test(info); if ( retval ) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) if (capable(CAP_SYS_ADMIN) && info->tty) -#else - if (suser() && info->tty) -#endif set_bit(TTY_IO_ERROR, &info->tty->flags); mgsl_release_resources(info); return retval; @@ -1974,21 +1897,8 @@ * allow tty settings to override, otherwise keep the * current data rate. */ - if (info->params.data_rate <= 460800) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) + if (info->params.data_rate <= 460800) info->params.data_rate = tty_get_baud_rate(info->tty); -#else - int i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 4) - info->tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - info->params.data_rate = baud_table[i]; -#endif - } if ( info->params.data_rate ) { info->timeout = (32*HZ*bits_per_char) / @@ -2950,7 +2860,6 @@ } /* end of set_modem_info() */ -#if LINUX_VERSION_CODE >= VERSION(2,1,0) /* mgsl_break() Set or clear transmit break condition * * Arguments: tty pointer to tty instance data @@ -2977,7 +2886,6 @@ spin_unlock_irqrestore(&info->irq_spinlock,flags); } /* end of mgsl_break() */ -#endif /* mgsl_ioctl() Service an IOCTL request * @@ -3100,7 +3008,6 @@ if (error) return error; PUT_USER(error,cnow.dcd, &p_cuser->dcd); if (error) return error; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) PUT_USER(error,cnow.rx, &p_cuser->rx); if (error) return error; PUT_USER(error,cnow.tx, &p_cuser->tx); @@ -3115,7 +3022,6 @@ if (error) return error; PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); if (error) return error; -#endif return 0; default: return -ENOIOCTLCMD; @@ -3596,9 +3502,7 @@ tmp_buf = (unsigned char *) page; } -#if LINUX_VERSION_CODE >= VERSION(2,1,0) info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; -#endif spin_lock_irqsave(&info->netlock, flags); if (info->netcount) { @@ -3985,22 +3889,14 @@ } /* end of mgsl_alloc_buffer_list_memory() */ -/* - * mgsl_free_buffer_list_memory() - * - * Free the common DMA buffer allocated for use as the - * receive and transmit buffer lists. The associated Memory - * Descriptor List (MDL) is also freed. - * +/* Free DMA buffers allocated for use as the + * receive and transmit buffer lists. * Warning: * * The data transfer buffers associated with the buffer list * MUST be freed before freeing the buffer list itself because * the buffer list contains the information necessary to free * the individual buffers! - * - * Arguments: info pointer to device extension - * Return Value: None */ void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) { @@ -4138,67 +4034,61 @@ void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) { if ( info->intermediate_rxbuffer ) - kfree( info->intermediate_rxbuffer ); + kfree(info->intermediate_rxbuffer); info->intermediate_rxbuffer = NULL; } /* end of mgsl_free_intermediate_rxbuffer_memory() */ -/* mgsl_claim_resources() - * - * Claim all resources used by a device - * - * Arguments: info pointer to device instance data - * Return Value: 0 if success, otherwise -ENODEV - */ int mgsl_claim_resources(struct mgsl_struct *info) { - /* claim 16C32 I/O base address */ - - if ( check_region(info->io_base,info->io_addr_size) < 0 ) { + if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) { printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n", - __FILE__,__LINE__,info->device_name, info->io_base ); + __FILE__,__LINE__,info->device_name, info->io_base); return -ENODEV; } - request_region(info->io_base,info->io_addr_size,"synclink.o"); info->io_addr_requested = 1; - /* claim interrupt level */ - if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags, info->device_name, info ) < 0 ) { printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n", __FILE__,__LINE__,info->device_name, info->irq_level ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } info->irq_requested = 1; if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* claim shared memory range */ + if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) { + printk( "%s(%d):mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_memory_base); + goto errout; + } + info->shared_mem_requested = 1; + if (request_mem_region(info->phys_lcr_base,128,"synclink") == NULL) { + printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n", + __FILE__,__LINE__,info->device_name, info->phys_lcr_base); + goto errout; + } + info->lcr_mem_requested = 1; + info->memory_base = ioremap(info->phys_memory_base,0x40000); if (!info->memory_base) { printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } - /* test the shared memory range */ if ( !mgsl_memory_test(info) ) { printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_memory_base ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } - /* claim LCR memory range */ info->lcr_base = ioremap(info->phys_lcr_base,PAGE_SIZE) + info->lcr_offset; if (!info->lcr_base) { printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n", __FILE__,__LINE__,info->device_name, info->phys_lcr_base ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } } else { @@ -4220,21 +4110,16 @@ if ( mgsl_allocate_dma_buffers(info) < 0 ) { printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n", __FILE__,__LINE__,info->device_name, info->dma_level ); - mgsl_release_resources( info ); - return -ENODEV; + goto errout; } return 0; - +errout: + mgsl_release_resources(info); + return ENODEV; + } /* end of mgsl_claim_resources() */ -/* mgsl_release_resources() - * - * Release all resources used by a device - * - * Arguments: info pointer to device instance data - * Return Value: None - */ void mgsl_release_resources(struct mgsl_struct *info) { if ( debug_level >= DEBUG_LEVEL_INFO ) @@ -4245,7 +4130,6 @@ free_irq(info->irq_level, info); info->irq_requested = 0; } - if ( info->dma_requested ) { disable_dma(info->dma_level); free_dma(info->dma_level); @@ -4258,12 +4142,18 @@ release_region(info->io_base,info->io_addr_size); info->io_addr_requested = 0; } - + if ( info->shared_mem_requested ) { + release_mem_region(info->phys_memory_base,0x40000); + info->shared_mem_requested = 0; + } + if ( info->lcr_mem_requested ) { + release_mem_region(info->phys_lcr_base,128); + info->lcr_mem_requested = 0; + } if (info->memory_base){ iounmap(info->memory_base); info->memory_base = 0; } - if (info->lcr_base){ iounmap(info->lcr_base - info->lcr_offset); info->lcr_base = 0; @@ -4367,210 +4257,23 @@ } /* end of mgsl_allocate_device()*/ -/* mgsl_enumerate_devices() - * - * Enumerate SyncLink serial devices based on user specified - * options for ISA adapters and autodetected PCI adapters. - * - * Arguments: None - * Return Value: 0 if success, otherwise error code - */ -int mgsl_enumerate_devices() -{ - struct mgsl_struct *info; - int i; - - /* Check for user specified ISA devices */ - - for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){ - if ( debug_level >= DEBUG_LEVEL_INFO ) - printk("ISA device specified io=%04X,irq=%d,dma=%d\n", - io[i], irq[i], dma[i] ); - - info = mgsl_allocate_device(); - if ( !info ) { - /* error allocating device instance data */ - if ( debug_level >= DEBUG_LEVEL_ERROR ) - printk( "can't allocate device instance data.\n"); - continue; - } - - /* Copy user configuration info to device instance data */ - info->io_base = (unsigned int)io[i]; - info->irq_level = (unsigned int)irq[i]; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - info->irq_level = irq_cannonicalize(info->irq_level); -#else - if (info->irq_level == 2) - info->irq_level = 9; -#endif - info->dma_level = (unsigned int)dma[i]; - info->bus_type = MGSL_BUS_TYPE_ISA; - info->io_addr_size = 16; - info->irq_flags = 0; - - mgsl_add_device( info ); - } - - -#ifdef CONFIG_PCI - /* Auto detect PCI adapters */ - - if ( pcibios_present() ) { - unsigned char bus; - unsigned char func; - unsigned int shared_mem_base; - unsigned int lcr_mem_base; - unsigned int io_base; - unsigned char irq_line; - - for(i=0;;i++){ - if ( PCIBIOS_SUCCESSFUL == pcibios_find_device( - MICROGATE_VENDOR_ID, SYNCLINK_DEVICE_ID, i, &bus, &func) ) { - -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - struct pci_dev *pdev = pci_find_slot(bus,func); - irq_line = pdev->irq; -#else - if (pcibios_read_config_byte(bus,func, - PCI_INTERRUPT_LINE,&irq_line) ) { - printk( "%s(%d):USC I/O addr not set.\n", - __FILE__,__LINE__); - continue; - } -#endif - - if (pcibios_read_config_dword(bus,func, - PCI_BASE_ADDRESS_3,&shared_mem_base) ) { - printk( "%s(%d):Shared mem addr not set.\n", - __FILE__,__LINE__); - continue; - } - - if (pcibios_read_config_dword(bus,func, - PCI_BASE_ADDRESS_0,&lcr_mem_base) ) { - printk( "%s(%d):LCR mem addr not set.\n", - __FILE__,__LINE__); - continue; - } - - if (pcibios_read_config_dword(bus,func, - PCI_BASE_ADDRESS_2,&io_base) ) { - printk( "%s(%d):USC I/O addr not set.\n", - __FILE__,__LINE__); - continue; - } - - info = mgsl_allocate_device(); - if ( !info ) { - /* error allocating device instance data */ - if ( debug_level >= DEBUG_LEVEL_ERROR ) - printk( "can't allocate device instance data.\n"); - continue; - } - - /* Copy user configuration info to device instance data */ - - info->io_base = io_base & PCI_BASE_ADDRESS_IO_MASK; - info->irq_level = (unsigned int)irq_line; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - info->irq_level = irq_cannonicalize(info->irq_level); -#else - if (info->irq_level == 2) - info->irq_level = 9; -#endif - info->phys_memory_base = shared_mem_base & PCI_BASE_ADDRESS_MEM_MASK; - - /* Because veremap only works on page boundaries we must map - * a larger area than is actually implemented for the LCR - * memory range. We map a full page starting at the page boundary. - */ - info->phys_lcr_base = lcr_mem_base & PCI_BASE_ADDRESS_MEM_MASK; - info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); - info->phys_lcr_base &= ~(PAGE_SIZE-1); - - info->bus_type = MGSL_BUS_TYPE_PCI; - info->io_addr_size = 8; - info->irq_flags = SA_SHIRQ; - info->bus = bus; - info->function = func; - - /* Store the PCI9050 misc control register value because a flaw - * in the PCI9050 prevents LCR registers from being read if - * BIOS assigns an LCR base address with bit 7 set. - * - * Only the misc control register is accessed for which only - * write access is needed, so set an initial value and change - * bits to the device instance data as we write the value - * to the actual misc control register. - */ - info->misc_ctrl_value = 0x087e4546; - - /* add new device to device list */ - mgsl_add_device( info ); - } else { - break; - } - } - } -#endif - - /* - * Allocate memory to hold the following tty/termios arrays - * with an element for each enumerated device. - */ - - serial_table = (struct tty_struct**)kmalloc(sizeof(struct tty_struct*)*mgsl_device_count, GFP_KERNEL); - serial_termios = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL); - serial_termios_locked = (struct termios**)kmalloc(sizeof(struct termios*)*mgsl_device_count, GFP_KERNEL); - - if (!serial_table || !serial_termios || !serial_termios_locked){ - printk("%s(%d):Can't allocate tty/termios arrays.\n", - __FILE__,__LINE__); - return -ENOMEM; - } - - memset(serial_table,0,sizeof(struct tty_struct*)*mgsl_device_count); - memset(serial_termios,0,sizeof(struct termios*)*mgsl_device_count); - memset(serial_termios_locked,0,sizeof(struct termios*)*mgsl_device_count); - - return 0; - -} /* end of mgsl_enumerate_devices() */ - -/* mgsl_init() - * - * Driver initialization entry point. - * - * Arguments: None - * Return Value: 0 if success, otherwise error code +/* + * perform tty device initialization */ -int __init mgsl_init(void) +int mgsl_init_tty(void); +int mgsl_init_tty() { struct mgsl_struct *info; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) - EXPORT_NO_SYMBOLS; -#else - register_symtab(NULL); -#endif - - printk("%s version %s\n", driver_name, driver_version); - - /* determine how many SyncLink devices are installed */ - mgsl_enumerate_devices(); - if ( !mgsl_device_list ) { - printk("%s(%d):No SyncLink devices found.\n",__FILE__,__LINE__); - return -ENODEV; - } + memset(serial_table,0,sizeof(struct tty_struct*)*MAX_TOTAL_DEVICES); + memset(serial_termios,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES); + memset(serial_termios_locked,0,sizeof(struct termios*)*MAX_TOTAL_DEVICES); /* Initialize the tty_driver structure */ memset(&serial_driver, 0, sizeof(struct tty_driver)); serial_driver.magic = TTY_DRIVER_MAGIC; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) serial_driver.driver_name = "synclink"; -#endif serial_driver.name = "ttySL"; serial_driver.major = ttymajor; serial_driver.minor_start = 64; @@ -4597,12 +4300,10 @@ serial_driver.ioctl = mgsl_ioctl; serial_driver.throttle = mgsl_throttle; serial_driver.unthrottle = mgsl_unthrottle; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) serial_driver.send_xchar = mgsl_send_xchar; serial_driver.break_ctl = mgsl_break; serial_driver.wait_until_sent = mgsl_wait_until_sent; serial_driver.read_proc = mgsl_read_proc; -#endif serial_driver.set_termios = mgsl_set_termios; serial_driver.stop = mgsl_stop; serial_driver.start = mgsl_start; @@ -4616,10 +4317,8 @@ callout_driver.name = "cuaSL"; callout_driver.major = cuamajor; callout_driver.subtype = SERIAL_TYPE_CALLOUT; -#if LINUX_VERSION_CODE >= VERSION(2,1,0) callout_driver.read_proc = 0; callout_driver.proc_entry = 0; -#endif if (tty_register_driver(&serial_driver) < 0) printk("%s(%d):Couldn't register serial driver\n", @@ -4641,13 +4340,76 @@ info->normal_termios = serial_driver.init_termios; info = info->next_device; } + + return 0; +} + +/* enumerate user specified ISA adapters + */ +int mgsl_enum_isa_devices() +{ + struct mgsl_struct *info; + int i; + + /* Check for user specified ISA devices */ + + for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){ + if ( debug_level >= DEBUG_LEVEL_INFO ) + printk("ISA device specified io=%04X,irq=%d,dma=%d\n", + io[i], irq[i], dma[i] ); + + info = mgsl_allocate_device(); + if ( !info ) { + /* error allocating device instance data */ + if ( debug_level >= DEBUG_LEVEL_ERROR ) + printk( "can't allocate device instance data.\n"); + continue; + } + + /* Copy user configuration info to device instance data */ + info->io_base = (unsigned int)io[i]; + info->irq_level = (unsigned int)irq[i]; + info->irq_level = irq_cannonicalize(info->irq_level); + info->dma_level = (unsigned int)dma[i]; + info->bus_type = MGSL_BUS_TYPE_ISA; + info->io_addr_size = 16; + info->irq_flags = 0; + + mgsl_add_device( info ); + } return 0; +} + +/* mgsl_init() + * + * Driver initialization entry point. + * + * Arguments: None + * Return Value: 0 if success, otherwise error code + */ +int __init mgsl_init(void) +{ + int rc; + + EXPORT_NO_SYMBOLS; + + printk("%s version %s\n", driver_name, driver_version); -} /* end of mgsl_init() */ + mgsl_enum_isa_devices(); + pci_register_driver(&synclink_pci_driver); -#ifdef MODULE -int init_module(void) + if ( !mgsl_device_list ) { + printk("%s(%d):No SyncLink devices found.\n",__FILE__,__LINE__); + return -ENODEV; + } + if ((rc = mgsl_init_tty())) + return rc; + + return 0; +} + +static int __init synclink_init(void) { /* Uncomment this to kernel debug module. * mgsl_get_text_ptr() leaves the .text address in eax @@ -4661,7 +4423,7 @@ return mgsl_init(); } -void cleanup_module(void) +static void __exit synclink_exit(void) { unsigned long flags; int rc; @@ -4693,19 +4455,11 @@ tmp_buf = NULL; } - if (serial_table) - kfree(serial_table); - - if (serial_termios) - kfree(serial_termios); - - if (serial_termios_locked) - kfree(serial_termios_locked); - -} /* end of cleanup_module() */ - -#endif /* MODULE */ + pci_unregister_driver(&synclink_pci_driver); +} +module_init(synclink_init); +module_exit(synclink_exit); /* * usc_RTCmd() @@ -6953,7 +6707,6 @@ while( EndTime-- && !info->irq_occurred ) { set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(jiffies_from_ms(10)); - set_current_state(TASK_RUNNING); } spin_lock_irqsave(&info->irq_spinlock,flags); @@ -7567,16 +7320,13 @@ sprintf(info->netname,"mgsl%d",info->line); -#if LINUX_VERSION_CODE < VERSION(2,2,16) - info->netdev = &info->pppdev.dev; -#else info->if_ptr = &info->pppdev; info->netdev = info->pppdev.dev = &info->netdevice; -#endif + sppp_attach(&info->pppdev); d = info->netdev; - strcpy(d->name, info->netname); + strcpy(d->name,info->netname); d->base_addr = info->io_base; d->irq = info->irq_level; d->dma = info->dma_level; @@ -7587,10 +7337,9 @@ d->hard_start_xmit = mgsl_sppp_tx; d->do_ioctl = mgsl_sppp_ioctl; d->get_stats = mgsl_net_stats; -#if LINUX_VERSION_CODE >= VERSION(2,3,43) d->tx_timeout = mgsl_sppp_tx_timeout; d->watchdog_timeo = 10*HZ; -#endif + dev_init_buffers(d); if (register_netdev(d) == -1) { @@ -7680,17 +7429,7 @@ if (debug_level >= DEBUG_LEVEL_INFO) printk("mgsl_sppp_tx(%s)\n",info->netname); -#if LINUX_VERSION_CODE < VERSION(2,3,43) - if (dev->tbusy) { - if (time_before(jiffies, dev->trans_start+10*HZ)) - return -EBUSY; /* 10 seconds timeout */ - mgsl_sppp_tx_timeout(dev); - } - if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) - return -EBUSY; -#else netif_stop_queue(dev); -#endif info->xmit_cnt = skb->len; mgsl_load_tx_dma_buffer(info, skb->data, skb->len); @@ -7777,3 +7516,57 @@ } #endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */ + +static int __init synclink_init_one (struct pci_dev *dev, + const struct pci_device_id *ent) +{ + struct mgsl_struct *info; + + if (pci_enable_device(dev)) { + printk("error enabling pci device %p\n", dev); + return -EIO; + } + + if (!(info = mgsl_allocate_device())) { + printk("can't allocate device instance data.\n"); + return -EIO; + } + + /* Copy user configuration info to device instance data */ + + info->io_base = pci_resource_start(dev, 2); + info->irq_level = dev->irq; + info->phys_memory_base = pci_resource_start(dev, 3); + + /* Because veremap only works on page boundaries we must map + * a larger area than is actually implemented for the LCR + * memory range. We map a full page starting at the page boundary. + */ + info->phys_lcr_base = pci_resource_start(dev, 0); + info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1); + info->phys_lcr_base &= ~(PAGE_SIZE-1); + + info->bus_type = MGSL_BUS_TYPE_PCI; + info->io_addr_size = 8; + info->irq_flags = SA_SHIRQ; + + /* Store the PCI9050 misc control register value because a flaw + * in the PCI9050 prevents LCR registers from being read if + * BIOS assigns an LCR base address with bit 7 set. + * + * Only the misc control register is accessed for which only + * write access is needed, so set an initial value and change + * bits to the device instance data as we write the value + * to the actual misc control register. + */ + info->misc_ctrl_value = 0x087e4546; + + mgsl_add_device(info); + + return 0; +} + +static void __exit synclink_remove_one (struct pci_dev *dev) +{ +} + diff -u --recursive --new-file v2.4.0-test10/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c --- v2.4.0-test10/linux/drivers/i2o/i2o_block.c Thu Jul 6 19:24:51 2000 +++ linux/drivers/i2o/i2o_block.c Wed Nov 8 17:09:50 2000 @@ -584,7 +584,6 @@ int i; lock_kernel(); - exit_files(current); daemonize(); unlock_kernel(); @@ -593,6 +592,7 @@ while(1) { +#warning "RACE" interruptible_sleep_on(&i2ob_evt_wait); if(signal_pending(current)) { evt_running = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c --- v2.4.0-test10/linux/drivers/i2o/i2o_core.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/i2o/i2o_core.c Wed Nov 8 17:09:50 2000 @@ -842,7 +842,6 @@ int flags; lock_kernel(); - exit_files(current); daemonize(); unlock_kernel(); @@ -1005,7 +1004,6 @@ char name[16]; lock_kernel(); - exit_files(current); daemonize(); unlock_kernel(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/i2o/i2o_proc.c linux/drivers/i2o/i2o_proc.c --- v2.4.0-test10/linux/drivers/i2o/i2o_proc.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/i2o/i2o_proc.c Fri Nov 17 16:51:47 2000 @@ -3237,7 +3237,7 @@ for(dev=pctrl->devices; dev; dev=dev->next) i2o_proc_remove_device(dev); - if(!pctrl->proc_entry->count) + if(!atomic_read(&pctrl->proc_entry->count)) { sprintf(buff, "iop%d", pctrl->unit); @@ -3257,7 +3257,7 @@ i2o_device_notify_off(dev, &i2o_proc_handler); /* Would it be safe to remove _files_ even if they are in use? */ - if((de) && (!de->count)) + if((de) && (!atomic_read(&de->count))) { i2o_proc_remove_entries(generic_dev_entries, de); switch(dev->lct_data.class_id) @@ -3334,7 +3334,7 @@ } } - if(!i2o_proc_dir_root->count) + if(!atomic_read(&i2o_proc_dir_root->count)) remove_proc_entry("i2o", 0); else return -1; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/Makefile linux/drivers/ide/Makefile --- v2.4.0-test10/linux/drivers/ide/Makefile Tue Oct 31 12:42:26 2000 +++ linux/drivers/ide/Makefile Wed Nov 8 17:09:49 2000 @@ -31,7 +31,7 @@ ide-obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o ide-obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o ide-obj-$(CONFIG_BLK_DEV_Q40IDE) += q40ide.o -ide-obj-$(CONFIG_BLK_DEV_HD) += hd.o +obj-$(CONFIG_BLK_DEV_HD) += hd.o ide-obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o ide-obj-$(CONFIG_BLK_DEV_HPT366) += hpt366.o ide-obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c --- v2.4.0-test10/linux/drivers/ide/alim15x3.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/ide/alim15x3.c Tue Nov 7 11:02:24 2000 @@ -691,7 +691,7 @@ } } -void ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) { if ((dmabase) && (m5229_revision < 0x20)) { return; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c --- v2.4.0-test10/linux/drivers/ide/amd7409.c Tue Jun 20 07:52:36 2000 +++ linux/drivers/ide/amd7409.c Tue Nov 7 11:02:24 2000 @@ -464,7 +464,7 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ } -void ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase) { ide_setup_dma(hwif, dmabase, 8); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/hd.c linux/drivers/ide/hd.c --- v2.4.0-test10/linux/drivers/ide/hd.c Wed Jul 5 11:24:41 2000 +++ linux/drivers/ide/hd.c Tue Nov 7 11:02:24 2000 @@ -723,7 +723,7 @@ * We enable interrupts in some of the routines after making sure it's * safe. */ -static void hd_geninit(void) +static void __init hd_geninit(void) { int drive; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c --- v2.4.0-test10/linux/drivers/ide/hpt366.c Thu Jul 27 16:40:57 2000 +++ linux/drivers/ide/hpt366.c Tue Nov 7 11:02:24 2000 @@ -698,7 +698,7 @@ #endif /* CONFIG_BLK_DEV_IDEDMA */ } -void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase) { byte masterdma = 0, slavedma = 0; byte dma_new = 0, dma_old = inb(dmabase+2); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/icside.c linux/drivers/ide/icside.c --- v2.4.0-test10/linux/drivers/ide/icside.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/ide/icside.c Tue Nov 7 11:02:24 2000 @@ -163,7 +163,7 @@ * Purpose : identify IDE interface type * Notes : checks the description string */ -static iftype_t icside_identifyif (struct expansion_card *ec) +static iftype_t __init icside_identifyif (struct expansion_card *ec) { unsigned int addr; iftype_t iftype; @@ -505,7 +505,7 @@ return hwif; } -static int icside_register_v5(struct expansion_card *ec, int autodma) +static int __init icside_register_v5(struct expansion_card *ec, int autodma) { unsigned long slot_port; ide_hwif_t *hwif; @@ -527,7 +527,7 @@ return hwif ? 0 : -1; } -static int icside_register_v6(struct expansion_card *ec, int autodma) +static int __init icside_register_v6(struct expansion_card *ec, int autodma) { unsigned long slot_port, port; ide_hwif_t *hwif, *mate; @@ -585,7 +585,7 @@ return hwif || mate ? 0 : -1; } -int icside_init(void) +int __init icside_init(void) { int autodma = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c --- v2.4.0-test10/linux/drivers/ide/ide-pci.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/ide/ide-pci.c Tue Nov 7 11:02:24 2000 @@ -528,10 +528,7 @@ autodma = 1; #endif -#if 1 /* what do do with this useful tool ??? */ - if (pci_enable_device(dev)) - return; -#endif + pci_enable_device(dev); check_if_enabled: if (pci_read_config_word(dev, PCI_COMMAND, &pcicmd)) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/opti621.c linux/drivers/ide/opti621.c --- v2.4.0-test10/linux/drivers/ide/opti621.c Thu Apr 13 22:54:26 2000 +++ linux/drivers/ide/opti621.c Tue Nov 7 11:02:24 2000 @@ -308,7 +308,7 @@ /* * ide_init_opti621() is called once for each hwif found at boot. */ -void ide_init_opti621 (ide_hwif_t *hwif) +void __init ide_init_opti621 (ide_hwif_t *hwif) { hwif->drives[0].drive_data = PIO_DONT_KNOW; hwif->drives[1].drive_data = PIO_DONT_KNOW; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c --- v2.4.0-test10/linux/drivers/ide/sis5513.c Tue Sep 5 13:48:25 2000 +++ linux/drivers/ide/sis5513.c Tue Nov 7 10:59:43 2000 @@ -33,8 +33,6 @@ static struct pci_dev *host_dev = NULL; -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define SIS5513_FLAG_ATA_00 0x00000000 #define SIS5513_FLAG_ATA_16 0x00000001 #define SIS5513_FLAG_ATA_33 0x00000002 @@ -545,7 +543,7 @@ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &latency); - for (i = 0; i < arraysize (SiSHostChipInfo) && !host_dev; i++) { + for (i = 0; i < ARRAY_SIZE (SiSHostChipInfo) && !host_dev; i++) { host = pci_find_device (PCI_VENDOR_ID_SI, SiSHostChipInfo[i].host_id, NULL); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/sl82c105.c linux/drivers/ide/sl82c105.c --- v2.4.0-test10/linux/drivers/ide/sl82c105.c Wed Mar 22 17:18:44 2000 +++ linux/drivers/ide/sl82c105.c Tue Nov 7 11:02:24 2000 @@ -91,7 +91,7 @@ } #endif -void ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_sl82c105(ide_hwif_t *hwif, unsigned long dmabase) { unsigned char rev; @@ -107,7 +107,7 @@ ide_setup_dma(hwif, dmabase, 8); } -void ide_init_sl82c105(ide_hwif_t *hwif) +void __init ide_init_sl82c105(ide_hwif_t *hwif) { struct pci_dev *dev = hwif->pci_dev; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c --- v2.4.0-test10/linux/drivers/ide/via82cxxx.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/ide/via82cxxx.c Tue Nov 7 11:02:24 2000 @@ -611,7 +611,7 @@ * We allow the BM-DMA driver only work on enabled interfaces. */ -void ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) +void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase) { if ((via_enabled >> hwif->channel) & 1) ide_setup_dma(hwif, dmabase, 8); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/input/evdev.c linux/drivers/input/evdev.c --- v2.4.0-test10/linux/drivers/input/evdev.c Thu Jul 27 18:36:54 2000 +++ linux/drivers/input/evdev.c Fri Nov 17 16:52:23 2000 @@ -123,7 +123,7 @@ struct evdev_list *list; int i = MINOR(inode->i_rdev) - EVDEV_MINOR_BASE; - if (i > EVDEV_MINORS || !evdev_table[i]) + if (i >= EVDEV_MINORS || !evdev_table[i]) return -ENODEV; if (!(list = kmalloc(sizeof(struct evdev_list), GFP_KERNEL))) @@ -288,7 +288,7 @@ int minor; for (minor = 0; minor < EVDEV_MINORS && evdev_table[minor]; minor++); - if (evdev_table[minor]) { + if (minor == EVDEV_MINORS) { printk(KERN_ERR "evdev: no more free evdev devices\n"); return NULL; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/input/input.c linux/drivers/input/input.c --- v2.4.0-test10/linux/drivers/input/input.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/input/input.c Fri Nov 17 16:52:23 2000 @@ -29,6 +29,8 @@ */ #include +#include +#include #include #include #include @@ -378,7 +380,11 @@ } old_fops = file->f_op; file->f_op = new_fops; + + lock_kernel(); err = new_fops->open(inode, file); + unlock_kernel(); + if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/input/joydev.c linux/drivers/input/joydev.c --- v2.4.0-test10/linux/drivers/input/joydev.c Tue Aug 22 09:06:31 2000 +++ linux/drivers/input/joydev.c Fri Nov 17 16:52:23 2000 @@ -193,7 +193,7 @@ struct joydev_list *list; int i = MINOR(inode->i_rdev) - JOYDEV_MINOR_BASE; - if (i > JOYDEV_MINORS || !joydev_table[i]) + if (i >= JOYDEV_MINORS || !joydev_table[i]) return -ENODEV; if (!(list = kmalloc(sizeof(struct joydev_list), GFP_KERNEL))) @@ -395,7 +395,7 @@ || test_bit(BTN_1, dev->keybit)))) return NULL; for (minor = 0; minor < JOYDEV_MINORS && joydev_table[minor]; minor++); - if (joydev_table[minor]) { + if (minor == JOYDEV_MINORS) { printk(KERN_ERR "joydev: no more free joydev devices\n"); return NULL; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/input/mousedev.c linux/drivers/input/mousedev.c --- v2.4.0-test10/linux/drivers/input/mousedev.c Tue Aug 22 09:06:31 2000 +++ linux/drivers/input/mousedev.c Fri Nov 17 16:52:23 2000 @@ -39,6 +39,7 @@ #include #include #include +#include #ifndef CONFIG_INPUT_MOUSEDEV_SCREEN_X #define CONFIG_INPUT_MOUSEDEV_SCREEN_X 1024 @@ -86,6 +87,8 @@ struct mousedev_list *list; int index, size; + add_mouse_randomness((type << 4) ^ code ^ (code >> 4) ^ value); + while (*mousedev) { list = (*mousedev)->list; while (list) { @@ -213,7 +216,7 @@ struct mousedev_list *list; int i = MINOR(inode->i_rdev) - MOUSEDEV_MINOR_BASE; - if (i > MOUSEDEV_MINORS || !mousedev_table[i]) + if (i >= MOUSEDEV_MINORS || !mousedev_table[i]) return -ENODEV; if (!(list = kmalloc(sizeof(struct mousedev_list), GFP_KERNEL))) @@ -407,7 +410,7 @@ return NULL; for (minor = 0; minor < MOUSEDEV_MINORS && mousedev_table[minor]; minor++); - if (mousedev_table[minor]) { + if (minor == MOUSEDEV_MINORS) { printk(KERN_ERR "mousedev: no more free mousedev devices\n"); return NULL; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/Config.in linux/drivers/isdn/Config.in --- v2.4.0-test10/linux/drivers/isdn/Config.in Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/Config.in Fri Nov 17 11:16:20 2000 @@ -10,7 +10,7 @@ fi bool ' Support audio via ISDN' CONFIG_ISDN_AUDIO if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then - bool ' Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX + bool ' Support AT-Fax Class 1 and 2 commands' CONFIG_ISDN_TTY_FAX fi if [ "$CONFIG_X25" != "n" ]; then bool ' X.25 PLP on top of ISDN' CONFIG_ISDN_X25 diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/Makefile linux/drivers/isdn/act2000/Makefile --- v2.4.0-test10/linux/drivers/isdn/act2000/Makefile Wed Apr 1 16:20:57 1998 +++ linux/drivers/isdn/act2000/Makefile Fri Nov 17 11:16:20 2000 @@ -7,7 +7,7 @@ O_TARGET += act2000.o else ifeq ($(CONFIG_ISDN_DRV_ACT2000),m) - O_TARGET += act2000.o + O_TARGET += act2000.o M_OBJS = act2000.o endif endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/act2000.h linux/drivers/isdn/act2000/act2000.h --- v2.4.0-test10/linux/drivers/isdn/act2000/act2000.h Sun May 23 10:03:41 1999 +++ linux/drivers/isdn/act2000/act2000.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: act2000.h,v 1.7 1999/04/12 13:13:54 fritz Exp $ +/* $Id: act2000.h,v 1.8 2000/11/12 16:32:06 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -18,31 +18,6 @@ * 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. - * - * $Log: act2000.h,v $ - * Revision 1.7 1999/04/12 13:13:54 fritz - * Made cards pointer static to avoid name-clash. - * - * Revision 1.6 1998/11/05 22:12:38 fritz - * Changed mail-address. - * - * Revision 1.5 1997/10/09 22:22:59 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.4 1997/09/25 17:25:37 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.3 1997/09/24 23:11:43 fritz - * Optimized IRQ load and polling-mode. - * - * Revision 1.2 1997/09/24 19:44:12 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.1 1997/09/23 18:00:05 fritz - * New driver for IBM Active 2000. * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/act2000_isa.c linux/drivers/isdn/act2000/act2000_isa.c --- v2.4.0-test10/linux/drivers/isdn/act2000/act2000_isa.c Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/act2000/act2000_isa.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: act2000_isa.c,v 1.10 1999/10/24 18:46:05 fritz Exp $ +/* $Id: act2000_isa.c,v 1.11 2000/11/12 16:32:06 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * @@ -18,43 +18,6 @@ * 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. - * - * $Log: act2000_isa.c,v $ - * Revision 1.10 1999/10/24 18:46:05 fritz - * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest - * kernels. - * - * Revision 1.9 1999/09/04 06:20:04 keil - * Changes from kernel set_current_state() - * - * Revision 1.8 1999/01/05 18:29:25 he - * merged remaining schedule_timeout() changes from 2.1.127 - * - * Revision 1.7 1998/11/05 22:12:41 fritz - * Changed mail-address. - * - * Revision 1.6 1998/06/17 19:51:09 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.5 1998/02/12 23:06:47 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.4 1997/10/09 22:23:00 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.3 1997/09/25 17:25:38 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.2 1997/09/24 23:11:44 fritz - * Optimized IRQ load and polling-mode. - * - * Revision 1.1 1997/09/23 18:00:05 fritz - * New driver for IBM Active 2000. * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/act2000_isa.h linux/drivers/isdn/act2000/act2000_isa.h --- v2.4.0-test10/linux/drivers/isdn/act2000/act2000_isa.h Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/act2000/act2000_isa.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: act2000_isa.h,v 1.3 1999/10/24 18:46:05 fritz Exp $ +/* $Id: act2000_isa.h,v 1.4 2000/11/12 16:32:06 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). * @@ -18,17 +18,6 @@ * 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. - * - * $Log: act2000_isa.h,v $ - * Revision 1.3 1999/10/24 18:46:05 fritz - * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest - * kernels. - * - * Revision 1.2 1998/11/05 22:12:43 fritz - * Changed mail-address. - * - * Revision 1.1 1997/09/23 18:00:07 fritz - * New driver for IBM Active 2000. * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/capi.c linux/drivers/isdn/act2000/capi.c --- v2.4.0-test10/linux/drivers/isdn/act2000/capi.c Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/act2000/capi.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: capi.c,v 1.8 1998/11/05 22:12:46 fritz Exp $ +/* $Id: capi.c,v 1.9 2000/11/12 16:32:06 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * CAPI encoder/decoder @@ -19,34 +19,6 @@ * 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. - * - * $Log: capi.c,v $ - * Revision 1.8 1998/11/05 22:12:46 fritz - * Changed mail-address. - * - * Revision 1.7 1998/02/23 23:35:41 fritz - * Eliminated some compiler warnings. - * - * Revision 1.6 1998/02/12 23:06:50 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.5 1997/10/09 22:23:02 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.4 1997/09/25 17:25:39 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.3 1997/09/24 19:44:14 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.2 1997/09/23 19:41:24 fritz - * Disabled Logging of DATA_B3_IND/RESP/REQ/CONF Messages. - * - * Revision 1.1 1997/09/23 18:00:08 fritz - * New driver for IBM Active 2000. * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/capi.h linux/drivers/isdn/act2000/capi.h --- v2.4.0-test10/linux/drivers/isdn/act2000/capi.h Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/act2000/capi.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: capi.h,v 1.5 1998/11/05 22:12:48 fritz Exp $ +/* $Id: capi.h,v 1.6 2000/11/12 16:32:06 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -18,25 +18,6 @@ * 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. - * - * $Log: capi.h,v $ - * Revision 1.5 1998/11/05 22:12:48 fritz - * Changed mail-address. - * - * Revision 1.4 1997/10/01 09:21:04 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.3 1997/09/25 17:25:41 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.2 1997/09/24 19:44:15 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.1 1997/09/23 18:00:10 fritz - * New driver for IBM Active 2000. * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/act2000/module.c linux/drivers/isdn/act2000/module.c --- v2.4.0-test10/linux/drivers/isdn/act2000/module.c Fri Apr 28 22:50:13 2000 +++ linux/drivers/isdn/act2000/module.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: module.c,v 1.11 1999/10/30 09:48:04 keil Exp $ +/* $Id: module.c,v 1.14 2000/11/12 16:32:06 kai Exp $ * * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. * @@ -19,44 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: module.c,v $ - * Revision 1.11 1999/10/30 09:48:04 keil - * miss one prefix act2000 - * - * Revision 1.10 1999/10/24 18:46:05 fritz - * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest - * kernels. - * - * Revision 1.9 1999/04/12 13:13:56 fritz - * Made cards pointer static to avoid name-clash. - * - * Revision 1.8 1998/11/05 22:12:51 fritz - * Changed mail-address. - * - * Revision 1.7 1998/02/12 23:06:52 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.6 1998/01/31 22:10:42 keil - * changes for 2.1.82 - * - * Revision 1.5 1997/10/09 22:23:04 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.4 1997/09/25 17:25:43 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.3 1997/09/24 23:11:45 fritz - * Optimized IRQ load and polling-mode. - * - * Revision 1.2 1997/09/24 19:44:17 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.1 1997/09/23 18:00:13 fritz - * New driver for IBM Active 2000. - * */ #include "act2000.h" @@ -561,37 +523,6 @@ card->status_buf_read = card->status_buf; } return count; -} - -static void -act2000_putmsg(act2000_card *card, char c) -{ - ulong flags; - - save_flags(flags); - cli(); - *card->status_buf_write++ = c; - if (card->status_buf_write == card->status_buf_read) { - if (++card->status_buf_read > card->status_buf_end) - card->status_buf_read = card->status_buf; - } - if (card->status_buf_write > card->status_buf_end) - card->status_buf_write = card->status_buf; - restore_flags(flags); -} - -static void -act2000_logstat(struct act2000_card *card, char *str) -{ - char *p = str; - isdn_ctrl c; - - while (*p) - act2000_putmsg(card, *p++); - c.command = ISDN_STAT_STAVAIL; - c.driver = card->myid; - c.arg = strlen(str); - card->interface.statcallb(&c); } /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/Makefile linux/drivers/isdn/avmb1/Makefile --- v2.4.0-test10/linux/drivers/isdn/avmb1/Makefile Thu Jun 29 11:37:15 2000 +++ linux/drivers/isdn/avmb1/Makefile Fri Nov 17 11:16:20 2000 @@ -1,5 +1,5 @@ # -# $Id: Makefile,v 1.18 2000/04/03 16:39:25 calle Exp $ +# $Id: Makefile,v 1.21 2000/11/01 14:05:02 calle Exp $ # # Makefile for the CAPI and AVM-B1 device drivers. # @@ -11,6 +11,23 @@ # parent makes.. # # $Log: Makefile,v $ +# 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. +# - avm_cs.c, let it work with newer pcmcia-cs. +# +# Revision 1.20 2000/10/18 06:13:34 ostoyke +# Removing CAPI4Linux from I4L CVS. +# +# Revision 1.19 2000/08/10 14:46:25 ostoyke +# CAPI4Linux. +# +# Revision 1.18 2000/04/03 16:39:25 calle +# Makefile checked in with future things :-( +# +# Revision 1.17 2000/04/03 16:38:05 calle +# made suppress_pollack static. +# # Revision 1.16 2000/03/17 12:15:44 calle # ALL_SUB_DIRS were wrong. # @@ -109,7 +126,7 @@ SUB_DIRS := MOD_SUB_DIRS := -ALL_SUB_DIRS := # fcpci fcclassic +ALL_SUB_DIRS := # # Objects that don't export a symtab # @@ -158,14 +175,6 @@ ifdef CONFIG_ISDN_DRV_AVMB1_C4 O_OBJS += c4.o endif - ifdef CONFIG_ISDN_DRV_AVMB1_FCPCI - SUB_DIRS += fcpci - MOD_SUB_DIRS += fcpci - endif - ifdef CONFIG_ISDN_DRV_AVMB1_FCCLASSIC - SUB_DIRS += fcclassic - MOD_SUB_DIRS += fcclassic - endif OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o else ifeq ($(CONFIG_ISDN_CAPI),m) @@ -198,12 +207,6 @@ ifdef CONFIG_ISDN_DRV_AVMB1_C4 M_OBJS += c4.o endif - ifdef CONFIG_ISDN_DRV_AVMB1_FCPCI - MOD_SUB_DIRS += fcpci - endif - ifdef CONFIG_ISDN_DRV_AVMB1_FCCLASSIC - MOD_SUB_DIRS += fcclassic - endif MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o endif endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h --- v2.4.0-test10/linux/drivers/isdn/avmb1/avmcard.h Tue Feb 15 11:40:42 2000 +++ linux/drivers/isdn/avmb1/avmcard.h Sat Nov 11 18:58:02 2000 @@ -1,9 +1,12 @@ /* - * $Id: avmcard.h,v 1.7 2000/01/25 14:33:38 calle Exp $ + * $Id: avmcard.h,v 1.8 2000/10/10 17:44:19 kai Exp $ * * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: avmcard.h,v $ + * Revision 1.8 2000/10/10 17:44:19 kai + * changes from/for 2.2.18 + * * Revision 1.7 2000/01/25 14:33:38 calle * - Added Support AVM B1 PCI V4.0 (tested with prototype) * - splitted up t1pci.c into b1dma.c for common function with b1pciv4 @@ -347,13 +350,13 @@ static inline void b1_reset(unsigned int base) { b1outp(base, B1_RESET, 0); - udelay(55 * 2 * 1000); /* 2 TIC's */ + mdelay(55 * 2); /* 2 TIC's */ b1outp(base, B1_RESET, 1); - udelay(55 * 2 * 1000); /* 2 TIC's */ + mdelay(55 * 2); /* 2 TIC's */ b1outp(base, B1_RESET, 0); - udelay(55 * 2 * 1000); /* 2 TIC's */ + mdelay(55 * 2); /* 2 TIC's */ } static inline unsigned char b1_disable_irq(unsigned int base) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/b1.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/isdn/avmb1/b1.c Fri Nov 17 11:16:21 2000 @@ -517,7 +517,7 @@ struct sk_buff *skb; unsigned ApplId; - signed MsgLen; + unsigned MsgLen; unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/b1dma.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/isdn/avmb1/b1dma.c Fri Nov 17 11:16:21 2000 @@ -1,11 +1,19 @@ /* - * $Id: b1dma.c,v 1.7 2000/08/04 12:20:08 calle Exp $ + * $Id: b1dma.c,v 1.9 2000/11/01 14:05:02 calle 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.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/10/10 17:44:19 kai + * changes from/for 2.2.18 + * * Revision 1.7 2000/08/04 12:20:08 calle * - Fix unsigned/signed warning in the right way ... * @@ -47,7 +55,7 @@ #include "capicmd.h" #include "capiutil.h" -static char *revision = "$Revision: 1.7 $"; +static char *revision = "$Revision: 1.9 $"; /* ------------------------------------------------------------- */ @@ -243,14 +251,14 @@ restore_flags(flags); b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - udelay(10 * 1000); + mdelay(10); b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ - udelay(10 * 1000); + mdelay(10); b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); if (card->cardtype == avm_t1pci) - udelay(42 * 1000); + mdelay(42); else - udelay(10 * 1000); + mdelay(10); } /* ------------------------------------------------------------- */ @@ -258,11 +266,11 @@ int b1dma_detect(avmcard *card) { b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - udelay(10 * 1000); + mdelay(10); b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ - udelay(10 * 1000); + mdelay(10); b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - udelay(42 * 1000); + mdelay(42); b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0); b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0); @@ -475,8 +483,7 @@ struct capi_ctr *ctrl = cinfo->capi_ctrl; struct sk_buff *skb; void *p = dma->recvbuf+4; - __u32 ApplId, DataB3Len, NCCI, WindowSize; - __s32 MsgLen; + __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; __u8 b1cmd = _get_byte(&p); #ifdef CONFIG_B1DMA_DEBUG diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/b1isa.c Thu Apr 13 09:03:03 2000 +++ linux/drivers/isdn/avmb1/b1isa.c Fri Nov 17 11:16:21 2000 @@ -244,20 +244,20 @@ /* ------------------------------------------------------------- */ static struct capi_driver b1isa_driver = { - "b1isa", - "0.0", - b1_load_firmware, - b1_reset_ctr, - b1isa_remove_ctr, - b1_register_appl, - b1_release_appl, - b1_send_message, + name: "b1isa", + revision: "0.0", + load_firmware: b1_load_firmware, + reset_ctr: b1_reset_ctr, + remove_ctr: b1isa_remove_ctr, + register_appl: b1_register_appl, + release_appl: b1_release_appl, + send_message: b1_send_message, - b1isa_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ + procinfo: b1isa_procinfo, + ctr_read_proc: b1ctl_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - b1isa_add_card, + add_card: b1isa_add_card, }; #ifdef MODULE diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/b1pci.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/avmb1/b1pci.c Fri Nov 17 11:16:21 2000 @@ -276,20 +276,20 @@ /* ------------------------------------------------------------- */ static struct capi_driver b1pci_driver = { - "b1pci", - "0.0", - b1_load_firmware, - b1_reset_ctr, - b1pci_remove_ctr, - b1_register_appl, - b1_release_appl, - b1_send_message, - - b1pci_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ + name: "b1pci", + revision: "0.0", + load_firmware: b1_load_firmware, + reset_ctr: b1_reset_ctr, + remove_ctr: b1pci_remove_ctr, + register_appl: b1_register_appl, + release_appl: b1_release_appl, + send_message: b1_send_message, + + procinfo: b1pci_procinfo, + ctr_read_proc: b1ctl_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - 0, /* no add_card function */ + add_card: 0, /* no add_card function */ }; #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 @@ -463,20 +463,20 @@ static struct capi_driver b1pciv4_driver = { - "b1pciv4", - "0.0", - b1dma_load_firmware, - b1dma_reset_ctr, - b1pciv4_remove_ctr, - b1dma_register_appl, - b1dma_release_appl, - b1dma_send_message, - - b1pciv4_procinfo, - b1dmactl_read_proc, - 0, /* use standard driver_read_proc */ + name: "b1pciv4", + revision: "0.0", + load_firmware: b1dma_load_firmware, + reset_ctr: b1dma_reset_ctr, + remove_ctr: b1pciv4_remove_ctr, + register_appl: b1dma_register_appl, + release_appl: b1dma_release_appl, + send_message: b1dma_send_message, + + procinfo: b1pciv4_procinfo, + ctr_read_proc: b1dmactl_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - 0, /* no add_card function */ + add_card: 0, /* no add_card function */ }; #endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/b1pcmcia.c Mon Jul 24 18:48:49 2000 +++ linux/drivers/isdn/avmb1/b1pcmcia.c Fri Nov 17 11:16:21 2000 @@ -245,20 +245,20 @@ /* ------------------------------------------------------------- */ static struct capi_driver b1pcmcia_driver = { - "b1pcmcia", - "0.0", - b1_load_firmware, - b1_reset_ctr, - b1pcmcia_remove_ctr, - b1_register_appl, - b1_release_appl, - b1_send_message, + name: "b1pcmcia", + revision: "0.0", + load_firmware: b1_load_firmware, + reset_ctr: b1_reset_ctr, + remove_ctr: b1pcmcia_remove_ctr, + register_appl: b1_register_appl, + release_appl: b1_release_appl, + send_message: b1_send_message, - b1pcmcia_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ + procinfo: b1pcmcia_procinfo, + ctr_read_proc: b1ctl_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - 0, + add_card: 0, }; /* ------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/c4.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/isdn/avmb1/c4.c Fri Nov 17 11:16:21 2000 @@ -1,11 +1,19 @@ /* - * $Id: c4.c,v 1.16 2000/08/20 07:30:13 keil Exp $ + * $Id: c4.c,v 1.18 2000/11/01 14:05:02 calle Exp $ * * Module for AVM C4 card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: c4.c,v $ + * 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. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.17 2000/10/10 17:44:19 kai + * changes from/for 2.2.18 + * * Revision 1.16 2000/08/20 07:30:13 keil * changes for 2.4 * @@ -80,7 +88,7 @@ #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.16 $"; +static char *revision = "$Revision: 1.18 $"; #undef CONFIG_C4_DEBUG #undef CONFIG_C4_POLLDEBUG @@ -410,7 +418,7 @@ return 8; if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9; - udelay(1000); + mdelay(1); if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10; if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11; @@ -422,7 +430,7 @@ if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16; if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17; - udelay(1000); + mdelay(1); if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF)) return 18; @@ -572,8 +580,7 @@ avmctrl_info *cinfo; struct sk_buff *skb; void *p = dma->recvbuf; - __u32 ApplId, DataB3Len, NCCI, WindowSize; - __s32 MsgLen; + __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; __u8 b1cmd = _get_byte(&p); __u32 cidx; @@ -927,7 +934,7 @@ c4outmeml(card->mbase+MBOX_UP_LEN, 0); c4outmeml(card->mbase+MBOX_DOWN_LEN, 0); c4outmeml(card->mbase+DOORBELL, DBELL_INIT); - udelay(1000); + mdelay(1); c4outmeml(card->mbase+DOORBELL, DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST); @@ -1303,21 +1310,22 @@ /* ------------------------------------------------------------- */ static struct capi_driver c4_driver = { - "c4", - "0.0", - c4_load_firmware, - c4_reset_ctr, - c4_remove_ctr, - c4_register_appl, - c4_release_appl, - c4_send_message, - - c4_procinfo, - c4_read_proc, - 0, /* use standard driver_read_proc */ + name: "c4", + revision: "0.0", + load_firmware: c4_load_firmware, + reset_ctr: c4_reset_ctr, + remove_ctr: c4_remove_ctr, + register_appl: c4_register_appl, + release_appl: c4_release_appl, + send_message: c4_send_message, + + procinfo: c4_procinfo, + ctr_read_proc: c4_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - 0, /* no add_card function */ + add_card: 0, /* no add_card function */ }; + #ifdef MODULE #define c4_init init_module diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/capi.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/isdn/avmb1/capi.c Fri Nov 17 11:16:21 2000 @@ -2054,8 +2054,8 @@ } static struct capi_interface_user cuser = { - "capi20", - lower_callback, + name: "capi20", + callback: lower_callback, }; static char rev[10]; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/capidrv.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/isdn/avmb1/capidrv.c Fri Nov 17 11:16:21 2000 @@ -386,16 +386,16 @@ } } -static _cstruct b1config_sync_v110(__u16 rate) +static _cstruct b1config_async_v110(__u16 rate) { /* CAPI-Spec "B1 Configuration" */ static unsigned char buf[9]; buf[0] = 8; /* len */ /* maximum bitrate */ buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff; - buf[3] = buf[4] = 0; /* reserved, bits per character */ - buf[5] = buf[6] = 0; /* reserved, parity */ - buf[7] = buf[9] = 0; /* reserved, stop bits */ + buf[3] = 8; buf[4] = 0; /* 8 bits per character */ + buf[5] = 0; buf[6] = 0; /* parity none */ + buf[7] = 0; buf[8] = 0; /* 1 stop bit */ return buf; } @@ -410,11 +410,11 @@ default: return 0; case ISDN_PROTO_L2_V11096: - return b1config_sync_v110(9600); + return b1config_async_v110(9600); case ISDN_PROTO_L2_V11019: - return b1config_sync_v110(19200); + return b1config_async_v110(19200); case ISDN_PROTO_L2_V11038: - return b1config_sync_v110(38400); + return b1config_async_v110(38400); } } @@ -2464,8 +2464,8 @@ } static struct capi_interface_user cuser = { - "capidrv", - lower_callback + name: "capidrv", + callback: lower_callback }; int __init capidrv_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/capifs.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/isdn/avmb1/capifs.c Fri Nov 17 11:35:27 2000 @@ -119,8 +119,6 @@ lookup: capifs_root_lookup, }; -struct inode_operations capifs_inode_operations; - static struct dentry_operations capifs_dentry_operations = { d_revalidate: capifs_revalidate, }; @@ -468,10 +466,8 @@ ino_t ino = inode->i_ino; struct capifs_sb_info *sbi = SBI(inode->i_sb); - inode->i_op = NULL; inode->i_mode = 0; inode->i_nlink = 0; - inode->i_size = 0; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; inode->i_blksize = 1024; @@ -484,9 +480,6 @@ inode->i_nlink = 2; return; } - - /* need dummy inode operations .... */ - inode->i_op = &capifs_inode_operations; ino -= 2; if ( ino >= sbi->max_ncci ) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/t1isa.c Sun Oct 8 10:50:17 2000 +++ linux/drivers/isdn/avmb1/t1isa.c Fri Nov 17 11:16:21 2000 @@ -1,11 +1,19 @@ /* - * $Id: t1isa.c,v 1.13 2000/08/04 15:36:31 calle Exp $ + * $Id: t1isa.c,v 1.15 2000/11/01 14:05:02 calle Exp $ * * Module for AVM T1 HEMA-card. * * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) * * $Log: t1isa.c,v $ + * 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. + * - avm_cs.c, let it work with newer pcmcia-cs. + * + * Revision 1.14 2000/10/10 17:44:19 kai + * changes from/for 2.2.18 + * * Revision 1.13 2000/08/04 15:36:31 calle * copied wrong from file to file :-( * @@ -85,13 +93,14 @@ #include #include #include +#include #include #include "capicmd.h" #include "capiutil.h" #include "capilli.h" #include "avmcard.h" -static char *revision = "$Revision: 1.13 $"; +static char *revision = "$Revision: 1.15 $"; /* ------------------------------------------------------------- */ @@ -145,7 +154,7 @@ cli(); /* board reset */ t1outp(base, T1_RESETBOARD, 0xf); - udelay(100 * 1000); + mdelay(100); dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */ /* write config */ @@ -157,18 +166,18 @@ t1outp(base, ((base >> 4)) & 0x3, cregs[7]); restore_flags(flags); - udelay(100 * 1000); + mdelay(100); t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); - udelay(10 * 1000); + mdelay(10); t1outp(base, T1_FASTLINK+T1_RESETLINK, 1); t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1); - udelay(100 * 1000); + mdelay(100); t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); - udelay(10 * 1000); + mdelay(10); t1outp(base, T1_FASTLINK+T1_ANALYSE, 0); - udelay(5 * 1000); + mdelay(5); t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0); if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */ @@ -200,7 +209,7 @@ struct sk_buff *skb; unsigned ApplId; - signed MsgLen; + unsigned MsgLen; unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; @@ -588,20 +597,20 @@ /* ------------------------------------------------------------- */ static struct capi_driver t1isa_driver = { - "t1isa", - "0.0", - t1isa_load_firmware, - t1isa_reset_ctr, - t1isa_remove_ctr, - b1_register_appl, - b1_release_appl, - t1isa_send_message, - - t1isa_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ + name: "t1isa", + revision: "0.0", + load_firmware: t1isa_load_firmware, + reset_ctr: t1isa_reset_ctr, + remove_ctr: t1isa_remove_ctr, + register_appl: b1_register_appl, + release_appl: b1_release_appl, + send_message: t1isa_send_message, + + procinfo: t1isa_procinfo, + ctr_read_proc: b1ctl_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - t1isa_add_card, + add_card: t1isa_add_card, }; #ifdef MODULE diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c --- v2.4.0-test10/linux/drivers/isdn/avmb1/t1pci.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/avmb1/t1pci.c Fri Nov 17 11:16:21 2000 @@ -259,20 +259,20 @@ /* ------------------------------------------------------------- */ static struct capi_driver t1pci_driver = { - "t1pci", - "0.0", - b1dma_load_firmware, - b1dma_reset_ctr, - t1pci_remove_ctr, - b1dma_register_appl, - b1dma_release_appl, - b1dma_send_message, + name: "t1pci", + revision: "0.0", + load_firmware: b1dma_load_firmware, + reset_ctr: b1dma_reset_ctr, + remove_ctr: t1pci_remove_ctr, + register_appl: b1dma_register_appl, + release_appl: b1dma_release_appl, + send_message: b1dma_send_message, - t1pci_procinfo, - b1dmactl_read_proc, - 0, /* use standard driver_read_proc */ + procinfo: t1pci_procinfo, + ctr_read_proc: b1dmactl_read_proc, + driver_read_proc: 0, /* use standard driver_read_proc */ - 0, /* no add_card function */ + add_card: 0, /* no add_card function */ }; #ifdef MODULE diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/divert/divert_init.c linux/drivers/isdn/divert/divert_init.c --- v2.4.0-test10/linux/drivers/isdn/divert/divert_init.c Wed Aug 25 15:18:08 1999 +++ linux/drivers/isdn/divert/divert_init.c Fri Nov 17 11:16:20 2000 @@ -1,5 +1,5 @@ /* - * $Id: divert_init.c,v 1.4 1999/08/22 20:26:32 calle Exp $ + * $Id: divert_init.c,v 1.5 2000/11/13 22:51:47 kai Exp $ * * Module init for DSS1 diversion services for i4l. * @@ -18,22 +18,6 @@ * 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. - * - * $Log: divert_init.c,v $ - * Revision 1.4 1999/08/22 20:26:32 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/07/05 20:21:39 werner - * changes to use diversion sources for all kernel versions. - * removed static device, only proc filesystem used - * - * Revision 1.2 1999/07/04 21:37:30 werner - * Ported from kernel version 2.0 - * - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c --- v2.4.0-test10/linux/drivers/isdn/divert/divert_procfs.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/divert/divert_procfs.c Fri Nov 17 11:16:20 2000 @@ -1,5 +1,5 @@ /* - * $Id: divert_procfs.c,v 1.9 2000/08/20 07:40:14 keil Exp $ + * $Id: divert_procfs.c,v 1.10 2000/11/13 22:51:47 kai Exp $ * * Filesystem handling for the diversion supplementary services. * @@ -18,38 +18,6 @@ * 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. - * - * $Log: divert_procfs.c,v $ - * Revision 1.9 2000/08/20 07:40:14 keil - * changes from 2.4 - * - * Revision 1.8 2000/03/03 16:37:11 kai - * incorporated some cosmetic changes from the official kernel tree back - * into CVS - * - * Revision 1.7 2000/03/02 00:11:06 werner - * - * Changes related to procfs for 2.3.48 - * - * Revision 1.6 2000/02/14 19:23:03 werner - * - * Changed handling of proc filesystem tables to a more portable version - * - * Revision 1.5 1999/09/14 20:31:01 werner - * - * Removed obsoleted functions for proc fs and synced with new ones. - * - * Revision 1.4 1999/08/06 07:42:48 calle - * Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels. - * - * Revision 1.3 1999/07/05 20:21:41 werner - * changes to use diversion sources for all kernel versions. - * removed static device, only proc filesystem used - * - * Revision 1.2 1999/07/04 21:37:31 werner - * Ported from kernel version 2.0 - * - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/divert/isdn_divert.c linux/drivers/isdn/divert/isdn_divert.c --- v2.4.0-test10/linux/drivers/isdn/divert/isdn_divert.c Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/divert/isdn_divert.c Fri Nov 17 11:16:20 2000 @@ -1,5 +1,5 @@ /* - * $Id: isdn_divert.c,v 1.5 1999/08/31 11:20:04 paul Exp $ + * $Id: isdn_divert.c,v 1.6 2000/11/13 22:51:47 kai Exp $ * * DSS1 main diversion supplementary handling for i4l. * @@ -18,25 +18,6 @@ * 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. - * - * $Log: isdn_divert.c,v $ - * Revision 1.5 1999/08/31 11:20:04 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.4 1999/08/25 20:02:21 werner - * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts - * with existing software definitions. (PtP incomplete called party number) - * - * Revision 1.3 1999/08/22 20:26:35 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.2 1999/07/04 21:37:32 werner - * Ported from kernel version 2.0 - * - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/divert/isdn_divert.h linux/drivers/isdn/divert/isdn_divert.h --- v2.4.0-test10/linux/drivers/isdn/divert/isdn_divert.h Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/divert/isdn_divert.h Fri Nov 17 11:16:20 2000 @@ -1,5 +1,5 @@ /* - * $Id: isdn_divert.h,v 1.4 1999/09/02 13:24:12 paul Exp $ + * $Id: isdn_divert.h,v 1.5 2000/11/13 22:51:47 kai Exp $ * * Header for the diversion supplementary ioctl interface. * @@ -18,19 +18,6 @@ * 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. - * - * $Log: isdn_divert.h,v $ - * Revision 1.4 1999/09/02 13:24:12 paul - * cosmetics; text following #endif is not ANSI C - * - * Revision 1.3 1999/08/22 20:26:37 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.2 1999/07/04 21:37:33 werner - * Ported from kernel version 2.0 * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c --- v2.4.0-test10/linux/drivers/isdn/hisax/config.c Mon Aug 21 07:49:02 2000 +++ linux/drivers/isdn/hisax/config.c Fri Nov 17 11:16:21 2000 @@ -484,7 +484,7 @@ } i++; } - if (strlen(str)) { + if (str && *str) { strcpy(HiSaxID, str); HiSax_id = HiSaxID; } else { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c --- v2.4.0-test10/linux/drivers/isdn/hisax/hfc_pci.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/isdn/hisax/hfc_pci.c Wed Nov 8 19:09:49 2000 @@ -31,6 +31,7 @@ #include "isdnl1.h" #include #include +#include extern const char *CardType[]; @@ -1631,11 +1632,9 @@ #endif /* CONFIG_PCI */ -__initfunc(int - setup_hfcpci(struct IsdnCard *card)) +int __init setup_hfcpci(struct IsdnCard *card) { struct IsdnCardState *cs = card->cs; - unsigned short cmd; char tmp[64]; int i; struct pci_dev *tmp_hfcpci = NULL; @@ -1645,15 +1644,11 @@ #endif strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); -#if CONFIG_PCI +#ifdef CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; if (cs->typ == ISDN_CTYPE_HFC_PCI) { - if (!pci_present()) { - printk(KERN_ERR "HFC-PCI: no PCI bus present\n"); - return (0); - } i = 0; while (id_list[i].vendor_id) { tmp_hfcpci = pci_find_device(id_list[i].vendor_id, @@ -1686,41 +1681,6 @@ printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); return (0); } -#ifdef notdef - if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) { - printk(KERN_WARNING "HFC-PCI shared mem address will be corrected\n"); - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - 0x0103); /* set SERR */ - pcibios_read_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - &cmd); - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - cmd & ~2); - (int) cs->hw.hfcpci.pci_io &= ~(PAGE_SIZE - 1); - pcibios_write_config_dword(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_BASE_ADDRESS_1, - (int) cs->hw.hfcpci.pci_io); - pcibios_write_config_word(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_COMMAND, - cmd); - pcibios_read_config_dword(cs->hw.hfcpci.pci_bus, - cs->hw.hfcpci.pci_device_fn, - PCI_BASE_ADDRESS_1, - (void *) &cs->hw.hfcpci.pci_io); - if (((int) cs->hw.hfcpci.pci_io & (PAGE_SIZE - 1))) { - printk(KERN_WARNING "HFC-PCI unable to align address %x\n", (unsigned) cs->hw.hfcpci.pci_io); - return (0); - } - dev_hfcpci->resource[1].start = (int) cs->hw.hfcpci.pci_io; - } -#endif if (!cs->hw.hfcpci.pci_io) { printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); return (0); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hisax/nj_s.c linux/drivers/isdn/hisax/nj_s.c --- v2.4.0-test10/linux/drivers/isdn/hisax/nj_s.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/nj_s.c Thu Nov 16 12:51:27 2000 @@ -148,11 +148,10 @@ return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - for ( ;; ) - { - #if CONFIG_PCI + for ( ;; ) + { if (!pci_present()) { printk(KERN_ERR "Netjet: no PCI bus present\n"); return(0); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hisax/nj_u.c linux/drivers/isdn/hisax/nj_u.c --- v2.4.0-test10/linux/drivers/isdn/hisax/nj_u.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/nj_u.c Thu Nov 16 12:51:27 2000 @@ -150,11 +150,10 @@ return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); - for ( ;; ) - { - #if CONFIG_PCI + for ( ;; ) + { if (!pci_present()) { printk(KERN_ERR "NETspider-U: no PCI bus present\n"); return(0); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hisax/w6692.c linux/drivers/isdn/hisax/w6692.c --- v2.4.0-test10/linux/drivers/isdn/hisax/w6692.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hisax/w6692.c Fri Nov 17 11:16:21 2000 @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.7 2000/06/26 08:59:15 keil Exp $ +/* $Id: w6692.c,v 1.8 2000/09/07 20:33:30 werner Exp $ * * w6692.c Winbond W6692 specific routines * @@ -46,7 +46,7 @@ extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.7 $"; +const char *w6692_revision = "$Revision: 1.8 $"; #define DBUSY_TIMER_VALUE 80 @@ -1056,6 +1056,7 @@ cs->BC_Send_Data = &W6692B_fill_fifo; cs->cardmsg = &w6692_card_msg; cs->irq_func = &W6692_interrupt; + cs->irq_flags |= SA_SHIRQ; W6692Version(cs, "W6692:"); printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/boardergo.c linux/drivers/isdn/hysdn/boardergo.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/boardergo.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/isdn/hysdn/boardergo.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: boardergo.c,v 1.3 2000/05/17 11:41:30 ualbrecht Exp $ +/* $Id: boardergo.c,v 1.4 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, specific routines for ergo type boards. * @@ -23,18 +23,6 @@ * 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. - * - * $Log: boardergo.c,v $ - * Revision 1.3 2000/05/17 11:41:30 ualbrecht - * CAPI 2.0 support added - * - * Revision 1.2 2000/04/23 14:18:36 kai - * merge changes from main tree - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/boardergo.h linux/drivers/isdn/hysdn/boardergo.h --- v2.4.0-test10/linux/drivers/isdn/hysdn/boardergo.h Tue Feb 15 11:40:43 2000 +++ linux/drivers/isdn/hysdn/boardergo.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: boardergo.h,v 1.1 2000/02/10 19:44:30 werner Exp $ +/* $Id: boardergo.h,v 1.2 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..). * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -18,12 +18,6 @@ * 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. - * - * $Log: boardergo.h,v $ - * Revision 1.1 2000/02/10 19:44:30 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hycapi.c linux/drivers/isdn/hysdn/hycapi.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hycapi.c Tue Aug 22 09:06:31 2000 +++ linux/drivers/isdn/hysdn/hycapi.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hycapi.c,v 1.6 2000/07/25 08:07:42 ualbrecht Exp $ +/* $Id: hycapi.c,v 1.7 2000/11/13 22:51:47 kai Exp $ * * Linux driver for HYSDN cards, CAPI2.0-Interface. * written by Ulrich Albrecht (u.albrecht@hypercope.de) for Hypercope GmbH @@ -19,26 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: hycapi.c,v $ - * Revision 1.6 2000/07/25 08:07:42 ualbrecht - * Fixed stupid re-registering bug resulting in system-freeze - * - * Revision 1.5 2000/06/18 16:08:18 keil - * 2.4 PCI changes and some cosmetics - * - * Revision 1.4 2000/06/13 09:13:06 ualbrecht - * Changed internal application handling: Registration is now deferred - * until a CAPI-message is actually sent to the controller (no good - * wasting memory on the card if it's never used anyways). - * Module will now unload more gracefully. - * - * Revision 1.2 2000/05/22 10:31:22 ualbrecht - * Parameter-checking for app-registration fixed - * - * Revision 1.1 2000/05/17 11:34:30 ualbrecht - * Initial release - * - * */ #define __NO_VERSION__ @@ -61,7 +41,7 @@ #include "hysdn_defs.h" #include -static char hycapi_revision[]="$Revision: 1.6 $"; +static char hycapi_revision[]="$Revision: 1.7 $"; typedef struct _hycapi_appl { unsigned int ctrl_mask; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_boot.c linux/drivers/isdn/hysdn/hysdn_boot.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_boot.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hysdn/hysdn_boot.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_boot.c,v 1.3 2000/05/17 11:41:30 ualbrecht Exp $ +/* $Id: hysdn_boot.c,v 1.4 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, specific routines for booting and pof handling. * @@ -19,18 +19,6 @@ * 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. - * - * $Log: hysdn_boot.c,v $ - * Revision 1.3 2000/05/17 11:41:30 ualbrecht - * CAPI 2.0 support added - * - * Revision 1.2 2000/04/23 14:18:36 kai - * merge changes from main tree - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_defs.h linux/drivers/isdn/hysdn/hysdn_defs.h --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_defs.h Tue Aug 22 09:06:31 2000 +++ linux/drivers/isdn/hysdn/hysdn_defs.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_defs.h,v 1.3 2000/06/13 09:14:26 ualbrecht Exp $ +/* $Id: hysdn_defs.h,v 1.4 2000/11/13 22:51: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 @@ -18,18 +18,6 @@ * 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. - * - * $Log: hysdn_defs.h,v $ - * Revision 1.3 2000/06/13 09:14:26 ualbrecht - * Removed obsolete struct for CAPI-application tracking. - * - * Revision 1.2 2000/05/17 11:41:30 ualbrecht - * CAPI 2.0 support added - * - * Revision 1.1 2000/02/10 19:44:30 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_init.c linux/drivers/isdn/hysdn/hysdn_init.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_init.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hysdn/hysdn_init.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_init.c,v 1.5 2000/08/20 16:46:09 keil Exp $ +/* $Id: hysdn_init.c,v 1.6 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, init functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -19,24 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: hysdn_init.c,v $ - * Revision 1.5 2000/08/20 16:46:09 keil - * Changes for 2.4 - * - * Revision 1.4 2000/06/18 16:08:18 keil - * 2.4 PCI changes and some cosmetics - * - * Revision 1.3 2000/06/13 09:15:07 ualbrecht - * Module will now unload more gracefully. - * - * Revision 1.2 2000/05/17 11:41:30 ualbrecht - * CAPI 2.0 support added - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * - * */ #include @@ -49,7 +31,7 @@ #include "hysdn_defs.h" -static char *hysdn_init_revision = "$Revision: 1.5 $"; +static char *hysdn_init_revision = "$Revision: 1.6 $"; int cardmax; /* number of found cards */ hysdn_card *card_root = NULL; /* pointer to first card */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_net.c linux/drivers/isdn/hysdn/hysdn_net.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_net.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hysdn/hysdn_net.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_net.c,v 1.7 2000/05/23 06:48:54 ualbrecht Exp $ +/* $Id: hysdn_net.c,v 1.8 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, net (ethernet type) handling routines. * @@ -23,33 +23,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: hysdn_net.c,v $ - * Revision 1.7 2000/05/23 06:48:54 ualbrecht - * Reverted last change in dev->name assignment (broken netdevice.h in 2.3.99pre6?) - * - * Revision 1.6 2000/05/17 11:43:03 ualbrecht - * Fixed a NULL-pointer kernel-oops assigning the device-name - * - * Revision 1.5 2000/05/06 00:52:38 kai - * merged changes from kernel tree - * fixed timer and net_device->name breakage - * - * Revision 1.4 2000/04/23 14:18:36 kai - * merge changes from main tree - * - * Revision 1.3 2000/02/14 19:24:12 werner - * - * Removed superflous file - * - * Revision 1.2 2000/02/13 17:32:19 werner - * - * Added support for new network layer of 2.3.43 and 44 kernels and tested driver. - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * - * */ #define __NO_VERSION__ @@ -65,7 +38,7 @@ #include "hysdn_defs.h" /* store the actual version for log reporting */ -char *hysdn_net_revision = "$Revision: 1.7 $"; +char *hysdn_net_revision = "$Revision: 1.8 $"; #define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_pof.h linux/drivers/isdn/hysdn/hysdn_pof.h --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_pof.h Tue Feb 15 11:40:43 2000 +++ linux/drivers/isdn/hysdn/hysdn_pof.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_pof.h,v 1.1 2000/02/10 19:44:30 werner Exp $ +/* $Id: hysdn_pof.h,v 1.2 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, definitions used for handling pof-files. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -18,12 +18,6 @@ * 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. - * - * $Log: hysdn_pof.h,v $ - * Revision 1.1 2000/02/10 19:44:30 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_procconf.c linux/drivers/isdn/hysdn/hysdn_procconf.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_procconf.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hysdn/hysdn_procconf.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_procconf.c,v 1.7 2000/08/20 16:46:09 keil Exp $ +/* $Id: hysdn_procconf.c,v 1.8 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -19,33 +19,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: hysdn_procconf.c,v $ - * Revision 1.7 2000/08/20 16:46:09 keil - * Changes for 2.4 - * - * Revision 1.6 2000/05/17 11:41:30 ualbrecht - * CAPI 2.0 support added - * - * Revision 1.5 2000/04/23 14:18:36 kai - * merge changes from main tree - * - * Revision 1.4 2000/03/03 16:37:12 kai - * incorporated some cosmetic changes from the official kernel tree back - * into CVS - * - * Revision 1.3 2000/03/02 00:11:07 werner - * - * Changes related to procfs for 2.3.48 - * - * Revision 1.2 2000/02/14 19:23:03 werner - * - * Changed handling of proc filesystem tables to a more portable version - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * - * */ #define __NO_VERSION__ @@ -58,7 +31,7 @@ #include "hysdn_defs.h" -static char *hysdn_procconf_revision = "$Revision: 1.7 $"; +static char *hysdn_procconf_revision = "$Revision: 1.8 $"; #define INFO_OUT_LEN 80 /* length of info line including lf */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_proclog.c linux/drivers/isdn/hysdn/hysdn_proclog.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_proclog.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/hysdn/hysdn_proclog.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_proclog.c,v 1.7 2000/08/20 16:46:09 keil Exp $ +/* $Id: hysdn_proclog.c,v 1.8 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, /proc/net filesystem log functions. * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH @@ -18,33 +18,6 @@ * 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. - * - * $Log: hysdn_proclog.c,v $ - * Revision 1.7 2000/08/20 16:46:09 keil - * Changes for 2.4 - * - * Revision 1.6 2000/06/18 16:08:18 keil - * 2.4 PCI changes and some cosmetics - * - * Revision 1.5 2000/04/23 14:18:36 kai - * merge changes from main tree - * - * Revision 1.4 2000/03/03 16:37:12 kai - * incorporated some cosmetic changes from the official kernel tree back - * into CVS - * - * Revision 1.3 2000/03/02 00:11:07 werner - * - * Changes related to procfs for 2.3.48 - * - * Revision 1.2 2000/02/14 19:23:03 werner - * - * Changed handling of proc filesystem tables to a more portable version - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_sched.c linux/drivers/isdn/hysdn/hysdn_sched.c --- v2.4.0-test10/linux/drivers/isdn/hysdn/hysdn_sched.c Tue Aug 22 09:06:31 2000 +++ linux/drivers/isdn/hysdn/hysdn_sched.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: hysdn_sched.c,v 1.3 2000/05/17 11:41:30 ualbrecht Exp $ +/* $Id: hysdn_sched.c,v 1.4 2000/11/13 22:51:47 kai Exp $ * Linux driver for HYSDN cards, scheduler routines for handling exchange card <-> pc. * @@ -19,18 +19,6 @@ * 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. - * - * $Log: hysdn_sched.c,v $ - * Revision 1.3 2000/05/17 11:41:30 ualbrecht - * CAPI 2.0 support added - * - * Revision 1.2 2000/04/23 14:18:36 kai - * merge changes from main tree - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c --- v2.4.0-test10/linux/drivers/isdn/icn/icn.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/icn/icn.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: icn.c,v 1.63 2000/05/06 00:52:39 kai Exp $ +/* $Id: icn.c,v 1.65 2000/11/13 22:51:48 kai Exp $ * ISDN low-level module for the ICN active ISDN-Card. * @@ -18,224 +18,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: icn.c,v $ - * Revision 1.63 2000/05/06 00:52:39 kai - * merged changes from kernel tree - * fixed timer and net_device->name breakage - * - * Revision 1.62 1999/09/06 07:29:35 fritz - * Changed my mail-address. - * - * Revision 1.61 1999/09/03 14:06:58 fritz - * Fixed a memory leak. - * - * Revision 1.60 1999/08/31 11:20:32 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.59 1999/08/28 22:10:55 keil - * __setup function should be static - * - * Revision 1.58 1999/08/25 16:44:17 keil - * Support for new __setup function - * - * Revision 1.57 1999/07/06 16:15:30 detabc - * remove unused messages - * - * Revision 1.56 1999/04/12 13:15:07 fritz - * Fixed a cast. - * - * Revision 1.55 1999/04/12 12:34:02 fritz - * Changes from 2.0 tree. - * - * Revision 1.54 1999/01/05 18:29:39 he - * merged remaining schedule_timeout() changes from 2.1.127 - * - * Revision 1.53 1998/06/17 19:51:28 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.52 1998/05/20 19:29:58 tsbogend - * fixed bug introduced by changes for new BSENT callback - * - * Revision 1.51 1998/03/07 22:29:55 fritz - * Adapted Detlef's chenges for 2.1. - * - * Revision 1.49 1998/02/13 11:14:15 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.48 1997/10/10 15:56:14 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.47 1997/10/01 09:21:51 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.46 1997/08/21 22:38:33 fritz - * Fixed a typo. - * - * Revision 1.45 1997/06/21 10:42:06 fritz - * Added availability to select leased mode on only one channel. - * - * Revision 1.44 1997/03/30 16:51:26 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.43 1997/03/21 18:27:04 fritz - * Corrected parsing of incoming setup. - * - * Revision 1.42 1997/03/05 21:13:18 fritz - * Bugfix: sndcount was not reset on hangup. - * - * Revision 1.41 1997/02/24 23:34:29 fritz - * Bugfix in Layer1 error-recovery. - * - * Revision 1.40 1997/02/23 23:34:45 fritz - * Minor bugfixes in debugging code. - * - * Revision 1.39 1997/02/23 16:21:56 fritz - * Bugfix: Check for NULL pointer in icn_parse_status(). - * - * Revision 1.38 1997/02/11 18:29:31 fritz - * Bugfix in D64S initialization. - * - * Revision 1.37 1997/02/10 22:43:20 fritz - * Added plan and screen elements on ISDN_STAT_ICALL - * - * Revision 1.36 1997/02/10 21:31:20 fritz - * Changed setup-interface (incoming and outgoing). - * - * Revision 1.35 1997/02/10 10:10:28 fritz - * Changes for Kernel 2.1.X compatibility. - * Enhanced initialization, can recover from - * misconfiguration by other autoprobing drivers. - * - * Revision 1.34 1997/01/29 22:34:44 fritz - * Cleanup, Corrected D64S setup of 2nd channel. - * - * Revision 1.33 1996/12/05 20:31:48 tsbogend - * added handling of L2: DATA LINK LOST messages - * - * Revision 1.32 1996/11/14 23:49:18 fritz - * Bugfix: copy_to_user/copy_from_user mismatch in debugging-ioctl. - * - * Revision 1.31 1996/11/13 02:36:25 fritz - * Fixed a race condition in writecmd. - * Some optimizations and cleanup. - * - * Revision 1.30 1996/10/22 23:14:09 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.29 1996/08/29 20:34:54 fritz - * Bugfix in send queue management: - * sndcount was not updated correctly. - * Minor Bugfixes. - * - * Revision 1.28 1996/06/28 17:02:53 fritz - * replaced memcpy_fromfs_toio. - * - * Revision 1.27 1996/06/25 18:38:59 fritz - * Fixed function name in error message. - * - * Revision 1.26 1996/06/24 17:20:35 fritz - * Bugfixes in pollbchan_send(): - * - Using lock field of skbuff breaks networking. - * - Added channel locking - * - changed dequeuing scheme. - * Eliminated misc. compiler warnings. - * - * Revision 1.25 1996/06/11 22:53:35 tsbogend - * fixed problem with large array on stack - * made the driver working on Linux/alpha - * - * Revision 1.24 1996/06/06 13:58:33 fritz - * Changed code to be architecture independent - * - * Revision 1.23 1996/06/03 19:59:00 fritz - * Fixed typos. - * - * Revision 1.22 1996/05/17 15:46:41 fritz - * Removed own queue management. - * Changed queue management to use sk_buffs. - * - * Revision 1.21 1996/05/02 04:01:20 fritz - * Bugfix: - * - icn_addcard() evaluated wrong driverId. - * - * Revision 1.20 1996/05/02 00:40:27 fritz - * Major rewrite to support more than one card - * with a single module. - * Support for new firmware. - * - * Revision 1.19 1996/04/21 17:43:32 fritz - * Changes for Support of new Firmware BRV3.02 - * - * Revision 1.18 1996/04/20 16:50:26 fritz - * Fixed status-buffer overrun. - * Misc. typos - * - * Revision 1.17 1996/02/11 02:39:04 fritz - * Increased Buffer for status-messages. - * Removed conditionals for HDLC-firmware. - * - * Revision 1.16 1996/01/22 05:01:55 fritz - * Revert to GPL. - * - * Revision 1.15 1996/01/10 20:57:39 fritz - * Bugfix: Loading firmware twice caused the device stop working. - * - * Revision 1.14 1995/12/18 18:23:37 fritz - * Support for ICN-2B Cards. - * Change for supporting user-settable service-octet. - * - * Revision 1.13 1995/10/29 21:41:07 fritz - * Added support for DriverId's, added Jan's patches for Kernel versions. - * - * Revision 1.12 1995/04/29 13:07:35 fritz - * Added support for new Euro-ISDN-firmware - * - * Revision 1.11 1995/04/23 13:40:45 fritz - * Added support for SPV's. - * Changed Dial-Command to support MSN's on DSS1-Lines. - * - * Revision 1.10 1995/03/25 23:23:24 fritz - * Changed configurable Ports, to allow settings for DIP-Switch Cardversions. - * - * Revision 1.9 1995/03/25 23:17:30 fritz - * Fixed race-condition in pollbchan_send - * - * Revision 1.8 1995/03/15 12:49:44 fritz - * Added support for SPV's - * Split pollbchan_work for calling send-routine directly - * - * Revision 1.7 1995/02/20 03:48:03 fritz - * Added support of new request_region-function. - * Minor bugfixes. - * - * Revision 1.6 1995/01/31 15:48:45 fritz - * Added Cause-Messages to be signaled to upper layers. - * Added Revision-Info on load. - * - * Revision 1.5 1995/01/29 23:34:59 fritz - * Added stopdriver() and appropriate calls. - * Changed printk-statements to support loglevels. - * - * Revision 1.4 1995/01/09 07:40:46 fritz - * Added GPL-Notice - * - * Revision 1.3 1995/01/04 05:15:18 fritz - * Added undocumented "bootload-finished"-command in download-code - * to satisfy some brain-damaged icn card-versions. - * - * Revision 1.2 1995/01/02 02:14:45 fritz - * Misc Bugfixes - * - * Revision 1.1 1994/12/14 17:56:06 fritz - * Initial revision - * */ #include "icn.h" @@ -251,7 +33,7 @@ #undef MAP_DEBUG static char -*revision = "$Revision: 1.63 $"; +*revision = "$Revision: 1.65 $"; static int icn_addcard(int, char *, char *); @@ -1873,7 +1655,7 @@ portbase = ints[1]; if (ints[0] > 1) membase = ints[2]; - if (strlen(str)) { + if (str && *str) { strcpy(sid, str); icn_id = sid; if ((p = strchr(sid, ','))) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h --- v2.4.0-test10/linux/drivers/isdn/icn/icn.h Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/icn/icn.h Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: icn.h,v 1.29 1999/09/06 07:29:35 fritz Exp $ +/* $Id: icn.h,v 1.30 2000/11/13 22:51:48 kai Exp $ * ISDN lowlevel-module for the ICN active ISDN-Card. * @@ -17,110 +17,6 @@ * 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. - * - * $Log: icn.h,v $ - * Revision 1.29 1999/09/06 07:29:35 fritz - * Changed my mail-address. - * - * Revision 1.28 1997/10/10 15:56:18 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.27 1997/10/01 09:21:56 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.26 1997/02/14 12:23:16 fritz - * Added support for new insmod parameter handling. - * - * Revision 1.25 1997/02/10 10:10:31 fritz - * Changes for Kernel 2.1.X compatibility. - * Enhanced initialization, can recover from - * misconfiguration by other autoprobing drivers. - * - * Revision 1.24 1997/01/29 22:34:46 fritz - * Cleanup, Corrected D64S setup of 2nd channel. - * - * Revision 1.23 1996/12/17 18:47:55 tsbogend - * changed timeouts from absolute numbers to HZ based values - * - * Revision 1.22 1996/11/13 02:37:33 fritz - * Added delay include. - * - * Revision 1.21 1996/08/29 20:35:57 fritz - * Speed up B-Channel polling interval. - * - * Revision 1.20 1996/06/24 17:20:37 fritz - * Bugfixes in pollbchan_send(): - * - Using lock field of skbuff breaks networking. - * - Added channel locking - * - changed dequeuing scheme. - * Eliminated misc. compiler warnings. - * - * Revision 1.19 1996/06/06 13:58:35 fritz - * Changed code to be architecture independent - * - * Revision 1.18 1996/06/03 19:59:30 fritz - * Removed include of config.h - * - * Revision 1.17 1996/05/18 00:47:04 fritz - * Removed callback debug code. - * - * Revision 1.16 1996/05/17 15:46:43 fritz - * Removed own queue management. - * Changed queue management to use sk_buffs. - * - * Revision 1.15 1996/05/02 04:01:57 fritz - * Removed ICN_MAXCARDS - * - * Revision 1.14 1996/05/02 00:40:29 fritz - * Major rewrite to support more than one card - * with a single module. - * Support for new firmware. - * - * Revision 1.13 1996/04/20 16:51:41 fritz - * Increased status buffer. - * Misc. typos - * - * Revision 1.12 1996/01/22 05:01:22 fritz - * Revert to GPL. - * - * Revision 1.11 1995/12/18 18:25:00 fritz - * Support for ICN-2B Cards. - * Change for supporting user-settable service-octet. - * - * Revision 1.10 1995/10/29 21:43:10 fritz - * Added support for leased lines. - * - * Revision 1.9 1995/04/23 13:42:10 fritz - * Added some constants for distinguishing 1TR6 and DSS1 - * - * Revision 1.8 1995/03/25 23:18:55 fritz - * Changed ICN_PORTLEN to reflect correct number of ports. - * - * Revision 1.7 1995/03/15 12:52:06 fritz - * Some cleanup - * - * Revision 1.6 1995/02/20 03:49:22 fritz - * Fixed ICN_MAX_SQUEUE to correctly reflect outstanding bytes, not number - * of buffers. - * - * Revision 1.5 1995/01/29 23:36:50 fritz - * Minor cleanup. - * - * Revision 1.4 1995/01/09 07:41:20 fritz - * Added GPL-Notice - * - * Revision 1.3 1995/01/04 05:14:20 fritz - * removed include of linux/asm/string.h for compiling with Linux 1.1.76 - * - * Revision 1.2 1995/01/02 02:15:57 fritz - * Misc. Bugfixes - * - * Revision 1.1 1994/12/14 18:02:38 fritz - * Initial revision * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/isdn_cards.c linux/drivers/isdn/isdn_cards.c --- v2.4.0-test10/linux/drivers/isdn/isdn_cards.c Sun Aug 6 12:43:42 2000 +++ linux/drivers/isdn/isdn_cards.c Sat Nov 11 18:58:03 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_cards.c,v 1.11 2000/05/11 22:29:20 kai Exp $ +/* $Id: isdn_cards.c,v 1.13 2000/10/28 23:03:38 kai Exp $ * Linux ISDN subsystem, initialization for non-modularized drivers. * @@ -42,6 +42,9 @@ 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 void diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c --- v2.4.0-test10/linux/drivers/isdn/isdn_common.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/isdn/isdn_common.c Sat Nov 11 18:58:03 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_common.c,v 1.111 2000/08/20 07:40:14 keil Exp $ +/* $Id: isdn_common.c,v 1.113 2000/11/01 17:54:00 detabc Exp $ * Linux ISDN subsystem, common used functions (linklevel). * @@ -48,7 +48,7 @@ isdn_dev *dev; -static char *isdn_revision = "$Revision: 1.111 $"; +static char *isdn_revision = "$Revision: 1.113 $"; extern char *isdn_net_revision; extern char *isdn_tty_revision; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c --- v2.4.0-test10/linux/drivers/isdn/isdn_net.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/isdn_net.c Sat Nov 11 18:58:03 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_net.c,v 1.135 2000/08/10 22:52:46 kai Exp $ +/* $Id: isdn_net.c,v 1.140 2000/11/01 17:54:01 detabc Exp $ * Linux ISDN subsystem, network interfaces and related functions (linklevel). * @@ -181,7 +181,7 @@ int isdn_net_force_dial_lp(isdn_net_local *); static int isdn_net_start_xmit(struct sk_buff *, struct net_device *); -char *isdn_net_revision = "$Revision: 1.135 $"; +char *isdn_net_revision = "$Revision: 1.140 $"; /* * Code for raw-networking over ISDN @@ -190,7 +190,6 @@ static void isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason) { - if(skb) { u_short proto = ntohs(skb->protocol); @@ -704,6 +703,7 @@ i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel); if (i >= 0) { strcpy(dev->num[i], cmd.parm.setup.phone); + dev->usage[i] |= ISDN_USAGE_OUTGOING; isdn_info_update(); } printk(KERN_INFO "%s: dialing %d %s...\n", lp->name, @@ -1001,8 +1001,7 @@ /* * called from tq_immediate */ -static void -isdn_net_softint(void *private) +static void isdn_net_softint(void *private) { isdn_net_local *lp = private; struct sk_buff *skb; @@ -1086,9 +1085,7 @@ return isdn_ppp_xmit(skb, ndev); } #endif - nd = ((isdn_net_local *) ndev->priv)->netdev; - lp = isdn_net_get_locked_lp(nd); if (!lp) { printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name); @@ -1218,6 +1215,7 @@ buf = skb->data; isdn_dumppkt("S:", buf, skb->len, 40); #endif + if (!(lp->flags & ISDN_NET_CONNECTED)) { int chi; /* only do autodial if allowed by config */ @@ -1532,7 +1530,6 @@ lp->stats.rx_packets++; lp->stats.rx_bytes += skb->len; } - skb->dev = ndev; skb->pkt_type = PACKET_HOST; skb->mac.raw = skb->data; @@ -1615,6 +1612,7 @@ isdn_ppp_receive(lp->netdev, olp, skb); return; #endif + default: #ifdef CONFIG_ISDN_X25 /* try if there are generic sync_device receiver routines */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c --- v2.4.0-test10/linux/drivers/isdn/isdn_ppp.c Tue Aug 8 15:03:57 2000 +++ linux/drivers/isdn/isdn_ppp.c Fri Nov 17 11:16:20 2000 @@ -1,4 +1,4 @@ -/* $Id: isdn_ppp.c,v 1.77 2000/06/12 16:46:34 keil Exp $ +/* $Id: isdn_ppp.c,v 1.84 2000/11/13 22:51:46 kai Exp $ * * Linux ISDN subsystem, functions for synchronous PPP (linklevel). * @@ -36,8 +36,6 @@ #define PPP_IPX 0x002b #endif -/* set this if you use dynamic addressing */ - /* Prototypes */ static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot); static int isdn_ppp_closewait(int slot); @@ -46,7 +44,7 @@ static int isdn_ppp_if_get_unit(char *namebuf); static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *); static struct sk_buff *isdn_ppp_decompress(struct sk_buff *, - struct ippp_struct *,struct ippp_struct *,int proto); + struct ippp_struct *,struct ippp_struct *,int *proto); static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb,int proto); static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, @@ -85,7 +83,7 @@ static int isdn_ppp_bundle(struct ippp_struct *, int unit); #endif /* CONFIG_ISDN_MPP */ -char *isdn_ppp_revision = "$Revision: 1.77 $"; +char *isdn_ppp_revision = "$Revision: 1.84 $"; static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS]; @@ -849,15 +847,49 @@ } /* + * check for address/control field and skip if allowed + * retval != 0 -> discard packet silently + */ +static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb) +{ + if (skb->len < 1) + return -1; + + if (skb->data[0] == 0xff) { + if (skb->len < 2) + return -1; + + if (skb->data[1] != 0x03) + return -1; + + // skip address/control (AC) field + skb_pull(skb, 2); + } else { + if (is->pppcfg & SC_REJ_COMP_AC) + // if AC compression was not negotiated, but used, discard packet + return -1; + } + return 0; +} + +/* * get the PPP protocol header and pull skb + * retval < 0 -> discard packet silently */ static int isdn_ppp_strip_proto(struct sk_buff *skb) { int proto; + + if (skb->len < 1) + return -1; + if (skb->data[0] & 0x1) { + // protocol field is compressed proto = skb->data[0]; - skb_pull(skb, 1); /* protocol ID is only 8 bit */ + skb_pull(skb, 1); } else { + if (skb->len < 2) + return -1; proto = ((int) skb->data[0] << 8) + skb->data[1]; skb_pull(skb, 2); } @@ -874,6 +906,9 @@ int slot; int proto; + if (net_dev->local->master) + BUG(); // we're called with the master device always + slot = lp->ppp_slot; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot %d\n", lp->ppp_slot); @@ -887,122 +922,95 @@ (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len); isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } - if (net_dev->local->master) { - printk(KERN_WARNING "isdn_ppp_receive: net_dev != master\n"); - net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev; - } - if (skb->data[0] == 0xff && skb->data[1] == 0x03) - skb_pull(skb, 2); - else if (is->pppcfg & SC_REJ_COMP_AC) { - dev_kfree_skb(skb); - return; /* discard it silently */ - } - - proto = isdn_ppp_strip_proto(skb); + if (isdn_ppp_skip_ac(is, skb) < 0) { + kfree_skb(skb); + return; + } + proto = isdn_ppp_strip_proto(skb); + if (proto < 0) { + kfree_skb(skb); + return; + } + #ifdef CONFIG_ISDN_MPP - if (!(is->mpppcfg & SC_REJ_MP_PROT)) { - - if(is->compflags & SC_LINK_DECOMP_ON) { - if(proto == PPP_COMPFRAG) { - if(is->debug & 0x10) - printk(KERN_DEBUG "received single link compressed frame\n"); - skb = isdn_ppp_decompress(skb,is,NULL,proto); - if(!skb) - return; - proto = isdn_ppp_strip_proto(skb); - } - else - isdn_ppp_decompress(skb,is,NULL,proto); - } - - if (proto == PPP_MP) { - isdn_ppp_mp_receive(net_dev, lp, skb); - } - else - isdn_ppp_push_higher(net_dev, lp, skb, proto); - } else -#endif /* CONFIG_ISDN_MPP */ - isdn_ppp_push_higher(net_dev, lp, skb, proto); + if (is->compflags & SC_LINK_DECOMP_ON) { + skb = isdn_ppp_decompress(skb, is, NULL, &proto); + if (!skb) // decompression error + return; + } + + if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP + if (proto == PPP_MP) { + isdn_ppp_mp_receive(net_dev, lp, skb); + return; + } + } +#endif + isdn_ppp_push_higher(net_dev, lp, skb, proto); } /* - * push frame to higher layers + * we receive a reassembled frame, MPPP has been taken care of before. + * address/control and protocol have been stripped from the skb * note: net_dev has to be master net_dev */ static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto) { struct net_device *dev = &net_dev->dev; - struct ippp_struct *is; + struct ippp_struct *is, *mis; int slot; slot = lp->ppp_slot; if (slot < 0 || slot > ISDN_MAX_CHANNELS) { printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot %d\n", lp->ppp_slot); - kfree_skb(skb); - return; + goto drop_packet; } is = ippp_table[slot]; + + if (lp->master) { // FIXME? + slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot; + if (slot < 0 || slot > ISDN_MAX_CHANNELS) { + printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot %d\n", lp->ppp_slot); + goto drop_packet; + } + } + mis = ippp_table[slot]; + if (is->debug & 0x10) { printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto); isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot); } - - if(proto == PPP_COMP) { - if(!lp->master) - skb = isdn_ppp_decompress(skb,is,is,proto); - else - skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto); - - if(!skb) { - printk(KERN_DEBUG "ippp: compressed frame discarded!\n"); - return; - } - - proto = isdn_ppp_strip_proto(skb); - if (is->debug & 0x10) { - printk(KERN_DEBUG "RPostDecomp, skb %d %04x\n", (int) skb->len, proto); - isdn_ppp_frame_log("R-Decomp", skb->data, skb->len, 32,is->unit,lp->ppp_slot); - } - } - else if(is->compflags & SC_DECOMP_ON) { /* If decomp is ON */ - if(!lp->master) - isdn_ppp_decompress(skb,is,is,proto); - else - isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto); - } - + if (is->compflags & SC_DECOMP_ON) { + skb = isdn_ppp_decompress(skb, is, mis, &proto); + if (!skb) // decompression error + return; + } switch (proto) { case PPP_IPX: /* untested */ if (is->debug & 0x20) printk(KERN_DEBUG "isdn_ppp: IPX\n"); - skb->dev = dev; - skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IPX); break; + case PPP_IP: + if (is->debug & 0x20) + printk(KERN_DEBUG "isdn_ppp: IP\n"); + skb->protocol = htons(ETH_P_IP); + break; #ifdef CONFIG_ISDN_PPP_VJ case PPP_VJC_UNCOMP: if (is->debug & 0x20) printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) { printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n"); - net_dev->local->stats.rx_dropped++; - dev_kfree_skb(skb); - return; + goto drop_packet; } -#endif - case PPP_IP: - if (is->debug & 0x20) - printk(KERN_DEBUG "isdn_ppp: IP\n"); - skb->dev = dev; - skb->mac.raw = skb->data; skb->protocol = htons(ETH_P_IP); break; case PPP_VJC_COMP: if (is->debug & 0x20) printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n"); -#ifdef CONFIG_ISDN_PPP_VJ { struct sk_buff *skb_old = skb; int pkt_len; @@ -1010,32 +1018,22 @@ if (!skb) { printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); - net_dev->local->stats.rx_dropped++; - dev_kfree_skb(skb_old); - return; + skb = skb_old; + goto drop_packet; } - skb->dev = dev; skb_put(skb, skb_old->len + 128); memcpy(skb->data, skb_old->data, skb_old->len); - skb->mac.raw = skb->data; pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb_old->len); - dev_kfree_skb(skb_old); - if (pkt_len < 0) { - dev_kfree_skb(skb); - lp->stats.rx_dropped++; - return; - } + kfree_skb(skb_old); + if (pkt_len < 0) + goto drop_packet; + skb_trim(skb, pkt_len); skb->protocol = htons(ETH_P_IP); } -#else - printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n"); - lp->stats.rx_dropped++; - dev_kfree_skb(skb); - return; -#endif break; +#endif case PPP_CCP: case PPP_CCPFRAG: isdn_ppp_receive_ccp(net_dev,lp,skb,proto); @@ -1047,21 +1045,27 @@ /* fall through */ default: isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */ - dev_kfree_skb(skb); + kfree_skb(skb); return; } /* Reset hangup-timer */ lp->huptimer = 0; - netif_rx(skb); - /* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */ + skb->dev = dev; + skb->mac.raw = skb->data; + netif_rx(skb); + /* net_dev->local->stats.rx_packets++; done in isdn_net.c */ return; + + drop_packet: + net_dev->local->stats.rx_dropped++; + kfree_skb(skb); } /* * isdn_ppp_skb_push .. - * checks whether we have enough space at the beginning of the SKB + * checks whether we have enough space at the beginning of the skb * and allocs a new SKB if necessary */ static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len) @@ -1363,9 +1367,9 @@ static u32 isdn_ppp_mp_get_seq( int short_seq, struct sk_buff * skb, u32 last_seq ); -struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, +static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp, struct sk_buff * from, struct sk_buff * to ); -void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, +static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff * from, struct sk_buff * to ); static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb ); static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb ); @@ -2256,8 +2260,20 @@ is->reset->lastid++; } +/* + * decompress packet + * + * if master = 0, we're trying to uncompress an per-link compressed packet, + * as opposed to an compressed reconstructed-from-MPPP packet. + * proto is updated to protocol field of uncompressed packet. + * + * retval: decompressed packet, + * same packet if uncompressed, + * NULL if decompression error + */ + static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master, - int proto) + int *proto) { void *stat = NULL; struct isdn_ppp_compressor *ipc = NULL; @@ -2268,84 +2284,69 @@ unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; if(!master) { - /* - * single link decompression - */ - if(!is->link_decompressor) { - printk(KERN_ERR "ippp: no link decompressor defined!\n"); - dev_kfree_skb(skb); - return NULL; - } - if(!is->link_decomp_stat) { - printk(KERN_DEBUG "ippp: no link decompressor data allocated\n"); - dev_kfree_skb(skb); - return NULL; - } + // per-link decompression stat = is->link_decomp_stat; ipc = is->link_decompressor; ri = is; - } - else { - /* - * 'normal' or bundle-compression - */ - if(!master->decompressor) { - printk(KERN_ERR "ippp: no decompressor defined!\n"); - dev_kfree_skb(skb); - return NULL; - } - if(!master->decomp_stat) { - printk(KERN_DEBUG "ippp: no decompressor data allocated\n"); - dev_kfree_skb(skb); - return NULL; - } + } else { stat = master->decomp_stat; ipc = master->decompressor; ri = master; } - /* - printk(KERN_DEBUG "ippp: Decompress valid!\n"); - */ + if (!ipc) { + // no decompressor -> we can't decompress. + printk(KERN_DEBUG "ippp: no decompressor defined!\n"); + return skb; + } + if (!stat) // if we have a compressor, stat has been set as well + BUG(); + + if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) { + // compressed packets are compressed by their protocol type + + // Set up reset params for the decompressor + memset(&rsparm, 0, sizeof(rsparm)); + rsparm.data = rsdata; + rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; + + /* !!!HACK,HACK,HACK!!! 2048 is only assumed */ + skb_out = dev_alloc_skb(2048); + len = ipc->decompress(stat, skb, skb_out, &rsparm); + kfree_skb(skb); + if (len <= 0) { + switch(len) { + case DECOMP_ERROR: + ri->pppcfg |= SC_DC_ERROR; + printk(KERN_INFO "ippp: decomp wants reset %s params\n", + rsparm.valid ? "with" : "without"); + + isdn_ppp_ccp_reset_trans(ri, &rsparm); + break; + case DECOMP_FATALERROR: + ri->pppcfg |= SC_DC_FERROR; + /* Kick ipppd to recognize the error */ + isdn_ppp_ccp_kickup(ri); + break; + } + kfree_skb(skb_out); + return NULL; + } - if((master && proto == PPP_COMP) || (!master && proto == PPP_COMPFRAG) ) { - /* Set up reset params for the decompressor */ - memset(&rsparm, 0, sizeof(rsparm)); - rsparm.data = rsdata; - rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; - -/* !!!HACK,HACK,HACK!!! 2048 is only assumed */ - skb_out = dev_alloc_skb(2048); - len = ipc->decompress(stat,skb,skb_out, &rsparm); - dev_kfree_skb(skb); - if(len <= 0) { - /* Ok, some error */ - switch(len) { - case DECOMP_ERROR: - ri->pppcfg |= SC_DC_ERROR; - printk(KERN_INFO "ippp: decomp wants reset %s params\n", - rsparm.valid ? "with" : "without"); - - isdn_ppp_ccp_reset_trans(ri, &rsparm); - - break; - case DECOMP_FATALERROR: - ri->pppcfg |= SC_DC_FERROR; - /* Kick ipppd to recognize the error */ - isdn_ppp_ccp_kickup(ri); - break; - } - /* Did I see a leak here ? */ - dev_kfree_skb(skb_out); - return NULL; + if (isdn_ppp_skip_ac(ri, skb) < 0) { + kfree_skb(skb); + return NULL; + } + *proto = isdn_ppp_strip_proto(skb); + if (*proto < 0) { + kfree_skb(skb); + return NULL; } return skb_out; - } - else { - /* - printk(KERN_DEBUG "isdn_ppp: [%d] Calling incomp with this frame!\n",is->unit); - */ - ipc->incomp(stat,skb,proto); + } else { + // uncompressed packets are fed through the decompressor to + // update the decompressor state + ipc->incomp(stat, skb, *proto); return skb; } } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/isdnloop/isdnloop.c linux/drivers/isdn/isdnloop/isdnloop.c --- v2.4.0-test10/linux/drivers/isdn/isdnloop/isdnloop.c Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/isdnloop/isdnloop.c Fri Nov 17 11:16:21 2000 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.c,v 1.9 1999/09/06 07:29:36 fritz Exp $ +/* $Id: isdnloop.c,v 1.11 2000/11/13 22:51:50 kai Exp $ * ISDN low-level module implementing a dummy loop driver. * @@ -18,48 +18,13 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Log: isdnloop.c,v $ - * Revision 1.9 1999/09/06 07:29:36 fritz - * Changed my mail-address. - * - * Revision 1.8 1998/11/18 18:59:43 armin - * changes for 2.1.127 - * - * Revision 1.7 1998/10/30 18:58:03 he - * typecast to suppress a compiler warning - * - * Revision 1.6 1998/06/17 19:51:37 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.5 1998/04/14 20:59:32 he - * merged 2.1.94 changes - * - * Revision 1.4 1998/02/24 21:39:05 he - * L2_PROT_X25DTE / DCE - * additional state 17 and new internal signal messages "BCON_I" - * (for reliable connect confirmation primitive as needed by x.25 upper layer) - * Changes for new LL-HL interface - * - * Revision 1.3 1998/02/20 17:33:30 fritz - * Changes for recent kernels. - * - * Revision 1.2 1997/10/01 09:22:03 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.1 1997/03/24 23:02:04 fritz - * Added isdnloop driver. - * */ #include #include "isdnloop.h" static char -*revision = "$Revision: 1.9 $"; +*revision = "$Revision: 1.11 $"; static int isdnloop_addcard(char *); @@ -865,6 +830,7 @@ if (card->rcard[ch - 1]) { isdnloop_fake(card->rcard[ch - 1], "BCON_I", card->rch[ch - 1] + 1); + isdnloop_fake(card, "BCON_C", ch); } break; case 17: diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/isdnloop/isdnloop.h linux/drivers/isdn/isdnloop/isdnloop.h --- v2.4.0-test10/linux/drivers/isdn/isdnloop/isdnloop.h Sun Nov 7 16:34:00 1999 +++ linux/drivers/isdn/isdnloop/isdnloop.h Fri Nov 17 11:16:21 2000 @@ -1,4 +1,4 @@ -/* $Id: isdnloop.h,v 1.4 1999/09/06 07:29:36 fritz Exp $ +/* $Id: isdnloop.h,v 1.5 2000/11/13 22:51:50 kai Exp $ * Loopback lowlevel module for testing of linklevel. * @@ -17,21 +17,6 @@ * 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. - * - * $Log: isdnloop.h,v $ - * Revision 1.4 1999/09/06 07:29:36 fritz - * Changed my mail-address. - * - * Revision 1.3 1998/04/14 20:59:35 he - * merged 2.1.94 changes - * - * Revision 1.2 1997/10/01 09:22:07 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.1 1997/03/24 23:02:05 fritz - * Added isdnloop driver. * */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c --- v2.4.0-test10/linux/drivers/isdn/pcbit/drv.c Mon Aug 21 07:49:03 2000 +++ linux/drivers/isdn/pcbit/drv.c Wed Nov 8 17:09:49 2000 @@ -114,9 +114,9 @@ dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); if (!dev->b1) { printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); - kfree(dev); iounmap((unsigned char*)dev->sh_mem); release_mem_region(dev->ph_mem, 4096); + kfree(dev); return -ENOMEM; } @@ -124,9 +124,9 @@ if (!dev->b2) { printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); kfree(dev->b1); - kfree(dev); iounmap((unsigned char*)dev->sh_mem); release_mem_region(dev->ph_mem, 4096); + kfree(dev); return -ENOMEM; } @@ -148,9 +148,9 @@ { kfree(dev->b1); kfree(dev->b2); - kfree(dev); iounmap((unsigned char*)dev->sh_mem); release_mem_region(dev->ph_mem, 4096); + kfree(dev); dev_pcbit[board] = NULL; return -EIO; } @@ -170,9 +170,9 @@ free_irq(irq, dev); kfree(dev->b1); kfree(dev->b2); - kfree(dev); iounmap((unsigned char*)dev->sh_mem); release_mem_region(dev->ph_mem, 4096); + kfree(dev); dev_pcbit[board] = NULL; return -EIO; } @@ -201,9 +201,9 @@ free_irq(irq, dev); kfree(dev->b1); kfree(dev->b2); - kfree(dev); iounmap((unsigned char*)dev->sh_mem); release_mem_region(dev->ph_mem, 4096); + kfree(dev); dev_pcbit[board] = NULL; return -EIO; } @@ -239,9 +239,9 @@ del_timer(&dev->b2->fsm_timer); kfree(dev->b1); kfree(dev->b2); - kfree(dev); iounmap((unsigned char*)dev->sh_mem); release_mem_region(dev->ph_mem, 4096); + kfree(dev); } } #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/isdn/sc/debug.c linux/drivers/isdn/sc/debug.c --- v2.4.0-test10/linux/drivers/isdn/sc/debug.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/isdn/sc/debug.c Fri Nov 17 11:16:20 2000 @@ -1,5 +1,5 @@ /* - * $Id: debug.c,v 1.3 1997/10/01 09:22:20 fritz Exp $ + * $Id: debug.c,v 1.5 2000/11/12 15:29:37 kai Exp $ * Copyright (C) 1996 SpellCaster Telecommunications Inc. * * This program is free software; you can redistribute it and/or modify @@ -27,11 +27,6 @@ */ #include -#define NULL 0x0 - -#define REQUEST_IRQ(a,b,c,d,e) request_irq(a,b,c,d,e) -#define FREE_IRQ(a,b) free_irq(a,b) - inline char *strcpy(char *, const char *); int dbg_level = 0; @@ -61,7 +56,7 @@ *i = *j; i++; j++; } - *(++i) = NULL; + *(++i) = 0; return dest; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c --- v2.4.0-test10/linux/drivers/macintosh/via-pmu.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/macintosh/via-pmu.c Sat Nov 11 18:19:56 2000 @@ -1296,6 +1296,33 @@ * Put the powerbook to sleep. */ +static u32 save_via[8]; +static void save_via_state(void) +{ + save_via[0] = in_8(&via[ANH]); + save_via[1] = in_8(&via[DIRA]); + save_via[2] = in_8(&via[B]); + save_via[3] = in_8(&via[DIRB]); + save_via[4] = in_8(&via[PCR]); + save_via[5] = in_8(&via[ACR]); + save_via[6] = in_8(&via[T1CL]); + save_via[7] = in_8(&via[T1CH]); +} +static void restore_via_state(void) +{ + out_8(&via[ANH], save_via[0]); + out_8(&via[DIRA], save_via[1]); + out_8(&via[B], save_via[2]); + out_8(&via[DIRB], save_via[3]); + out_8(&via[PCR], save_via[4]); + out_8(&via[ACR], save_via[5]); + out_8(&via[T1CL], save_via[6]); + out_8(&via[T1CH], save_via[7]); + out_8(&via[IER], IER_CLR | 0x7f); /* disable all intrs */ + out_8(&via[IFR], 0x7f); /* clear IFR */ + out_8(&via[IER], IER_SET | SR_INT | CB1_INT); +} + #define FEATURE_CTRL(base) ((unsigned int *)(base + 0x38)) #define GRACKLE_PM (1<<7) #define GRACKLE_DOZE (1<<5) @@ -1304,11 +1331,11 @@ int __openfirmware powerbook_sleep_G3(void) { - int ret; unsigned long save_l2cr; unsigned long wait; unsigned short pmcr1; struct adb_request req; + int ret, timeout; /* Notify device drivers */ ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT); @@ -1333,24 +1360,54 @@ } /* Give the disks a little time to actually finish writing */ - for (wait = jiffies + (HZ/4); time_before(jiffies, wait); ) + for (wait = jiffies + (HZ/2); time_before(jiffies, wait); ) mb(); + /* Wait for completion of async backlight requests */ + while (!bright_req_1.complete || !bright_req_2.complete || !bright_req_3.complete) + pmu_poll(); + + /* Turn off various things. Darwin does some retry tests here... */ + pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, PMU_POW0_OFF|PMU_POW0_HARD_DRIVE); + while (!req.complete) + pmu_poll(); + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_OFF|PMU_POW_BACKLIGHT|PMU_POW_IRLED|PMU_POW_MEDIABAY); + while (!req.complete) + pmu_poll(); + /* Disable all interrupts except pmu */ sleep_save_intrs(vias->intrs[0].line); + /* Make sure the PMU is idle */ + while (pmu_state != idle) + pmu_poll(); + /* Make sure the decrementer won't interrupt us */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); - - feature_prepare_for_sleep(); + /* Make sure any pending DEC interrupt occuring while we did + * the above didn't re-enable the DEC */ + mb(); + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + + /* Giveup the FPU */ + if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0) + giveup_fpu(current); /* For 750, save backside cache setting and disable it */ save_l2cr = _get_L2CR(); /* (returns 0 if not 750) */ if (save_l2cr) _set_L2CR(0); - if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0) - giveup_fpu(current); + /* Ask the PMU to put us to sleep */ + pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); + while (!req.complete) + pmu_poll(); + + /* The VIA is supposed not to be restored correctly*/ + save_via_state(); + /* We shut down some HW */ + feature_prepare_for_sleep(); grackle_pcibios_read_config_word(0,0,0x70,&pmcr1); /* Apparently, MacOS uses NAP mode for Grackle ??? */ @@ -1358,15 +1415,6 @@ pmcr1 |= GRACKLE_PM|GRACKLE_NAP; grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1); - /* Ask the PMU to put us to sleep */ - pmu_request(&req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T'); - while (!req.complete) - pmu_poll(); - - cli(); - while (pmu_state != idle) - pmu_poll(); - /* Call low-level ASM sleep handler */ low_sleep_handler(); @@ -1374,33 +1422,54 @@ grackle_pcibios_read_config_word(0, 0, 0x70, &pmcr1); pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1); - - /* Make sure the PMU is idle */ - while (pmu_state != idle) - pmu_poll(); - - sti(); - + + /* Restore things */ feature_wake_up(); - - /* The PGD is only a placeholder until Dan finds a way to make - * this work properly on the 8xx processors. It is only used on - * 8xx processors, it is ignored here. - */ - set_context(current->mm->context, current->mm->pgd); - + restore_via_state(); + /* Restore L2 cache */ if (save_l2cr) - _set_L2CR(save_l2cr | 0x200000); /* set invalidate bit */ + _set_L2CR(save_l2cr); + + /* Restore userland MMU context */ + set_context(current->mm->context, current->mm->pgd); - /* reenable interrupts */ - sleep_restore_intrs(); + /* Re-enable DEC interrupts and kick DEC */ + asm volatile("mtdec %0" : : "r" (0x7fffffff)); + sti(); + asm volatile("mtdec %0" : : "r" (0x10000000)); - /* Tell PMU we are ready */ - pmu_request(&req, NULL, 2, PMU_SYSTEM_READY, 2); + /* Power things up */ + pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, 0xfc); + while (!req.complete) + pmu_poll(); + pmu_request(&req, NULL, 2, PMU_POWER_CTRL0, + PMU_POW0_ON|PMU_POW0_HARD_DRIVE); + while (!req.complete) + pmu_poll(); + pmu_request(&req, NULL, 2, PMU_POWER_CTRL, + PMU_POW_ON|PMU_POW_BACKLIGHT|PMU_POW_CHARGER|PMU_POW_IRLED|PMU_POW_MEDIABAY); while (!req.complete) pmu_poll(); - + + /* ack all pending interrupts */ + timeout = 100000; + interrupt_data[0] = 1; + while (interrupt_data[0] || pmu_state != idle) { + if (--timeout < 0) + break; + if (pmu_state == idle) + adb_int_pending = 1; + via_pmu_interrupt(0, 0, 0); + udelay(10); + } + + /* reenable interrupt controller */ + sleep_restore_intrs(); + + /* Leave some time for HW to settle down */ + mdelay(100); + /* Notify drivers */ mdelay(10); broadcast_wake(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/md/lvm.c linux/drivers/md/lvm.c --- v2.4.0-test10/linux/drivers/md/lvm.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/md/lvm.c Wed Nov 8 19:09:49 2000 @@ -1928,7 +1928,7 @@ { int l, le, l_new, p, size; ulong lv_status_save; - char *lv_tmp, *lv_buf; + char *lv_tmp, *lv_buf = NULL; lv_block_exception_t *lvbe = lv->lv_block_exception; vg_t *vg_ptr = vg[VG_CHR(minor)]; lv_t *lv_ptr = NULL; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/md/md.c linux/drivers/md/md.c --- v2.4.0-test10/linux/drivers/md/md.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/md/md.c Tue Nov 14 11:21:12 2000 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -2836,14 +2837,13 @@ mdk_thread_t *thread = arg; md_lock_kernel(); - exit_mm(current); - exit_files(current); - exit_fs(current); /* * Detach thread */ + daemonize(); + sprintf(current->comm, thread->name); md_init_signals(); md_flush_signals(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/md/raid1.c linux/drivers/md/raid1.c --- v2.4.0-test10/linux/drivers/md/raid1.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/md/raid1.c Wed Nov 8 17:03:14 2000 @@ -91,7 +91,8 @@ static inline void raid1_free_bh(raid1_conf_t *conf, struct buffer_head *bh) { - md_spin_lock_irq(&conf->device_lock); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); while (bh) { struct buffer_head *t = bh; bh=bh->b_next; @@ -103,7 +104,7 @@ conf->freebh_cnt++; } } - md_spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); wake_up(&conf->wait_buffer); } @@ -182,10 +183,11 @@ r1_bh->mirror_bh_list = NULL; if (test_bit(R1BH_PreAlloc, &r1_bh->state)) { - md_spin_lock_irq(&conf->device_lock); + unsigned long flags; + spin_lock_irqsave(&conf->device_lock, flags); r1_bh->next_r1 = conf->freer1; conf->freer1 = r1_bh; - md_spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); } else { kfree(r1_bh); } @@ -229,14 +231,15 @@ static inline void raid1_free_buf(struct raid1_bh *r1_bh) { + unsigned long flags; struct buffer_head *bh = r1_bh->mirror_bh_list; raid1_conf_t *conf = mddev_to_conf(r1_bh->mddev); r1_bh->mirror_bh_list = NULL; - md_spin_lock_irq(&conf->device_lock); + spin_lock_irqsave(&conf->device_lock, flags); r1_bh->next_r1 = conf->freebuf; conf->freebuf = r1_bh; - md_spin_unlock_irq(&conf->device_lock); + spin_unlock_irqrestore(&conf->device_lock, flags); raid1_free_bh(conf, bh); } @@ -599,7 +602,7 @@ bh_req = &r1_bh->bh_req; memcpy(bh_req, bh, sizeof(*bh)); - bh_req->b_blocknr = bh->b_rsector * sectors; + bh_req->b_blocknr = bh->b_rsector / sectors; bh_req->b_dev = mirror->dev; bh_req->b_rdev = mirror->dev; /* bh_req->b_rsector = bh->n_rsector; */ @@ -643,7 +646,7 @@ /* * prepare mirrored mbh (fields ordered for max mem throughput): */ - mbh->b_blocknr = bh->b_rsector * sectors; + mbh->b_blocknr = bh->b_rsector / sectors; mbh->b_dev = conf->mirrors[i].dev; mbh->b_rdev = conf->mirrors[i].dev; mbh->b_rsector = bh->b_rsector; @@ -1181,7 +1184,7 @@ struct buffer_head *bh1 = mbh; mbh = mbh->b_next; generic_make_request(WRITE, bh1); - md_sync_acct(bh1->b_rdev, bh1->b_size/512); + md_sync_acct(bh1->b_dev, bh1->b_size/512); } } else { dev = bh->b_dev; @@ -1406,7 +1409,7 @@ init_waitqueue_head(&bh->b_wait); generic_make_request(READ, bh); - md_sync_acct(bh->b_rdev, bh->b_size/512); + md_sync_acct(bh->b_dev, bh->b_size/512); return (bsize >> 10); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/md/raid5.c linux/drivers/md/raid5.c --- v2.4.0-test10/linux/drivers/md/raid5.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/md/raid5.c Fri Nov 17 16:46:55 2000 @@ -858,13 +858,16 @@ PRINTK("compute_parity, stripe %lu, method %d\n", sh->sector, method); for (i = 0; i < disks; i++) { + char *bdata; if (i == pd_idx || !sh->bh_new[i]) continue; if (!sh->bh_copy[i]) sh->bh_copy[i] = raid5_alloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_copy[i], i); atomic_set_buffer_dirty(sh->bh_copy[i]); - memcpy(sh->bh_copy[i]->b_data, sh->bh_new[i]->b_data, sh->size); + bdata = bh_kmap(sh->bh_new[i]); + memcpy(sh->bh_copy[i]->b_data, bdata, sh->size); + bh_kunmap(sh->bh_new[i]); } if (sh->bh_copy[pd_idx] == NULL) { sh->bh_copy[pd_idx] = raid5_alloc_buffer(sh, sh->size); @@ -965,12 +968,14 @@ if (!sh->new[i]) { #if 0 if (sh->cmd == STRIPE_WRITE) { - if (memcmp(sh->bh_new[i]->b_data, sh->bh_copy[i]->b_data, sh->size)) { + char *bdata = bh_kmap(sh->bh_new[i]); + if (memcmp(bdata, sh->bh_copy[i]->b_data, sh->size)) { printk("copy differs, %s, sector %lu ", test_bit(BH_Dirty, &sh->bh_new[i]->b_state) ? "dirty" : "clean", sh->sector); } else if (test_bit(BH_Dirty, &sh->bh_new[i]->b_state)) printk("sector %lu dirty\n", sh->sector); + bh_kunmap(sh->bh_new[i]); } #endif if (sh->cmd == STRIPE_WRITE) @@ -1136,11 +1141,14 @@ if (!method1 || (method1 == 1 && nr_cache == disks - 1)) { PRINTK("read %lu completed from cache\n", sh->sector); for (i = 0; i < disks; i++) { + char *bdata; if (!sh->bh_new[i]) continue; if (!sh->bh_old[i]) compute_block(sh, i); - memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); + bdata = bh_kmap(sh->bh_new[i]); + memcpy(bdata, sh->bh_old[i]->b_data, sh->size); + bh_kunmap(sh->bh_new[i]); } complete_stripe(sh); return; @@ -1168,7 +1176,9 @@ if (!sh->bh_new[i]) continue; if (sh->bh_old[i]) { - memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); + char *bdata = bh_kmap(sh->bh_new[i]); + memcpy(bdata, sh->bh_old[i]->b_data, sh->size); + bh_kunmap(sh->bh_new[i]); continue; } #if RAID5_PARANOIA @@ -2344,18 +2354,7 @@ int raid5_init (void) { - int err; - - err = register_md_personality (RAID5, &raid5_personality); - if (err) - return err; - - /* - * pick a XOR routine, runtime. - */ - calibrate_xor_block(); - - return 0; + return register_md_personality (RAID5, &raid5_personality); } #ifdef MODULE diff -u --recursive --new-file v2.4.0-test10/linux/drivers/md/xor.c linux/drivers/md/xor.c --- v2.4.0-test10/linux/drivers/md/xor.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/md/xor.c Sun Nov 12 19:39:51 2000 @@ -1,10 +1,10 @@ /* * xor.c : Multiple Devices driver for Linux * - * Copyright (C) 1996, 1997, 1998, 1999 Ingo Molnar, Matti Aarnio, Jakub Jelinek + * Copyright (C) 1996, 1997, 1998, 1999, 2000, + * Ingo Molnar, Matti Aarnio, Jakub Jelinek, Richard Henderson. * - * - * optimized RAID-5 checksumming functions. + * Dispatch optimized RAID-5 checksumming functions. * * 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 @@ -15,2584 +15,66 @@ * (for example /usr/src/linux/COPYING); if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include #define BH_TRACE 0 #include #include -#ifdef __sparc_v9__ -#include -#include -#include -#endif - -/* - * we use the 'XOR function template' to register multiple xor - * functions runtime. The kernel measures their speed upon bootup - * and decides which one to use. (compile-time registration is - * not enough as certain CPU features like MMX can only be detected - * runtime) - * - * this architecture makes it pretty easy to add new routines - * that are faster on certain CPUs, without killing other CPU's - * 'native' routine. Although the current routines are belived - * to be the physically fastest ones on all CPUs tested, but - * feel free to prove me wrong and add yet another routine =B-) - * --mingo - */ - -#define MAX_XOR_BLOCKS 5 +#include +#include -#define XOR_ARGS (unsigned int count, struct buffer_head **bh_ptr) +/* The xor routines to use. */ +static struct xor_block_template *active_template; -typedef void (*xor_block_t) XOR_ARGS; -xor_block_t xor_block = NULL; - -#ifndef __sparc_v9__ - -struct xor_block_template; - -struct xor_block_template { - char * name; - xor_block_t xor_block; - int speed; - struct xor_block_template * next; -}; - -struct xor_block_template * xor_functions = NULL; - -#define XORBLOCK_TEMPLATE(x) \ -static void xor_block_##x XOR_ARGS; \ -static struct xor_block_template t_xor_block_##x = \ - { #x, xor_block_##x, 0, NULL }; \ -static void xor_block_##x XOR_ARGS - -#ifdef __i386__ - -#ifdef CONFIG_X86_XMM -/* - * Cache avoiding checksumming functions utilizing KNI instructions - * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) - */ - -XORBLOCK_TEMPLATE(pIII_kni) -{ - char xmm_save[16*4]; - int cr0; - int lines = (bh_ptr[0]->b_size>>8); - - __asm__ __volatile__ ( - "movl %%cr0,%0 ;\n\t" - "clts ;\n\t" - "movups %%xmm0,(%1) ;\n\t" - "movups %%xmm1,0x10(%1) ;\n\t" - "movups %%xmm2,0x20(%1) ;\n\t" - "movups %%xmm3,0x30(%1) ;\n\t" - : "=r" (cr0) - : "r" (xmm_save) - : "memory" ); - -#define OFFS(x) "8*("#x"*2)" -#define PF0(x) \ - " prefetcht0 "OFFS(x)"(%1) ;\n" -#define LD(x,y) \ - " movaps "OFFS(x)"(%1), %%xmm"#y" ;\n" -#define ST(x,y) \ - " movaps %%xmm"#y", "OFFS(x)"(%1) ;\n" -#define PF1(x) \ - " prefetchnta "OFFS(x)"(%2) ;\n" -#define PF2(x) \ - " prefetchnta "OFFS(x)"(%3) ;\n" -#define PF3(x) \ - " prefetchnta "OFFS(x)"(%4) ;\n" -#define PF4(x) \ - " prefetchnta "OFFS(x)"(%5) ;\n" -#define PF5(x) \ - " prefetchnta "OFFS(x)"(%6) ;\n" -#define XO1(x,y) \ - " xorps "OFFS(x)"(%2), %%xmm"#y" ;\n" -#define XO2(x,y) \ - " xorps "OFFS(x)"(%3), %%xmm"#y" ;\n" -#define XO3(x,y) \ - " xorps "OFFS(x)"(%4), %%xmm"#y" ;\n" -#define XO4(x,y) \ - " xorps "OFFS(x)"(%5), %%xmm"#y" ;\n" -#define XO5(x,y) \ - " xorps "OFFS(x)"(%6), %%xmm"#y" ;\n" - - switch(count) { - case 2: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - LD(i,0) \ - LD(i+1,1) \ - PF1(i) \ - PF1(i+2) \ - LD(i+2,2) \ - LD(i+3,3) \ - PF0(i+4) \ - PF0(i+6) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - ST(i,0) \ - ST(i+1,1) \ - ST(i+2,2) \ - ST(i+3,3) \ - - - PF0(0) - PF0(2) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $256, %1 ;\n" - " addl $256, %2 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data) - : "memory" ); - break; - case 3: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - PF1(i) \ - PF1(i+2) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - PF2(i) \ - PF2(i+2) \ - PF0(i+4) \ - PF0(i+6) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - XO2(i,0) \ - XO2(i+1,1) \ - XO2(i+2,2) \ - XO2(i+3,3) \ - ST(i,0) \ - ST(i+1,1) \ - ST(i+2,2) \ - ST(i+3,3) \ - - - PF0(0) - PF0(2) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $256, %1 ;\n" - " addl $256, %2 ;\n" - " addl $256, %3 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data) - : "memory" ); - break; - case 4: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - PF1(i) \ - PF1(i+2) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - PF2(i) \ - PF2(i+2) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - PF3(i) \ - PF3(i+2) \ - PF0(i+4) \ - PF0(i+6) \ - XO2(i,0) \ - XO2(i+1,1) \ - XO2(i+2,2) \ - XO2(i+3,3) \ - XO3(i,0) \ - XO3(i+1,1) \ - XO3(i+2,2) \ - XO3(i+3,3) \ - ST(i,0) \ - ST(i+1,1) \ - ST(i+2,2) \ - ST(i+3,3) \ - - - PF0(0) - PF0(2) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $256, %1 ;\n" - " addl $256, %2 ;\n" - " addl $256, %3 ;\n" - " addl $256, %4 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data), - "r" (bh_ptr[3]->b_data) - : "memory" ); - break; - case 5: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - PF1(i) \ - PF1(i+2) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - PF2(i) \ - PF2(i+2) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - PF3(i) \ - PF3(i+2) \ - XO2(i,0) \ - XO2(i+1,1) \ - XO2(i+2,2) \ - XO2(i+3,3) \ - PF4(i) \ - PF4(i+2) \ - PF0(i+4) \ - PF0(i+6) \ - XO3(i,0) \ - XO3(i+1,1) \ - XO3(i+2,2) \ - XO3(i+3,3) \ - XO4(i,0) \ - XO4(i+1,1) \ - XO4(i+2,2) \ - XO4(i+3,3) \ - ST(i,0) \ - ST(i+1,1) \ - ST(i+2,2) \ - ST(i+3,3) \ - - - PF0(0) - PF0(2) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $256, %1 ;\n" - " addl $256, %2 ;\n" - " addl $256, %3 ;\n" - " addl $256, %4 ;\n" - " addl $256, %5 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data), - "r" (bh_ptr[3]->b_data), - "r" (bh_ptr[4]->b_data) - : "memory"); - break; - } - - __asm__ __volatile__ ( - "sfence ;\n\t" - "movups (%1),%%xmm0 ;\n\t" - "movups 0x10(%1),%%xmm1 ;\n\t" - "movups 0x20(%1),%%xmm2 ;\n\t" - "movups 0x30(%1),%%xmm3 ;\n\t" - "movl %0,%%cr0 ;\n\t" - : - : "r" (cr0), "r" (xmm_save) - : "memory" ); -} - -#undef OFFS -#undef LD -#undef ST -#undef PF0 -#undef PF1 -#undef PF2 -#undef PF3 -#undef PF4 -#undef PF5 -#undef XO1 -#undef XO2 -#undef XO3 -#undef XO4 -#undef XO5 -#undef BLOCK - -#endif /* CONFIG_X86_XMM */ - -/* - * high-speed RAID5 checksumming functions utilizing MMX instructions - * Copyright (C) 1998 Ingo Molnar - */ -XORBLOCK_TEMPLATE(pII_mmx) +void +xor_block(unsigned int count, struct buffer_head **bh_ptr) { - char fpu_save[108]; - int lines = (bh_ptr[0]->b_size>>7); - - if (!(current->flags & PF_USEDFPU)) - __asm__ __volatile__ ( " clts;\n"); - - __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); - -#define LD(x,y) \ - " movq 8*("#x")(%1), %%mm"#y" ;\n" -#define ST(x,y) \ - " movq %%mm"#y", 8*("#x")(%1) ;\n" -#define XO1(x,y) \ - " pxor 8*("#x")(%2), %%mm"#y" ;\n" -#define XO2(x,y) \ - " pxor 8*("#x")(%3), %%mm"#y" ;\n" -#define XO3(x,y) \ - " pxor 8*("#x")(%4), %%mm"#y" ;\n" -#define XO4(x,y) \ - " pxor 8*("#x")(%5), %%mm"#y" ;\n" - - switch(count) { - case 2: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - XO1(i,0) \ - ST(i,0) \ - XO1(i+1,1) \ - ST(i+1,1) \ - XO1(i+2,2) \ - ST(i+2,2) \ - XO1(i+3,3) \ - ST(i+3,3) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $128, %1 ;\n" - " addl $128, %2 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data) - : "memory"); - break; - case 3: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - XO2(i,0) \ - ST(i,0) \ - XO2(i+1,1) \ - ST(i+1,1) \ - XO2(i+2,2) \ - ST(i+2,2) \ - XO2(i+3,3) \ - ST(i+3,3) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $128, %1 ;\n" - " addl $128, %2 ;\n" - " addl $128, %3 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data) - : "memory"); - break; - case 4: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - XO2(i,0) \ - XO2(i+1,1) \ - XO2(i+2,2) \ - XO2(i+3,3) \ - XO3(i,0) \ - ST(i,0) \ - XO3(i+1,1) \ - ST(i+1,1) \ - XO3(i+2,2) \ - ST(i+2,2) \ - XO3(i+3,3) \ - ST(i+3,3) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $128, %1 ;\n" - " addl $128, %2 ;\n" - " addl $128, %3 ;\n" - " addl $128, %4 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data), - "r" (bh_ptr[3]->b_data) - : "memory"); - break; - case 5: - __asm__ __volatile__ ( -#undef BLOCK -#define BLOCK(i) \ - LD(i,0) \ - LD(i+1,1) \ - LD(i+2,2) \ - LD(i+3,3) \ - XO1(i,0) \ - XO1(i+1,1) \ - XO1(i+2,2) \ - XO1(i+3,3) \ - XO2(i,0) \ - XO2(i+1,1) \ - XO2(i+2,2) \ - XO2(i+3,3) \ - XO3(i,0) \ - XO3(i+1,1) \ - XO3(i+2,2) \ - XO3(i+3,3) \ - XO4(i,0) \ - ST(i,0) \ - XO4(i+1,1) \ - ST(i+1,1) \ - XO4(i+2,2) \ - ST(i+2,2) \ - XO4(i+3,3) \ - ST(i+3,3) - - " .align 32,0x90 ;\n" - " 1: ;\n" - - BLOCK(0) - BLOCK(4) - BLOCK(8) - BLOCK(12) - - " addl $128, %1 ;\n" - " addl $128, %2 ;\n" - " addl $128, %3 ;\n" - " addl $128, %4 ;\n" - " addl $128, %5 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - : - : "g" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data), - "r" (bh_ptr[3]->b_data), - "r" (bh_ptr[4]->b_data) - : "memory"); - break; + unsigned long *p0, *p1, *p2, *p3, *p4; + unsigned long bytes = bh_ptr[0]->b_size; + + p0 = (unsigned long *) bh_ptr[0]->b_data; + p1 = (unsigned long *) bh_ptr[1]->b_data; + if (count == 2) { + active_template->do_2(bytes, p0, p1); + return; } - __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); - - if (!(current->flags & PF_USEDFPU)) - stts(); -} - -#undef LD -#undef XO1 -#undef XO2 -#undef XO3 -#undef XO4 -#undef ST -#undef BLOCK - -XORBLOCK_TEMPLATE(p5_mmx) -{ - char fpu_save[108]; - int lines = (bh_ptr[0]->b_size>>6); - - if (!(current->flags & PF_USEDFPU)) - __asm__ __volatile__ ( " clts;\n"); - - __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); - - switch(count) { - case 2: - __asm__ __volatile__ ( - - " .align 32,0x90 ;\n" - " 1: ;\n" - " movq (%1), %%mm0 ;\n" - " movq 8(%1), %%mm1 ;\n" - " pxor (%2), %%mm0 ;\n" - " movq 16(%1), %%mm2 ;\n" - " movq %%mm0, (%1) ;\n" - " pxor 8(%2), %%mm1 ;\n" - " movq 24(%1), %%mm3 ;\n" - " movq %%mm1, 8(%1) ;\n" - " pxor 16(%2), %%mm2 ;\n" - " movq 32(%1), %%mm4 ;\n" - " movq %%mm2, 16(%1) ;\n" - " pxor 24(%2), %%mm3 ;\n" - " movq 40(%1), %%mm5 ;\n" - " movq %%mm3, 24(%1) ;\n" - " pxor 32(%2), %%mm4 ;\n" - " movq 48(%1), %%mm6 ;\n" - " movq %%mm4, 32(%1) ;\n" - " pxor 40(%2), %%mm5 ;\n" - " movq 56(%1), %%mm7 ;\n" - " movq %%mm5, 40(%1) ;\n" - " pxor 48(%2), %%mm6 ;\n" - " pxor 56(%2), %%mm7 ;\n" - " movq %%mm6, 48(%1) ;\n" - " movq %%mm7, 56(%1) ;\n" - - " addl $64, %1 ;\n" - " addl $64, %2 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data) - : "memory" ); - break; - case 3: - __asm__ __volatile__ ( - - " .align 32,0x90 ;\n" - " 1: ;\n" - " movq (%1), %%mm0 ;\n" - " movq 8(%1), %%mm1 ;\n" - " pxor (%2), %%mm0 ;\n" - " movq 16(%1), %%mm2 ;\n" - " pxor 8(%2), %%mm1 ;\n" - " pxor (%3), %%mm0 ;\n" - " pxor 16(%2), %%mm2 ;\n" - " movq %%mm0, (%1) ;\n" - " pxor 8(%3), %%mm1 ;\n" - " pxor 16(%3), %%mm2 ;\n" - " movq 24(%1), %%mm3 ;\n" - " movq %%mm1, 8(%1) ;\n" - " movq 32(%1), %%mm4 ;\n" - " movq 40(%1), %%mm5 ;\n" - " pxor 24(%2), %%mm3 ;\n" - " movq %%mm2, 16(%1) ;\n" - " pxor 32(%2), %%mm4 ;\n" - " pxor 24(%3), %%mm3 ;\n" - " pxor 40(%2), %%mm5 ;\n" - " movq %%mm3, 24(%1) ;\n" - " pxor 32(%3), %%mm4 ;\n" - " pxor 40(%3), %%mm5 ;\n" - " movq 48(%1), %%mm6 ;\n" - " movq %%mm4, 32(%1) ;\n" - " movq 56(%1), %%mm7 ;\n" - " pxor 48(%2), %%mm6 ;\n" - " movq %%mm5, 40(%1) ;\n" - " pxor 56(%2), %%mm7 ;\n" - " pxor 48(%3), %%mm6 ;\n" - " pxor 56(%3), %%mm7 ;\n" - " movq %%mm6, 48(%1) ;\n" - " movq %%mm7, 56(%1) ;\n" - - " addl $64, %1 ;\n" - " addl $64, %2 ;\n" - " addl $64, %3 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data) - : "memory" ); - break; - case 4: - __asm__ __volatile__ ( - - " .align 32,0x90 ;\n" - " 1: ;\n" - " movq (%1), %%mm0 ;\n" - " movq 8(%1), %%mm1 ;\n" - " pxor (%2), %%mm0 ;\n" - " movq 16(%1), %%mm2 ;\n" - " pxor 8(%2), %%mm1 ;\n" - " pxor (%3), %%mm0 ;\n" - " pxor 16(%2), %%mm2 ;\n" - " pxor 8(%3), %%mm1 ;\n" - " pxor (%4), %%mm0 ;\n" - " movq 24(%1), %%mm3 ;\n" - " pxor 16(%3), %%mm2 ;\n" - " pxor 8(%4), %%mm1 ;\n" - " movq %%mm0, (%1) ;\n" - " movq 32(%1), %%mm4 ;\n" - " pxor 24(%2), %%mm3 ;\n" - " pxor 16(%4), %%mm2 ;\n" - " movq %%mm1, 8(%1) ;\n" - " movq 40(%1), %%mm5 ;\n" - " pxor 32(%2), %%mm4 ;\n" - " pxor 24(%3), %%mm3 ;\n" - " movq %%mm2, 16(%1) ;\n" - " pxor 40(%2), %%mm5 ;\n" - " pxor 32(%3), %%mm4 ;\n" - " pxor 24(%4), %%mm3 ;\n" - " movq %%mm3, 24(%1) ;\n" - " movq 56(%1), %%mm7 ;\n" - " movq 48(%1), %%mm6 ;\n" - " pxor 40(%3), %%mm5 ;\n" - " pxor 32(%4), %%mm4 ;\n" - " pxor 48(%2), %%mm6 ;\n" - " movq %%mm4, 32(%1) ;\n" - " pxor 56(%2), %%mm7 ;\n" - " pxor 40(%4), %%mm5 ;\n" - " pxor 48(%3), %%mm6 ;\n" - " pxor 56(%3), %%mm7 ;\n" - " movq %%mm5, 40(%1) ;\n" - " pxor 48(%4), %%mm6 ;\n" - " pxor 56(%4), %%mm7 ;\n" - " movq %%mm6, 48(%1) ;\n" - " movq %%mm7, 56(%1) ;\n" - - " addl $64, %1 ;\n" - " addl $64, %2 ;\n" - " addl $64, %3 ;\n" - " addl $64, %4 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "r" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data), - "r" (bh_ptr[3]->b_data) - : "memory" ); - break; - case 5: - __asm__ __volatile__ ( - - " .align 32,0x90 ;\n" - " 1: ;\n" - " movq (%1), %%mm0 ;\n" - " movq 8(%1), %%mm1 ;\n" - " pxor (%2), %%mm0 ;\n" - " pxor 8(%2), %%mm1 ;\n" - " movq 16(%1), %%mm2 ;\n" - " pxor (%3), %%mm0 ;\n" - " pxor 8(%3), %%mm1 ;\n" - " pxor 16(%2), %%mm2 ;\n" - " pxor (%4), %%mm0 ;\n" - " pxor 8(%4), %%mm1 ;\n" - " pxor 16(%3), %%mm2 ;\n" - " movq 24(%1), %%mm3 ;\n" - " pxor (%5), %%mm0 ;\n" - " pxor 8(%5), %%mm1 ;\n" - " movq %%mm0, (%1) ;\n" - " pxor 16(%4), %%mm2 ;\n" - " pxor 24(%2), %%mm3 ;\n" - " movq %%mm1, 8(%1) ;\n" - " pxor 16(%5), %%mm2 ;\n" - " pxor 24(%3), %%mm3 ;\n" - " movq 32(%1), %%mm4 ;\n" - " movq %%mm2, 16(%1) ;\n" - " pxor 24(%4), %%mm3 ;\n" - " pxor 32(%2), %%mm4 ;\n" - " movq 40(%1), %%mm5 ;\n" - " pxor 24(%5), %%mm3 ;\n" - " pxor 32(%3), %%mm4 ;\n" - " pxor 40(%2), %%mm5 ;\n" - " movq %%mm3, 24(%1) ;\n" - " pxor 32(%4), %%mm4 ;\n" - " pxor 40(%3), %%mm5 ;\n" - " movq 48(%1), %%mm6 ;\n" - " movq 56(%1), %%mm7 ;\n" - " pxor 32(%5), %%mm4 ;\n" - " pxor 40(%4), %%mm5 ;\n" - " pxor 48(%2), %%mm6 ;\n" - " pxor 56(%2), %%mm7 ;\n" - " movq %%mm4, 32(%1) ;\n" - " pxor 48(%3), %%mm6 ;\n" - " pxor 56(%3), %%mm7 ;\n" - " pxor 40(%5), %%mm5 ;\n" - " pxor 48(%4), %%mm6 ;\n" - " pxor 56(%4), %%mm7 ;\n" - " movq %%mm5, 40(%1) ;\n" - " pxor 48(%5), %%mm6 ;\n" - " pxor 56(%5), %%mm7 ;\n" - " movq %%mm6, 48(%1) ;\n" - " movq %%mm7, 56(%1) ;\n" - - " addl $64, %1 ;\n" - " addl $64, %2 ;\n" - " addl $64, %3 ;\n" - " addl $64, %4 ;\n" - " addl $64, %5 ;\n" - " decl %0 ;\n" - " jnz 1b ;\n" - - : - : "g" (lines), - "r" (bh_ptr[0]->b_data), - "r" (bh_ptr[1]->b_data), - "r" (bh_ptr[2]->b_data), - "r" (bh_ptr[3]->b_data), - "r" (bh_ptr[4]->b_data) - : "memory" ); - break; + p2 = (unsigned long *) bh_ptr[2]->b_data; + if (count == 3) { + active_template->do_3(bytes, p0, p1, p2); + return; } - __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); - - if (!(current->flags & PF_USEDFPU)) - stts(); -} -#endif /* __i386__ */ -#endif /* !__sparc_v9__ */ - -#ifdef __sparc_v9__ -/* - * High speed xor_block operation for RAID4/5 utilizing the - * UltraSparc Visual Instruction Set. - * - * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) - * - * Requirements: - * !(((long)dest | (long)sourceN) & (64 - 1)) && - * !(len & 127) && len >= 256 - * - * It is done in pure assembly, as otherwise gcc makes it - * a non-leaf function, which is not what we want. - * Also, we don't measure the speeds as on other architectures, - * as the measuring routine does not take into account cold caches - * and the fact that xor_block_VIS bypasses the caches. - * xor_block_32regs might be 5% faster for count 2 if caches are hot - * and things just right (for count 3 VIS is about as fast as 32regs for - * hot caches and for count 4 and 5 VIS is faster by good margin always), - * but I think it is better not to pollute the caches. - * Actually, if I'd just fight for speed for hot caches, I could - * write a hybrid VIS/integer routine, which would do always two - * 64B blocks in VIS and two in IEUs, but I really care more about - * caches. - */ -extern void *VISenter(void); -extern void xor_block_VIS XOR_ARGS; - -void __xor_block_VIS(void) -{ -__asm__ (" - .globl xor_block_VIS -xor_block_VIS: - ldx [%%o1 + 0], %%o4 - ldx [%%o1 + 8], %%o3 - ldx [%%o4 + %1], %%g5 - ldx [%%o4 + %0], %%o4 - ldx [%%o3 + %0], %%o3 - rd %%fprs, %%o5 - andcc %%o5, %2, %%g0 - be,pt %%icc, 297f - sethi %%hi(%5), %%g1 - jmpl %%g1 + %%lo(%5), %%g7 - add %%g7, 8, %%g7 -297: wr %%g0, %4, %%fprs - membar #LoadStore|#StoreLoad|#StoreStore - sub %%g5, 64, %%g5 - ldda [%%o4] %3, %%f0 - ldda [%%o3] %3, %%f16 - cmp %%o0, 4 - bgeu,pt %%xcc, 10f - cmp %%o0, 3 - be,pn %%xcc, 13f - mov -64, %%g1 - sub %%g5, 64, %%g5 - rd %%asi, %%g1 - wr %%g0, %3, %%asi - -2: ldda [%%o4 + 64] %%asi, %%f32 - fxor %%f0, %%f16, %%f16 - fxor %%f2, %%f18, %%f18 - fxor %%f4, %%f20, %%f20 - fxor %%f6, %%f22, %%f22 - fxor %%f8, %%f24, %%f24 - fxor %%f10, %%f26, %%f26 - fxor %%f12, %%f28, %%f28 - fxor %%f14, %%f30, %%f30 - stda %%f16, [%%o4] %3 - ldda [%%o3 + 64] %%asi, %%f48 - ldda [%%o4 + 128] %%asi, %%f0 - fxor %%f32, %%f48, %%f48 - fxor %%f34, %%f50, %%f50 - add %%o4, 128, %%o4 - fxor %%f36, %%f52, %%f52 - add %%o3, 128, %%o3 - fxor %%f38, %%f54, %%f54 - subcc %%g5, 128, %%g5 - fxor %%f40, %%f56, %%f56 - fxor %%f42, %%f58, %%f58 - fxor %%f44, %%f60, %%f60 - fxor %%f46, %%f62, %%f62 - stda %%f48, [%%o4 - 64] %%asi - bne,pt %%xcc, 2b - ldda [%%o3] %3, %%f16 - - ldda [%%o4 + 64] %%asi, %%f32 - fxor %%f0, %%f16, %%f16 - fxor %%f2, %%f18, %%f18 - fxor %%f4, %%f20, %%f20 - fxor %%f6, %%f22, %%f22 - fxor %%f8, %%f24, %%f24 - fxor %%f10, %%f26, %%f26 - fxor %%f12, %%f28, %%f28 - fxor %%f14, %%f30, %%f30 - stda %%f16, [%%o4] %3 - ldda [%%o3 + 64] %%asi, %%f48 - membar #Sync - fxor %%f32, %%f48, %%f48 - fxor %%f34, %%f50, %%f50 - fxor %%f36, %%f52, %%f52 - fxor %%f38, %%f54, %%f54 - fxor %%f40, %%f56, %%f56 - fxor %%f42, %%f58, %%f58 - fxor %%f44, %%f60, %%f60 - fxor %%f46, %%f62, %%f62 - stda %%f48, [%%o4 + 64] %%asi - membar #Sync|#StoreStore|#StoreLoad - wr %%g0, 0, %%fprs - retl - wr %%g1, %%g0, %%asi - -13: ldx [%%o1 + 16], %%o2 - ldx [%%o2 + %0], %%o2 - -3: ldda [%%o2] %3, %%f32 - fxor %%f0, %%f16, %%f48 - fxor %%f2, %%f18, %%f50 - add %%o4, 64, %%o4 - fxor %%f4, %%f20, %%f52 - fxor %%f6, %%f22, %%f54 - add %%o3, 64, %%o3 - fxor %%f8, %%f24, %%f56 - fxor %%f10, %%f26, %%f58 - fxor %%f12, %%f28, %%f60 - fxor %%f14, %%f30, %%f62 - ldda [%%o4] %3, %%f0 - fxor %%f48, %%f32, %%f48 - fxor %%f50, %%f34, %%f50 - fxor %%f52, %%f36, %%f52 - fxor %%f54, %%f38, %%f54 - add %%o2, 64, %%o2 - fxor %%f56, %%f40, %%f56 - fxor %%f58, %%f42, %%f58 - subcc %%g5, 64, %%g5 - fxor %%f60, %%f44, %%f60 - fxor %%f62, %%f46, %%f62 - stda %%f48, [%%o4 + %%g1] %3 - bne,pt %%xcc, 3b - ldda [%%o3] %3, %%f16 - - ldda [%%o2] %3, %%f32 - fxor %%f0, %%f16, %%f48 - fxor %%f2, %%f18, %%f50 - fxor %%f4, %%f20, %%f52 - fxor %%f6, %%f22, %%f54 - fxor %%f8, %%f24, %%f56 - fxor %%f10, %%f26, %%f58 - fxor %%f12, %%f28, %%f60 - fxor %%f14, %%f30, %%f62 - membar #Sync - fxor %%f48, %%f32, %%f48 - fxor %%f50, %%f34, %%f50 - fxor %%f52, %%f36, %%f52 - fxor %%f54, %%f38, %%f54 - fxor %%f56, %%f40, %%f56 - fxor %%f58, %%f42, %%f58 - fxor %%f60, %%f44, %%f60 - fxor %%f62, %%f46, %%f62 - stda %%f48, [%%o4] %3 - membar #Sync|#StoreStore|#StoreLoad - retl - wr %%g0, 0, %%fprs - -10: cmp %%o0, 5 - be,pt %%xcc, 15f - mov -64, %%g1 - -14: ldx [%%o1 + 16], %%o2 - ldx [%%o1 + 24], %%o0 - ldx [%%o2 + %0], %%o2 - ldx [%%o0 + %0], %%o0 - -4: ldda [%%o2] %3, %%f32 - fxor %%f0, %%f16, %%f16 - fxor %%f2, %%f18, %%f18 - add %%o4, 64, %%o4 - fxor %%f4, %%f20, %%f20 - fxor %%f6, %%f22, %%f22 - add %%o3, 64, %%o3 - fxor %%f8, %%f24, %%f24 - fxor %%f10, %%f26, %%f26 - fxor %%f12, %%f28, %%f28 - fxor %%f14, %%f30, %%f30 - ldda [%%o0] %3, %%f48 - fxor %%f16, %%f32, %%f32 - fxor %%f18, %%f34, %%f34 - fxor %%f20, %%f36, %%f36 - fxor %%f22, %%f38, %%f38 - add %%o2, 64, %%o2 - fxor %%f24, %%f40, %%f40 - fxor %%f26, %%f42, %%f42 - fxor %%f28, %%f44, %%f44 - fxor %%f30, %%f46, %%f46 - ldda [%%o4] %3, %%f0 - fxor %%f32, %%f48, %%f48 - fxor %%f34, %%f50, %%f50 - fxor %%f36, %%f52, %%f52 - add %%o0, 64, %%o0 - fxor %%f38, %%f54, %%f54 - fxor %%f40, %%f56, %%f56 - fxor %%f42, %%f58, %%f58 - subcc %%g5, 64, %%g5 - fxor %%f44, %%f60, %%f60 - fxor %%f46, %%f62, %%f62 - stda %%f48, [%%o4 + %%g1] %3 - bne,pt %%xcc, 4b - ldda [%%o3] %3, %%f16 - - ldda [%%o2] %3, %%f32 - fxor %%f0, %%f16, %%f16 - fxor %%f2, %%f18, %%f18 - fxor %%f4, %%f20, %%f20 - fxor %%f6, %%f22, %%f22 - fxor %%f8, %%f24, %%f24 - fxor %%f10, %%f26, %%f26 - fxor %%f12, %%f28, %%f28 - fxor %%f14, %%f30, %%f30 - ldda [%%o0] %3, %%f48 - fxor %%f16, %%f32, %%f32 - fxor %%f18, %%f34, %%f34 - fxor %%f20, %%f36, %%f36 - fxor %%f22, %%f38, %%f38 - fxor %%f24, %%f40, %%f40 - fxor %%f26, %%f42, %%f42 - fxor %%f28, %%f44, %%f44 - fxor %%f30, %%f46, %%f46 - membar #Sync - fxor %%f32, %%f48, %%f48 - fxor %%f34, %%f50, %%f50 - fxor %%f36, %%f52, %%f52 - fxor %%f38, %%f54, %%f54 - fxor %%f40, %%f56, %%f56 - fxor %%f42, %%f58, %%f58 - fxor %%f44, %%f60, %%f60 - fxor %%f46, %%f62, %%f62 - stda %%f48, [%%o4] %3 - membar #Sync|#StoreStore|#StoreLoad - retl - wr %%g0, 0, %%fprs - -15: ldx [%%o1 + 16], %%o2 - ldx [%%o1 + 24], %%o0 - ldx [%%o1 + 32], %%o1 - ldx [%%o2 + %0], %%o2 - ldx [%%o0 + %0], %%o0 - ldx [%%o1 + %0], %%o1 - -5: ldda [%%o2] %3, %%f32 - fxor %%f0, %%f16, %%f48 - fxor %%f2, %%f18, %%f50 - add %%o4, 64, %%o4 - fxor %%f4, %%f20, %%f52 - fxor %%f6, %%f22, %%f54 - add %%o3, 64, %%o3 - fxor %%f8, %%f24, %%f56 - fxor %%f10, %%f26, %%f58 - fxor %%f12, %%f28, %%f60 - fxor %%f14, %%f30, %%f62 - ldda [%%o0] %3, %%f16 - fxor %%f48, %%f32, %%f48 - fxor %%f50, %%f34, %%f50 - fxor %%f52, %%f36, %%f52 - fxor %%f54, %%f38, %%f54 - add %%o2, 64, %%o2 - fxor %%f56, %%f40, %%f56 - fxor %%f58, %%f42, %%f58 - fxor %%f60, %%f44, %%f60 - fxor %%f62, %%f46, %%f62 - ldda [%%o1] %3, %%f32 - fxor %%f48, %%f16, %%f48 - fxor %%f50, %%f18, %%f50 - add %%o0, 64, %%o0 - fxor %%f52, %%f20, %%f52 - fxor %%f54, %%f22, %%f54 - add %%o1, 64, %%o1 - fxor %%f56, %%f24, %%f56 - fxor %%f58, %%f26, %%f58 - fxor %%f60, %%f28, %%f60 - fxor %%f62, %%f30, %%f62 - ldda [%%o4] %3, %%f0 - fxor %%f48, %%f32, %%f48 - fxor %%f50, %%f34, %%f50 - fxor %%f52, %%f36, %%f52 - fxor %%f54, %%f38, %%f54 - fxor %%f56, %%f40, %%f56 - fxor %%f58, %%f42, %%f58 - subcc %%g5, 64, %%g5 - fxor %%f60, %%f44, %%f60 - fxor %%f62, %%f46, %%f62 - stda %%f48, [%%o4 + %%g1] %3 - bne,pt %%xcc, 5b - ldda [%%o3] %3, %%f16 - - ldda [%%o2] %3, %%f32 - fxor %%f0, %%f16, %%f48 - fxor %%f2, %%f18, %%f50 - fxor %%f4, %%f20, %%f52 - fxor %%f6, %%f22, %%f54 - fxor %%f8, %%f24, %%f56 - fxor %%f10, %%f26, %%f58 - fxor %%f12, %%f28, %%f60 - fxor %%f14, %%f30, %%f62 - ldda [%%o0] %3, %%f16 - fxor %%f48, %%f32, %%f48 - fxor %%f50, %%f34, %%f50 - fxor %%f52, %%f36, %%f52 - fxor %%f54, %%f38, %%f54 - fxor %%f56, %%f40, %%f56 - fxor %%f58, %%f42, %%f58 - fxor %%f60, %%f44, %%f60 - fxor %%f62, %%f46, %%f62 - ldda [%%o1] %3, %%f32 - fxor %%f48, %%f16, %%f48 - fxor %%f50, %%f18, %%f50 - fxor %%f52, %%f20, %%f52 - fxor %%f54, %%f22, %%f54 - fxor %%f56, %%f24, %%f56 - fxor %%f58, %%f26, %%f58 - fxor %%f60, %%f28, %%f60 - fxor %%f62, %%f30, %%f62 - membar #Sync - fxor %%f48, %%f32, %%f48 - fxor %%f50, %%f34, %%f50 - fxor %%f52, %%f36, %%f52 - fxor %%f54, %%f38, %%f54 - fxor %%f56, %%f40, %%f56 - fxor %%f58, %%f42, %%f58 - fxor %%f60, %%f44, %%f60 - fxor %%f62, %%f46, %%f62 - stda %%f48, [%%o4] %3 - membar #Sync|#StoreStore|#StoreLoad - retl - wr %%g0, 0, %%fprs - " : : - "i" (&((struct buffer_head *)0)->b_data), - "i" (&((struct buffer_head *)0)->b_size), - "i" (FPRS_FEF|FPRS_DU), "i" (ASI_BLK_P), - "i" (FPRS_FEF), "i" (VISenter)); -} -#endif /* __sparc_v9__ */ - -#if defined(__sparc__) && !defined(__sparc_v9__) -/* - * High speed xor_block operation for RAID4/5 utilizing the - * ldd/std SPARC instructions. - * - * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) - * - */ - -XORBLOCK_TEMPLATE(SPARC) -{ - int size = bh_ptr[0]->b_size; - int lines = size / (sizeof (long)) / 8, i; - long *destp = (long *) bh_ptr[0]->b_data; - long *source1 = (long *) bh_ptr[1]->b_data; - long *source2, *source3, *source4; - - switch (count) { - case 2: - for (i = lines; i > 0; i--) { - __asm__ __volatile__(" - ldd [%0 + 0x00], %%g2 - ldd [%0 + 0x08], %%g4 - ldd [%0 + 0x10], %%o0 - ldd [%0 + 0x18], %%o2 - ldd [%1 + 0x00], %%o4 - ldd [%1 + 0x08], %%l0 - ldd [%1 + 0x10], %%l2 - ldd [%1 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - std %%g2, [%0 + 0x00] - std %%g4, [%0 + 0x08] - std %%o0, [%0 + 0x10] - std %%o2, [%0 + 0x18] - " : : "r" (destp), "r" (source1) : "g2", "g3", "g4", "g5", "o0", - "o1", "o2", "o3", "o4", "o5", "l0", "l1", "l2", "l3", "l4", "l5"); - destp += 8; - source1 += 8; - } - break; - case 3: - source2 = (long *) bh_ptr[2]->b_data; - for (i = lines; i > 0; i--) { - __asm__ __volatile__(" - ldd [%0 + 0x00], %%g2 - ldd [%0 + 0x08], %%g4 - ldd [%0 + 0x10], %%o0 - ldd [%0 + 0x18], %%o2 - ldd [%1 + 0x00], %%o4 - ldd [%1 + 0x08], %%l0 - ldd [%1 + 0x10], %%l2 - ldd [%1 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - ldd [%2 + 0x00], %%o4 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - ldd [%2 + 0x08], %%l0 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - ldd [%2 + 0x10], %%l2 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - ldd [%2 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - std %%g2, [%0 + 0x00] - std %%g4, [%0 + 0x08] - std %%o0, [%0 + 0x10] - std %%o2, [%0 + 0x18] - " : : "r" (destp), "r" (source1), "r" (source2) - : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", - "l0", "l1", "l2", "l3", "l4", "l5"); - destp += 8; - source1 += 8; - source2 += 8; - } - break; - case 4: - source2 = (long *) bh_ptr[2]->b_data; - source3 = (long *) bh_ptr[3]->b_data; - for (i = lines; i > 0; i--) { - __asm__ __volatile__(" - ldd [%0 + 0x00], %%g2 - ldd [%0 + 0x08], %%g4 - ldd [%0 + 0x10], %%o0 - ldd [%0 + 0x18], %%o2 - ldd [%1 + 0x00], %%o4 - ldd [%1 + 0x08], %%l0 - ldd [%1 + 0x10], %%l2 - ldd [%1 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - ldd [%2 + 0x00], %%o4 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - ldd [%2 + 0x08], %%l0 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - ldd [%2 + 0x10], %%l2 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - ldd [%2 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - ldd [%3 + 0x00], %%o4 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - ldd [%3 + 0x08], %%l0 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - ldd [%3 + 0x10], %%l2 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - ldd [%3 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - std %%g2, [%0 + 0x00] - std %%g4, [%0 + 0x08] - std %%o0, [%0 + 0x10] - std %%o2, [%0 + 0x18] - " : : "r" (destp), "r" (source1), "r" (source2), "r" (source3) - : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", - "l0", "l1", "l2", "l3", "l4", "l5"); - destp += 8; - source1 += 8; - source2 += 8; - source3 += 8; - } - break; - case 5: - source2 = (long *) bh_ptr[2]->b_data; - source3 = (long *) bh_ptr[3]->b_data; - source4 = (long *) bh_ptr[4]->b_data; - for (i = lines; i > 0; i--) { - __asm__ __volatile__(" - ldd [%0 + 0x00], %%g2 - ldd [%0 + 0x08], %%g4 - ldd [%0 + 0x10], %%o0 - ldd [%0 + 0x18], %%o2 - ldd [%1 + 0x00], %%o4 - ldd [%1 + 0x08], %%l0 - ldd [%1 + 0x10], %%l2 - ldd [%1 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - ldd [%2 + 0x00], %%o4 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - ldd [%2 + 0x08], %%l0 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - ldd [%2 + 0x10], %%l2 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - ldd [%2 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - ldd [%3 + 0x00], %%o4 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - ldd [%3 + 0x08], %%l0 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - ldd [%3 + 0x10], %%l2 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - ldd [%3 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - ldd [%4 + 0x00], %%o4 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - ldd [%4 + 0x08], %%l0 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - ldd [%4 + 0x10], %%l2 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - ldd [%4 + 0x18], %%l4 - xor %%g2, %%o4, %%g2 - xor %%g3, %%o5, %%g3 - xor %%g4, %%l0, %%g4 - xor %%g5, %%l1, %%g5 - xor %%o0, %%l2, %%o0 - xor %%o1, %%l3, %%o1 - xor %%o2, %%l4, %%o2 - xor %%o3, %%l5, %%o3 - std %%g2, [%0 + 0x00] - std %%g4, [%0 + 0x08] - std %%o0, [%0 + 0x10] - std %%o2, [%0 + 0x18] - " : : "r" (destp), "r" (source1), "r" (source2), "r" (source3), "r" (source4) - : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", - "l0", "l1", "l2", "l3", "l4", "l5"); - destp += 8; - source1 += 8; - source2 += 8; - source3 += 8; - source4 += 8; - } - break; + p3 = (unsigned long *) bh_ptr[3]->b_data; + if (count == 4) { + active_template->do_4(bytes, p0, p1, p2, p3); + return; } -} -#endif /* __sparc_v[78]__ */ - -#ifdef __alpha__ -/* - * High speed xor_block operation for RAID4/5 pipelined for Alpha EV5. - * There is a second version using EV6 prefetch instructions. - * - * Copyright (C) 2000 Richard Henderson (rth@redhat.com) - */ - -XORBLOCK_TEMPLATE(alpha) -{ - long lines = bh_ptr[0]->b_size / sizeof (long) / 8; - long *d = (long *) bh_ptr[0]->b_data; - long *s1 = (long *) bh_ptr[1]->b_data; - long *s2, *s3, *s4; - - if (count == 2) goto two_blocks; - - s2 = (long *) bh_ptr[2]->b_data; - if (count == 3) goto three_blocks; - - s3 = (long *) bh_ptr[3]->b_data; - if (count == 4) goto four_blocks; - - s4 = (long *) bh_ptr[4]->b_data; - goto five_blocks; - -two_blocks: -asm volatile (" - .align 4 -2: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,8(%0) - ldq $3,8(%1) - - ldq $4,16(%0) - ldq $5,16(%1) - ldq $6,24(%0) - ldq $7,24(%1) - - ldq $16,32(%0) - ldq $17,32(%1) - ldq $18,40(%0) - ldq $19,40(%1) - - ldq $20,48(%0) - ldq $21,48(%1) - ldq $22,56(%0) - xor $0,$1,$0 # 7 cycles from $1 load - - ldq $23,56(%1) - xor $2,$3,$2 - stq $0,0(%0) - xor $4,$5,$4 - - stq $2,8(%0) - xor $6,$7,$6 - stq $4,16(%0) - xor $16,$17,$16 - - stq $6,24(%0) - xor $18,$19,$18 - stq $16,32(%0) - xor $20,$21,$20 - - stq $18,40(%0) - xor $22,$23,$22 - stq $20,48(%0) - subq %2,1,%2 - - stq $22,56(%0) - addq %0,64,%0 - addq %1,64,%1 - bgt %2,2b" - : "=r"(d), "=r"(s1), "=r"(lines) - : "0"(d), "1"(s1), "2"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23"); - return; - -three_blocks: -asm volatile (" - .align 4 -3: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,0(%2) - ldq $3,8(%0) - - ldq $4,8(%1) - ldq $6,16(%0) - ldq $7,16(%1) - ldq $17,24(%0) - - ldq $18,24(%1) - ldq $20,32(%0) - ldq $21,32(%1) - ldq $5,8(%2) - - ldq $16,16(%2) - ldq $19,24(%2) - ldq $22,32(%2) - nop - - xor $0,$1,$1 # 8 cycles from $0 load - xor $3,$4,$4 # 6 cycles from $4 load - xor $6,$7,$7 # 6 cycles from $7 load - xor $17,$18,$18 # 5 cycles from $18 load - - xor $1,$2,$2 # 9 cycles from $2 load - xor $20,$21,$21 # 5 cycles from $21 load - stq $2,0(%0) - xor $4,$5,$5 # 6 cycles from $5 load - - stq $5,8(%0) - xor $7,$16,$16 # 7 cycles from $16 load - stq $16,16(%0) - xor $18,$19,$19 # 7 cycles from $19 load - - stq $19,24(%0) - xor $21,$22,$22 # 7 cycles from $22 load - stq $22,32(%0) - nop - - ldq $0,40(%0) - ldq $1,40(%1) - ldq $3,48(%0) - ldq $4,48(%1) - - ldq $6,56(%0) - ldq $7,56(%1) - ldq $2,40(%2) - ldq $5,48(%2) - - ldq $16,56(%2) - xor $0,$1,$1 # 4 cycles from $1 load - xor $3,$4,$4 # 5 cycles from $4 load - xor $6,$7,$7 # 5 cycles from $7 load - - xor $1,$2,$2 # 4 cycles from $2 load - xor $4,$5,$5 # 5 cycles from $5 load - stq $2,40(%0) - xor $7,$16,$16 # 4 cycles from $16 load - - stq $5,48(%0) - subq %3,1,%3 - stq $16,56(%0) - addq %2,64,%2 - - addq %1,64,%1 - addq %0,64,%0 - bgt %3,3b" - : "=r"(d), "=r"(s1), "=r"(s2), "=r"(lines) - : "0"(d), "1"(s1), "2"(s2), "3"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21", "$22"); - return; - -four_blocks: -asm volatile (" - .align 4 -4: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,0(%2) - ldq $3,0(%3) - - ldq $4,8(%0) - ldq $5,8(%1) - ldq $6,8(%2) - ldq $7,8(%3) - - ldq $16,16(%0) - ldq $17,16(%1) - ldq $18,16(%2) - ldq $19,16(%3) - - ldq $20,24(%0) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $21,24(%1) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,24(%2) - xor $1,$3,$3 - ldq $1,24(%3) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $3,0(%0) - xor $6,$7,$7 - xor $16,$17,$17 # 7 cycles from $17 load - xor $5,$7,$7 - - stq $7,8(%0) - xor $18,$19,$19 # 7 cycles from $19 load - ldq $2,32(%0) - xor $17,$19,$19 - - ldq $3,32(%1) - ldq $4,32(%2) - ldq $5,32(%3) - xor $20,$21,$21 # 8 cycles from $21 load - - ldq $6,40(%0) - ldq $7,40(%1) - ldq $16,40(%2) - ldq $17,40(%3) - - stq $19,16(%0) - xor $0,$1,$1 # 9 cycles from $1 load - xor $2,$3,$3 # 5 cycles from $3 load - xor $21,$1,$1 - - ldq $18,48(%0) - xor $4,$5,$5 # 5 cycles from $5 load - ldq $19,48(%1) - xor $3,$5,$5 - - ldq $20,48(%2) - ldq $21,48(%3) - ldq $0,56(%0) - ldq $1,56(%1) - - ldq $2,56(%2) - xor $6,$7,$7 # 8 cycles from $6 load - ldq $3,56(%3) - xor $16,$17,$17 # 8 cycles from $17 load - - xor $7,$17,$17 - xor $18,$19,$19 # 5 cycles from $19 load - xor $20,$21,$21 # 5 cycles from $21 load - xor $19,$21,$21 - - stq $1,24(%0) - xor $0,$1,$1 # 5 cycles from $1 load - stq $5,32(%0) - xor $2,$3,$3 # 4 cycles from $3 load - - stq $17,40(%0) - xor $1,$3,$3 - stq $21,48(%0) - subq %4,1,%4 - - stq $3,56(%0) - addq %3,64,%3 - addq %2,64,%2 - addq %1,64,%1 - - addq %0,64,%0 - bgt %4,4b" - : "=r"(d), "=r"(s1), "=r"(s2), "=r"(s3), "=r"(lines) - : "0"(d), "1"(s1), "2"(s2), "3"(s3), "4"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21"); - return; - -five_blocks: -asm volatile (" - ldq %0,0(%6) - ldq %1,8(%6) - ldq %2,16(%6) - ldq %3,24(%6) - ldq %4,32(%6) - ldq %0,%7(%0) - ldq %1,%7(%1) - ldq %2,%7(%2) - ldq %3,%7(%3) - ldq %4,%7(%4) - .align 4 -5: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,0(%2) - ldq $3,0(%3) - - ldq $4,0(%4) - ldq $5,8(%0) - ldq $6,8(%1) - ldq $7,8(%2) - - ldq $16,8(%3) - ldq $17,8(%4) - ldq $18,16(%0) - ldq $19,16(%1) - - ldq $20,16(%2) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $21,16(%3) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,16(%4) - xor $1,$3,$3 - ldq $1,24(%0) - xor $3,$4,$4 # 7 cycles from $4 load - - stq $4,0(%0) - xor $5,$6,$6 # 7 cycles from $6 load - xor $7,$16,$16 # 7 cycles from $16 load - xor $6,$17,$17 # 7 cycles from $17 load - - ldq $2,24(%1) - xor $16,$17,$17 - ldq $3,24(%2) - xor $18,$19,$19 # 8 cycles from $19 load - - stq $17,8(%0) - xor $19,$20,$20 # 8 cycles from $20 load - ldq $4,24(%3) - xor $21,$0,$0 # 7 cycles from $0 load - - ldq $5,24(%4) - xor $20,$0,$0 - ldq $6,32(%0) - ldq $7,32(%1) - - stq $0,16(%0) - xor $1,$2,$2 # 6 cycles from $2 load - ldq $16,32(%2) - xor $3,$4,$4 # 4 cycles from $4 load - - ldq $17,32(%3) - xor $2,$4,$4 - ldq $18,32(%4) - ldq $19,40(%0) - - ldq $20,40(%1) - ldq $21,40(%2) - ldq $0,40(%3) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $5,24(%0) - xor $6,$7,$7 # 7 cycles from $7 load - ldq $1,40(%4) - ldq $2,48(%0) - - ldq $3,48(%1) - xor $7,$16,$16 # 7 cycles from $16 load - ldq $4,48(%2) - xor $17,$18,$18 # 6 cycles from $18 load - - ldq $5,48(%3) - xor $16,$18,$18 - ldq $6,48(%4) - xor $19,$20,$20 # 7 cycles from $20 load - - stq $18,32(%0) - xor $20,$21,$21 # 8 cycles from $21 load - ldq $7,56(%0) - xor $0,$1,$1 # 6 cycles from $1 load - - ldq $16,56(%1) - ldq $17,56(%2) - ldq $18,56(%3) - ldq $19,56(%4) - - xor $21,$1,$1 - xor $2,$3,$3 # 9 cycles from $3 load - xor $3,$4,$4 # 9 cycles from $4 load - xor $5,$6,$6 # 8 cycles from $6 load - - unop - xor $4,$6,$6 - xor $7,$16,$16 # 7 cycles from $16 load - xor $17,$18,$18 # 6 cycles from $18 load - - stq $6,48(%0) - xor $16,$18,$18 - subq %5,1,%5 - xor $18,$19,$19 # 8 cycles from $19 load - - stq $19,56(%0) - addq %4,64,%4 - addq %3,64,%3 - addq %2,64,%2 - - addq %1,64,%1 - addq %0,64,%0 - bgt %5,5b" - : "=&r"(d), "=&r"(s1), "=&r"(s2), "=&r"(s3), "=r"(s4), "=r"(lines) - /* ARG! We've run out of asm arguments! We've got to reload - all those pointers we just loaded. */ - : "r"(bh_ptr), "i" (&((struct buffer_head *)0)->b_data), "5"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21"); - return; -} - -#define prefetch(base, ofs) \ - asm("ldq $31,%2(%0)" : "=r"(base) : "0"(base), "i"(ofs)) -XORBLOCK_TEMPLATE(alpha_prefetch) -{ - long lines = bh_ptr[0]->b_size / sizeof (long) / 8; - long *d = (long *) bh_ptr[0]->b_data; - long *s1 = (long *) bh_ptr[1]->b_data; - long *s2, *s3, *s4; - long p; - - p = count == 2; - prefetch(d, 0); - prefetch(s1, 0); - prefetch(d, 64); - prefetch(s1, 64); - prefetch(d, 128); - prefetch(s1, 128); - prefetch(d, 192); - prefetch(s1, 192); - if (p) goto two_blocks; - - s2 = (long *) bh_ptr[2]->b_data; - p = count == 3; - prefetch(s2, 0); - prefetch(s2, 64); - prefetch(s2, 128); - prefetch(s2, 192); - if (p) goto three_blocks; - - s3 = (long *) bh_ptr[3]->b_data; - p = count == 4; - prefetch(s3, 0); - prefetch(s3, 64); - prefetch(s3, 128); - prefetch(s3, 192); - if (p) goto four_blocks; - - s4 = (long *) bh_ptr[4]->b_data; - prefetch(s4, 0); - prefetch(s4, 64); - prefetch(s4, 128); - prefetch(s4, 192); - goto five_blocks; - -two_blocks: -asm volatile (" - .align 4 -2: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,8(%0) - ldq $3,8(%1) - - ldq $4,16(%0) - ldq $5,16(%1) - ldq $6,24(%0) - ldq $7,24(%1) - - ldq $16,32(%0) - ldq $17,32(%1) - ldq $18,40(%0) - ldq $19,40(%1) - - ldq $20,48(%0) - ldq $21,48(%1) - ldq $22,56(%0) - ldq $23,56(%1) - - ldq $31,256(%0) - xor $0,$1,$0 # 8 cycles from $1 load - ldq $31,256(%1) - xor $2,$3,$2 - - stq $0,0(%0) - xor $4,$5,$4 - stq $2,8(%0) - xor $6,$7,$6 - - stq $4,16(%0) - xor $16,$17,$16 - stq $6,24(%0) - xor $18,$19,$18 - - stq $16,32(%0) - xor $20,$21,$20 - stq $18,40(%0) - xor $22,$23,$22 - - stq $20,48(%0) - subq %2,1,%2 - stq $22,56(%0) - addq %0,64,%0 - - addq %1,64,%1 - bgt %2,2b" - : "=r"(d), "=r"(s1), "=r"(lines) - : "0"(d), "1"(s1), "2"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23"); - return; - -three_blocks: -asm volatile (" - .align 4 -3: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,0(%2) - ldq $3,8(%0) - - ldq $4,8(%1) - ldq $6,16(%0) - ldq $7,16(%1) - ldq $17,24(%0) - - ldq $18,24(%1) - ldq $20,32(%0) - ldq $21,32(%1) - ldq $5,8(%2) - - ldq $16,16(%2) - ldq $19,24(%2) - ldq $22,32(%2) - nop - - xor $0,$1,$1 # 8 cycles from $0 load - xor $3,$4,$4 # 7 cycles from $4 load - xor $6,$7,$7 # 6 cycles from $7 load - xor $17,$18,$18 # 5 cycles from $18 load - - xor $1,$2,$2 # 9 cycles from $2 load - xor $20,$21,$21 # 5 cycles from $21 load - stq $2,0(%0) - xor $4,$5,$5 # 6 cycles from $5 load - - stq $5,8(%0) - xor $7,$16,$16 # 7 cycles from $16 load - stq $16,16(%0) - xor $18,$19,$19 # 7 cycles from $19 load - - stq $19,24(%0) - xor $21,$22,$22 # 7 cycles from $22 load - stq $22,32(%0) - nop - - ldq $0,40(%0) - ldq $1,40(%1) - ldq $3,48(%0) - ldq $4,48(%1) - - ldq $6,56(%0) - ldq $7,56(%1) - ldq $2,40(%2) - ldq $5,48(%2) - - ldq $16,56(%2) - ldq $31,256(%0) - ldq $31,256(%1) - ldq $31,256(%2) - - xor $0,$1,$1 # 6 cycles from $1 load - xor $3,$4,$4 # 5 cycles from $4 load - xor $6,$7,$7 # 5 cycles from $7 load - xor $1,$2,$2 # 4 cycles from $2 load - - xor $4,$5,$5 # 5 cycles from $5 load - xor $7,$16,$16 # 4 cycles from $16 load - stq $2,40(%0) - subq %3,1,%3 - - stq $5,48(%0) - addq %2,64,%2 - stq $16,56(%0) - addq %1,64,%1 - - addq %0,64,%0 - bgt %3,3b" - : "=r"(d), "=r"(s1), "=r"(s2), "=r"(lines) - : "0"(d), "1"(s1), "2"(s2), "3"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21", "$22"); - return; - -four_blocks: -asm volatile (" - .align 4 -4: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,0(%2) - ldq $3,0(%3) - - ldq $4,8(%0) - ldq $5,8(%1) - ldq $6,8(%2) - ldq $7,8(%3) - - ldq $16,16(%0) - ldq $17,16(%1) - ldq $18,16(%2) - ldq $19,16(%3) - - ldq $20,24(%0) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $21,24(%1) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,24(%2) - xor $1,$3,$3 - ldq $1,24(%3) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $3,0(%0) - xor $6,$7,$7 - xor $16,$17,$17 # 7 cycles from $17 load - xor $5,$7,$7 - - stq $7,8(%0) - xor $18,$19,$19 # 7 cycles from $19 load - ldq $2,32(%0) - xor $17,$19,$19 - - ldq $3,32(%1) - ldq $4,32(%2) - ldq $5,32(%3) - xor $20,$21,$21 # 8 cycles from $21 load - - ldq $6,40(%0) - ldq $7,40(%1) - ldq $16,40(%2) - ldq $17,40(%3) - - stq $19,16(%0) - xor $0,$1,$1 # 9 cycles from $1 load - xor $2,$3,$3 # 5 cycles from $3 load - xor $21,$1,$1 - - ldq $18,48(%0) - xor $4,$5,$5 # 5 cycles from $5 load - ldq $19,48(%1) - xor $3,$5,$5 - - ldq $20,48(%2) - ldq $21,48(%3) - ldq $0,56(%0) - ldq $1,56(%1) - - ldq $2,56(%2) - xor $6,$7,$7 # 8 cycles from $6 load - ldq $3,56(%3) - xor $16,$17,$17 # 8 cycles from $17 load - - ldq $31,256(%0) - xor $7,$17,$17 - ldq $31,256(%1) - xor $18,$19,$19 # 6 cycles from $19 load - - ldq $31,256(%2) - xor $20,$21,$21 # 6 cycles from $21 load - ldq $31,256(%3) - xor $19,$21,$21 - - stq $1,24(%0) - xor $0,$1,$1 # 7 cycles from $1 load - stq $5,32(%0) - xor $2,$3,$3 # 6 cycles from $3 load - - stq $17,40(%0) - xor $1,$3,$3 - stq $21,48(%0) - subq %4,1,%4 - - stq $3,56(%0) - addq %3,64,%3 - addq %2,64,%2 - addq %1,64,%1 - - addq %0,64,%0 - bgt %4,4b" - : "=r"(d), "=r"(s1), "=r"(s2), "=r"(s3), "=r"(lines) - : "0"(d), "1"(s1), "2"(s2), "3"(s3), "4"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21"); - return; - -five_blocks: -asm volatile (" - ldq %0,0(%6) - ldq %1,8(%6) - ldq %2,16(%6) - ldq %3,24(%6) - ldq %4,32(%6) - ldq %0,%7(%0) - ldq %1,%7(%1) - ldq %2,%7(%2) - ldq %3,%7(%3) - ldq %4,%7(%4) - .align 4 -5: - ldq $0,0(%0) - ldq $1,0(%1) - ldq $2,0(%2) - ldq $3,0(%3) - - ldq $4,0(%4) - ldq $5,8(%0) - ldq $6,8(%1) - ldq $7,8(%2) - - ldq $16,8(%3) - ldq $17,8(%4) - ldq $18,16(%0) - ldq $19,16(%1) - - ldq $20,16(%2) - xor $0,$1,$1 # 6 cycles from $1 load - ldq $21,16(%3) - xor $2,$3,$3 # 6 cycles from $3 load - - ldq $0,16(%4) - xor $1,$3,$3 - ldq $1,24(%0) - xor $3,$4,$4 # 7 cycles from $4 load - - stq $4,0(%0) - xor $5,$6,$6 # 7 cycles from $6 load - xor $7,$16,$16 # 7 cycles from $16 load - xor $6,$17,$17 # 7 cycles from $17 load - - ldq $2,24(%1) - xor $16,$17,$17 - ldq $3,24(%2) - xor $18,$19,$19 # 8 cycles from $19 load - - stq $17,8(%0) - xor $19,$20,$20 # 8 cycles from $20 load - ldq $4,24(%3) - xor $21,$0,$0 # 7 cycles from $0 load - - ldq $5,24(%4) - xor $20,$0,$0 - ldq $6,32(%0) - ldq $7,32(%1) - - stq $0,16(%0) - xor $1,$2,$2 # 6 cycles from $2 load - ldq $16,32(%2) - xor $3,$4,$4 # 4 cycles from $4 load - - ldq $17,32(%3) - xor $2,$4,$4 - ldq $18,32(%4) - ldq $19,40(%0) - - ldq $20,40(%1) - ldq $21,40(%2) - ldq $0,40(%3) - xor $4,$5,$5 # 7 cycles from $5 load - - stq $5,24(%0) - xor $6,$7,$7 # 7 cycles from $7 load - ldq $1,40(%4) - ldq $2,48(%0) - - ldq $3,48(%1) - xor $7,$16,$16 # 7 cycles from $16 load - ldq $4,48(%2) - xor $17,$18,$18 # 6 cycles from $18 load - - ldq $5,48(%3) - xor $16,$18,$18 - ldq $6,48(%4) - xor $19,$20,$20 # 7 cycles from $20 load - - stq $18,32(%0) - xor $20,$21,$21 # 8 cycles from $21 load - ldq $7,56(%0) - xor $0,$1,$1 # 6 cycles from $1 load - - ldq $16,56(%1) - ldq $17,56(%2) - ldq $18,56(%3) - ldq $19,56(%4) - - ldq $31,256(%0) - xor $21,$1,$1 - ldq $31,256(%1) - xor $2,$3,$3 # 9 cycles from $3 load - - ldq $31,256(%2) - xor $3,$4,$4 # 9 cycles from $4 load - ldq $31,256(%3) - xor $5,$6,$6 # 8 cycles from $6 load - - ldq $31,256(%4) - xor $4,$6,$6 - xor $7,$16,$16 # 7 cycles from $16 load - xor $17,$18,$18 # 6 cycles from $18 load - - stq $6,48(%0) - xor $16,$18,$18 - subq %5,1,%5 - xor $18,$19,$19 # 8 cycles from $19 load - - stq $19,56(%0) - addq %4,64,%4 - addq %3,64,%3 - addq %2,64,%2 - - addq %1,64,%1 - addq %0,64,%0 - bgt %5,5b" - : "=&r"(d), "=&r"(s1), "=&r"(s2), "=&r"(s3), "=r"(s4), "=r"(lines) - /* ARG! We've run out of asm arguments! We've got to reload - all those pointers we just loaded. */ - : "r"(bh_ptr), "i" (&((struct buffer_head *)0)->b_data), "5"(lines) - : "memory", "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", - "$16", "$17", "$18", "$19", "$20", "$21"); - return; + p4 = (unsigned long *) bh_ptr[4]->b_data; + active_template->do_5(bytes, p0, p1, p2, p3, p4); } -#undef prefetch - -#endif /* __alpha__ */ +/* Set of all registered templates. */ +static struct xor_block_template *template_list; -#ifndef __sparc_v9__ +/* The -6*32 shift factor colors the cache. */ +#define BENCH_SIZE (PAGE_SIZE-6*32) -/* - * this one works reasonably on any x86 CPU - * (send me an assembly version for inclusion if you can make it faster) - * - * this one is just as fast as written in pure assembly on x86. - * the reason for this separate version is that the - * fast open-coded xor routine "32reg" produces suboptimal code - * on x86, due to lack of registers. - */ -XORBLOCK_TEMPLATE(8regs) -{ - int len = bh_ptr[0]->b_size; - long *destp = (long *) bh_ptr[0]->b_data; - long *source1, *source2, *source3, *source4; - long lines = len / (sizeof (long)) / 8, i; - - switch(count) { - case 2: - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(source1 + 0); - *(destp + 1) ^= *(source1 + 1); - *(destp + 2) ^= *(source1 + 2); - *(destp + 3) ^= *(source1 + 3); - *(destp + 4) ^= *(source1 + 4); - *(destp + 5) ^= *(source1 + 5); - *(destp + 6) ^= *(source1 + 6); - *(destp + 7) ^= *(source1 + 7); - source1 += 8; - destp += 8; - } - break; - case 3: - source2 = (long *) bh_ptr[2]->b_data; - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(source1 + 0); - *(destp + 0) ^= *(source2 + 0); - *(destp + 1) ^= *(source1 + 1); - *(destp + 1) ^= *(source2 + 1); - *(destp + 2) ^= *(source1 + 2); - *(destp + 2) ^= *(source2 + 2); - *(destp + 3) ^= *(source1 + 3); - *(destp + 3) ^= *(source2 + 3); - *(destp + 4) ^= *(source1 + 4); - *(destp + 4) ^= *(source2 + 4); - *(destp + 5) ^= *(source1 + 5); - *(destp + 5) ^= *(source2 + 5); - *(destp + 6) ^= *(source1 + 6); - *(destp + 6) ^= *(source2 + 6); - *(destp + 7) ^= *(source1 + 7); - *(destp + 7) ^= *(source2 + 7); - source1 += 8; - source2 += 8; - destp += 8; - } - break; - case 4: - source3 = (long *) bh_ptr[3]->b_data; - source2 = (long *) bh_ptr[2]->b_data; - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(source1 + 0); - *(destp + 0) ^= *(source2 + 0); - *(destp + 0) ^= *(source3 + 0); - *(destp + 1) ^= *(source1 + 1); - *(destp + 1) ^= *(source2 + 1); - *(destp + 1) ^= *(source3 + 1); - *(destp + 2) ^= *(source1 + 2); - *(destp + 2) ^= *(source2 + 2); - *(destp + 2) ^= *(source3 + 2); - *(destp + 3) ^= *(source1 + 3); - *(destp + 3) ^= *(source2 + 3); - *(destp + 3) ^= *(source3 + 3); - *(destp + 4) ^= *(source1 + 4); - *(destp + 4) ^= *(source2 + 4); - *(destp + 4) ^= *(source3 + 4); - *(destp + 5) ^= *(source1 + 5); - *(destp + 5) ^= *(source2 + 5); - *(destp + 5) ^= *(source3 + 5); - *(destp + 6) ^= *(source1 + 6); - *(destp + 6) ^= *(source2 + 6); - *(destp + 6) ^= *(source3 + 6); - *(destp + 7) ^= *(source1 + 7); - *(destp + 7) ^= *(source2 + 7); - *(destp + 7) ^= *(source3 + 7); - source1 += 8; - source2 += 8; - source3 += 8; - destp += 8; - } - break; - case 5: - source4 = (long *) bh_ptr[4]->b_data; - source3 = (long *) bh_ptr[3]->b_data; - source2 = (long *) bh_ptr[2]->b_data; - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(source1 + 0); - *(destp + 0) ^= *(source2 + 0); - *(destp + 0) ^= *(source3 + 0); - *(destp + 0) ^= *(source4 + 0); - *(destp + 1) ^= *(source1 + 1); - *(destp + 1) ^= *(source2 + 1); - *(destp + 1) ^= *(source3 + 1); - *(destp + 1) ^= *(source4 + 1); - *(destp + 2) ^= *(source1 + 2); - *(destp + 2) ^= *(source2 + 2); - *(destp + 2) ^= *(source3 + 2); - *(destp + 2) ^= *(source4 + 2); - *(destp + 3) ^= *(source1 + 3); - *(destp + 3) ^= *(source2 + 3); - *(destp + 3) ^= *(source3 + 3); - *(destp + 3) ^= *(source4 + 3); - *(destp + 4) ^= *(source1 + 4); - *(destp + 4) ^= *(source2 + 4); - *(destp + 4) ^= *(source3 + 4); - *(destp + 4) ^= *(source4 + 4); - *(destp + 5) ^= *(source1 + 5); - *(destp + 5) ^= *(source2 + 5); - *(destp + 5) ^= *(source3 + 5); - *(destp + 5) ^= *(source4 + 5); - *(destp + 6) ^= *(source1 + 6); - *(destp + 6) ^= *(source2 + 6); - *(destp + 6) ^= *(source3 + 6); - *(destp + 6) ^= *(source4 + 6); - *(destp + 7) ^= *(source1 + 7); - *(destp + 7) ^= *(source2 + 7); - *(destp + 7) ^= *(source3 + 7); - *(destp + 7) ^= *(source4 + 7); - source1 += 8; - source2 += 8; - source3 += 8; - source4 += 8; - destp += 8; - } - break; - } -} - -/* - * platform independent RAID5 checksum calculation, this should - * be very fast on any platform that has a decent amount of - * registers. (32 or more) - */ -XORBLOCK_TEMPLATE(32regs) -{ - int size = bh_ptr[0]->b_size; - int lines = size / (sizeof (long)) / 8, i; - long *destp = (long *) bh_ptr[0]->b_data; - long *source1, *source2, *source3, *source4; - - /* LOTS of registers available... - We do explicite loop-unrolling here for code which - favours RISC machines. In fact this is almoast direct - RISC assembly on Alpha and SPARC :-) */ - - - switch(count) { - case 2: - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - register long d0, d1, d2, d3, d4, d5, d6, d7; - d0 = destp[0]; /* Pull the stuff into registers */ - d1 = destp[1]; /* ... in bursts, if possible. */ - d2 = destp[2]; - d3 = destp[3]; - d4 = destp[4]; - d5 = destp[5]; - d6 = destp[6]; - d7 = destp[7]; - d0 ^= source1[0]; - d1 ^= source1[1]; - d2 ^= source1[2]; - d3 ^= source1[3]; - d4 ^= source1[4]; - d5 ^= source1[5]; - d6 ^= source1[6]; - d7 ^= source1[7]; - destp[0] = d0; /* Store the result (in burts) */ - destp[1] = d1; - destp[2] = d2; - destp[3] = d3; - destp[4] = d4; /* Store the result (in burts) */ - destp[5] = d5; - destp[6] = d6; - destp[7] = d7; - source1 += 8; - destp += 8; - } - break; - case 3: - source2 = (long *) bh_ptr[2]->b_data; - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - register long d0, d1, d2, d3, d4, d5, d6, d7; - d0 = destp[0]; /* Pull the stuff into registers */ - d1 = destp[1]; /* ... in bursts, if possible. */ - d2 = destp[2]; - d3 = destp[3]; - d4 = destp[4]; - d5 = destp[5]; - d6 = destp[6]; - d7 = destp[7]; - d0 ^= source1[0]; - d1 ^= source1[1]; - d2 ^= source1[2]; - d3 ^= source1[3]; - d4 ^= source1[4]; - d5 ^= source1[5]; - d6 ^= source1[6]; - d7 ^= source1[7]; - d0 ^= source2[0]; - d1 ^= source2[1]; - d2 ^= source2[2]; - d3 ^= source2[3]; - d4 ^= source2[4]; - d5 ^= source2[5]; - d6 ^= source2[6]; - d7 ^= source2[7]; - destp[0] = d0; /* Store the result (in burts) */ - destp[1] = d1; - destp[2] = d2; - destp[3] = d3; - destp[4] = d4; /* Store the result (in burts) */ - destp[5] = d5; - destp[6] = d6; - destp[7] = d7; - source1 += 8; - source2 += 8; - destp += 8; - } - break; - case 4: - source3 = (long *) bh_ptr[3]->b_data; - source2 = (long *) bh_ptr[2]->b_data; - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - register long d0, d1, d2, d3, d4, d5, d6, d7; - d0 = destp[0]; /* Pull the stuff into registers */ - d1 = destp[1]; /* ... in bursts, if possible. */ - d2 = destp[2]; - d3 = destp[3]; - d4 = destp[4]; - d5 = destp[5]; - d6 = destp[6]; - d7 = destp[7]; - d0 ^= source1[0]; - d1 ^= source1[1]; - d2 ^= source1[2]; - d3 ^= source1[3]; - d4 ^= source1[4]; - d5 ^= source1[5]; - d6 ^= source1[6]; - d7 ^= source1[7]; - d0 ^= source2[0]; - d1 ^= source2[1]; - d2 ^= source2[2]; - d3 ^= source2[3]; - d4 ^= source2[4]; - d5 ^= source2[5]; - d6 ^= source2[6]; - d7 ^= source2[7]; - d0 ^= source3[0]; - d1 ^= source3[1]; - d2 ^= source3[2]; - d3 ^= source3[3]; - d4 ^= source3[4]; - d5 ^= source3[5]; - d6 ^= source3[6]; - d7 ^= source3[7]; - destp[0] = d0; /* Store the result (in burts) */ - destp[1] = d1; - destp[2] = d2; - destp[3] = d3; - destp[4] = d4; /* Store the result (in burts) */ - destp[5] = d5; - destp[6] = d6; - destp[7] = d7; - source1 += 8; - source2 += 8; - source3 += 8; - destp += 8; - } - break; - case 5: - source4 = (long *) bh_ptr[4]->b_data; - source3 = (long *) bh_ptr[3]->b_data; - source2 = (long *) bh_ptr[2]->b_data; - source1 = (long *) bh_ptr[1]->b_data; - for (i = lines; i > 0; i--) { - register long d0, d1, d2, d3, d4, d5, d6, d7; - d0 = destp[0]; /* Pull the stuff into registers */ - d1 = destp[1]; /* ... in bursts, if possible. */ - d2 = destp[2]; - d3 = destp[3]; - d4 = destp[4]; - d5 = destp[5]; - d6 = destp[6]; - d7 = destp[7]; - d0 ^= source1[0]; - d1 ^= source1[1]; - d2 ^= source1[2]; - d3 ^= source1[3]; - d4 ^= source1[4]; - d5 ^= source1[5]; - d6 ^= source1[6]; - d7 ^= source1[7]; - d0 ^= source2[0]; - d1 ^= source2[1]; - d2 ^= source2[2]; - d3 ^= source2[3]; - d4 ^= source2[4]; - d5 ^= source2[5]; - d6 ^= source2[6]; - d7 ^= source2[7]; - d0 ^= source3[0]; - d1 ^= source3[1]; - d2 ^= source3[2]; - d3 ^= source3[3]; - d4 ^= source3[4]; - d5 ^= source3[5]; - d6 ^= source3[6]; - d7 ^= source3[7]; - d0 ^= source4[0]; - d1 ^= source4[1]; - d2 ^= source4[2]; - d3 ^= source4[3]; - d4 ^= source4[4]; - d5 ^= source4[5]; - d6 ^= source4[6]; - d7 ^= source4[7]; - destp[0] = d0; /* Store the result (in burts) */ - destp[1] = d1; - destp[2] = d2; - destp[3] = d3; - destp[4] = d4; /* Store the result (in burts) */ - destp[5] = d5; - destp[6] = d6; - destp[7] = d7; - source1 += 8; - source2 += 8; - source3 += 8; - source4 += 8; - destp += 8; - } - break; - } -} - -/* - * (the -6*32 shift factor colors the cache) - */ -#define SIZE (PAGE_SIZE-6*32) - -static void xor_speed ( struct xor_block_template * func, - struct buffer_head *b1, struct buffer_head *b2) +static void +do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) { int speed; unsigned long now; int i, count, max; - struct buffer_head *bh_ptr[6]; - func->next = xor_functions; - xor_functions = func; - bh_ptr[0] = b1; - bh_ptr[1] = b2; + tmpl->next = template_list; + template_list = tmpl; /* - * count the number of XORs done during a whole jiffy. - * calculate the speed of checksumming from this. - * (we use a 2-page allocation to have guaranteed - * color L1-cache layout) + * Count the number of XORs done during a whole jiffy, and use + * this to calculate the speed of checksumming. We use a 2-page + * allocation to have guaranteed color L1-cache layout. */ max = 0; for (i = 0; i < 5; i++) { @@ -2600,7 +82,7 @@ count = 0; while (jiffies == now) { mb(); - func->xor_block(2,bh_ptr); + tmpl->do_2(BENCH_SIZE, b1, b2); mb(); count++; mb(); @@ -2609,120 +91,53 @@ max = count; } - speed = max * (HZ*SIZE/1024); - func->speed = speed; + speed = max * (HZ * BENCH_SIZE / 1024); + tmpl->speed = speed; - printk( " %-10s: %5d.%03d MB/sec\n", func->name, - speed / 1000, speed % 1000); + printk(" %-10s: %5d.%03d MB/sec\n", tmpl->name, + speed / 1000, speed % 1000); } -static inline void pick_fastest_function(void) +static int +calibrate_xor_block(void) { + void *b1, *b2; struct xor_block_template *f, *fastest; - fastest = xor_functions; - for (f = fastest; f; f = f->next) { - if (f->speed > fastest->speed) - fastest = f; - } -#ifdef CONFIG_X86_XMM - if (cpu_has_xmm) { - /* we force the use of the KNI xor block because it - can write around l2. we may also be able - to load into the l1 only depending on how - the cpu deals with a load to a line that is - being prefetched. - */ - fastest = &t_xor_block_pIII_kni; - } -#endif -#ifdef __alpha__ - if (implver() == IMPLVER_EV6) { - /* Force the use of alpha_prefetch if EV6, as it - is significantly faster in the cold cache case. */ - fastest = &t_xor_block_alpha_prefetch; - } -#endif - xor_block = fastest->xor_block; - printk( "using fastest function: %s (%d.%03d MB/sec)\n", fastest->name, - fastest->speed / 1000, fastest->speed % 1000); -} - -static struct buffer_head b1, b2; - -void calibrate_xor_block(void) -{ - if (xor_block) - return; - memset(&b1,0,sizeof(b1)); - b2 = b1; - - b1.b_data = (char *) md__get_free_pages(GFP_KERNEL,2); - if (!b1.b_data) { - pick_fastest_function(); - return; + b1 = (void *) md__get_free_pages(GFP_KERNEL, 2); + if (! b1) { + printk("raid5: Yikes! No memory available.\n"); + return -ENOMEM; } - b2.b_data = b1.b_data + 2*PAGE_SIZE + SIZE; - - b1.b_size = SIZE; + b2 = b1 + 2*PAGE_SIZE + BENCH_SIZE; printk(KERN_INFO "raid5: measuring checksumming speed\n"); + sti(); - sti(); /* should be safe */ +#define xor_speed(templ) do_xor_speed((templ), b1, b2) -#if defined(__sparc__) && !defined(__sparc_v9__) - printk(KERN_INFO "raid5: trying high-speed SPARC checksum routine\n"); - xor_speed(&t_xor_block_SPARC,&b1,&b2); -#endif + XOR_TRY_TEMPLATES; -#ifdef CONFIG_X86_XMM - if (cpu_has_xmm) { - printk(KERN_INFO - "raid5: KNI detected, trying cache-avoiding KNI checksum routine\n"); - xor_speed(&t_xor_block_pIII_kni,&b1,&b2); - } -#endif /* CONFIG_X86_XMM */ +#undef xor_speed -#ifdef __i386__ - if (md_cpu_has_mmx()) { - printk(KERN_INFO - "raid5: MMX detected, trying high-speed MMX checksum routines\n"); - xor_speed(&t_xor_block_pII_mmx,&b1,&b2); - xor_speed(&t_xor_block_p5_mmx,&b1,&b2); - } -#endif /* __i386__ */ + free_pages((unsigned long)b1, 2); -#ifdef __alpha__ - xor_speed(&t_xor_block_alpha,&b1,&b2); - xor_speed(&t_xor_block_alpha_prefetch,&b1,&b2); -#endif - - xor_speed(&t_xor_block_8regs,&b1,&b2); - xor_speed(&t_xor_block_32regs,&b1,&b2); + fastest = template_list; + for (f = fastest; f; f = f->next) + if (f->speed > fastest->speed) + fastest = f; - free_pages((unsigned long)b1.b_data,2); - pick_fastest_function(); -} +#ifdef XOR_SELECT_TEMPLATE + fastest = XOR_SELECT_TEMPLATE(fastest); +#endif -#else /* __sparc_v9__ */ + active_template = fastest; + printk("raid5: using function: %s (%d.%03d MB/sec)\n", + fastest->name, fastest->speed / 1000, fastest->speed % 1000); -void calibrate_xor_block(void) -{ - if (xor_block) - return; - printk(KERN_INFO "raid5: using high-speed VIS checksum routine\n"); - xor_block = xor_block_VIS; + return 0; } -#endif /* __sparc_v9__ */ - MD_EXPORT_SYMBOL(xor_block); -MD_EXPORT_SYMBOL(calibrate_xor_block); -#ifdef MODULE -int init_module(void) -{ - calibrate_xor_block(); - return 0; -} -#endif +module_init(calibrate_xor_block); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-aimslab.c linux/drivers/media/radio/radio-aimslab.c --- v2.4.0-test10/linux/drivers/media/radio/radio-aimslab.c Mon Jun 19 13:25:06 2000 +++ linux/drivers/media/radio/radio-aimslab.c Fri Nov 17 17:56:51 2000 @@ -322,17 +322,12 @@ static struct video_device rtrack_radio= { - "RadioTrack radio", - VID_TYPE_TUNER, - VID_HARDWARE_RTRACK, - rt_open, - rt_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - rt_ioctl, - NULL, - NULL + name: "RadioTrack radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_RTRACK, + open: rt_open, + close: rt_close, + ioctl: rt_ioctl, }; static int __init rtrack_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-aztech.c linux/drivers/media/radio/radio-aztech.c --- v2.4.0-test10/linux/drivers/media/radio/radio-aztech.c Wed Sep 29 14:02:59 1999 +++ linux/drivers/media/radio/radio-aztech.c Fri Nov 17 17:56:51 2000 @@ -273,17 +273,12 @@ static struct video_device aztech_radio= { - "Aztech radio", - VID_TYPE_TUNER, - VID_HARDWARE_AZTECH, - az_open, - az_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - az_ioctl, - NULL, - NULL + name: "Aztech radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_AZTECH, + open: az_open, + close: az_close, + ioctl: az_ioctl, }; static int __init aztech_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-cadet.c linux/drivers/media/radio/radio-cadet.c --- v2.4.0-test10/linux/drivers/media/radio/radio-cadet.c Wed May 3 01:45:19 2000 +++ linux/drivers/media/radio/radio-cadet.c Fri Nov 17 17:56:51 2000 @@ -12,6 +12,10 @@ * Scott McGrath (smcgrath@twilight.vtc.vsc.edu) * William McGrath (wmcgrath@twilight.vtc.vsc.edu) * + * History: + * 2000-04-29 Russell Kroll + * Added ISAPnP detection for Linux 2.3/2.4 + * */ #include /* Modules */ @@ -40,6 +44,17 @@ 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 int isapnp_cadet_probe(void); +#endif + /* * Signal Strength Threshold Values * The V4L API spec does not define any particular unit for the signal @@ -47,8 +62,6 @@ */ static __u16 sigtable[2][4]={{5,10,30,150},{28,40,63,1000}}; - - void cadet_wake(unsigned long qnum) { switch(qnum) { @@ -529,20 +542,41 @@ static struct video_device cadet_radio= { - "Cadet radio", - VID_TYPE_TUNER, - VID_HARDWARE_CADET, - cadet_open, - cadet_close, - cadet_read, - NULL, /* Can't write */ - NULL, /* No poll */ - cadet_ioctl, - NULL, - NULL + name: "Cadet radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_CADET, + open: cadet_open, + close: cadet_close, + read: cadet_read, + ioctl: cadet_ioctl, }; -#ifndef MODULE +#ifdef CONFIG_ISAPNP +static int isapnp_cadet_probe(void) +{ + dev = isapnp_find_dev (NULL, ISAPNP_VENDOR('M','S','M'), + ISAPNP_FUNCTION(0x0c24), NULL); + + if (!dev) + return -ENODEV; + if (dev->prepare(dev)<0) + return -EAGAIN; + if (!(dev->resource[0].flags & IORESOURCE_IO)) + return -ENODEV; + if (dev->activate(dev)<0) { + printk ("radio-cadet: isapnp configure failed (out of resources?)\n"); + return -ENOMEM; + } + + io = dev->resource[0].start; + + printk ("radio-cadet: ISAPnP reports card at %#x\n", io); + + return io; +} +#endif /* CONFIG_ISAPNP */ + +#ifdef MODULE static int cadet_probe(void) { static int iovals[8]={0x330,0x332,0x334,0x336,0x338,0x33a,0x33c,0x33e}; @@ -559,13 +593,20 @@ } return -1; } -#endif +#endif /* MODULE */ static int __init cadet_init(void) { -#ifndef MODULE +#ifdef CONFIG_ISAPNP + io = isapnp_cadet_probe(); + + if (io < 0) + return (io); +#else +#ifndef MODULE /* only probe on non-ISAPnP monolithic compiles */ io = cadet_probe (); -#endif +#endif /* MODULE */ +#endif /* CONFIG_ISAPNP */ if(io < 0) { #ifdef MODULE @@ -596,6 +637,11 @@ { 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-test10/linux/drivers/media/radio/radio-gemtek.c linux/drivers/media/radio/radio-gemtek.c --- v2.4.0-test10/linux/drivers/media/radio/radio-gemtek.c Mon Mar 13 09:43:36 2000 +++ linux/drivers/media/radio/radio-gemtek.c Fri Nov 17 17:56:51 2000 @@ -249,17 +249,12 @@ static struct video_device gemtek_radio= { - "GemTek radio", - VID_TYPE_TUNER, - VID_HARDWARE_GEMTEK, - gemtek_open, - gemtek_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - gemtek_ioctl, - NULL, - NULL + name: "GemTek radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_GEMTEK, + open: gemtek_open, + close: gemtek_close, + ioctl: gemtek_ioctl, }; static int __init gemtek_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-maestro.c linux/drivers/media/radio/radio-maestro.c --- v2.4.0-test10/linux/drivers/media/radio/radio-maestro.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/media/radio/radio-maestro.c Fri Nov 17 17:56:51 2000 @@ -69,17 +69,12 @@ static struct video_device maestro_radio= { - "Maestro radio", - VID_TYPE_TUNER, - VID_HARDWARE_SF16MI, - radio_open, - radio_close, - NULL, - NULL, - NULL, - radio_ioctl, - NULL, - NULL + name: "Maestro radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_SF16MI, + open: radio_open, + close: radio_close, + ioctl: radio_ioctl, }; static struct radio_device @@ -300,21 +295,17 @@ inline static __u16 radio_install(struct pci_dev *pcidev); -#ifdef MODULE MODULE_AUTHOR("Adam Tlalka, atlka@pg.gda.pl"); MODULE_DESCRIPTION("Radio driver for the Maestro PCI sound card radio."); EXPORT_NO_SYMBOLS; -void cleanup_module(void) +void __exit maestro_radio_exit(void) { video_unregister_device(&maestro_radio); } -int init_module(void) -#else -int __init maestro_radio_init(struct video_init *v) -#endif +int __init maestro_radio_init(void) { register __u16 found=0; struct pci_dev *pcidev = NULL; @@ -334,6 +325,9 @@ } return 0; } + +module_init(maestro_radio_init); +module_exit(maestro_radio_exit); inline static __u16 radio_power_on(struct radio_device *dev) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-miropcm20.c linux/drivers/media/radio/radio-miropcm20.c --- v2.4.0-test10/linux/drivers/media/radio/radio-miropcm20.c Tue Aug 22 11:29:02 2000 +++ linux/drivers/media/radio/radio-miropcm20.c Fri Nov 17 17:56:51 2000 @@ -192,17 +192,12 @@ static struct video_device pcm20_radio= { - "Miro PCM 20 radio", - VID_TYPE_TUNER, - VID_HARDWARE_RTRACK, - pcm20_open, - pcm20_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - pcm20_ioctl, - NULL, - NULL + name: "Miro PCM 20 radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_RTRACK, + open: pcm20_open, + close: pcm20_close, + ioctl: pcm20_ioctl, }; static int __init pcm20_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-rtrack2.c linux/drivers/media/radio/radio-rtrack2.c --- v2.4.0-test10/linux/drivers/media/radio/radio-rtrack2.c Thu Oct 28 16:12:56 1999 +++ linux/drivers/media/radio/radio-rtrack2.c Fri Nov 17 17:56:51 2000 @@ -215,17 +215,12 @@ static struct video_device rtrack2_radio= { - "RadioTrack II radio", - VID_TYPE_TUNER, - VID_HARDWARE_RTRACK2, - rt_open, - rt_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - rt_ioctl, - NULL, - NULL + name: "RadioTrack II radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_RTRACK2, + open: rt_open, + close: rt_close, + ioctl: rt_ioctl, }; static int __init rtrack2_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-sf16fmi.c linux/drivers/media/radio/radio-sf16fmi.c --- v2.4.0-test10/linux/drivers/media/radio/radio-sf16fmi.c Thu Oct 28 16:13:00 1999 +++ linux/drivers/media/radio/radio-sf16fmi.c Fri Nov 17 17:56:51 2000 @@ -276,17 +276,12 @@ static struct video_device fmi_radio= { - "SF16FMx radio", - VID_TYPE_TUNER, - VID_HARDWARE_SF16MI, - fmi_open, - fmi_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - fmi_ioctl, - NULL, - NULL + name: "SF16FMx radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_SF16MI, + open: fmi_open, + close: fmi_close, + ioctl: fmi_ioctl, }; static int __init fmi_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-terratec.c linux/drivers/media/radio/radio-terratec.c --- v2.4.0-test10/linux/drivers/media/radio/radio-terratec.c Thu Oct 28 16:13:03 1999 +++ linux/drivers/media/radio/radio-terratec.c Fri Nov 17 17:56:51 2000 @@ -294,17 +294,12 @@ static struct video_device terratec_radio= { - "TerraTec ActiveRadio", - VID_TYPE_TUNER, - VID_HARDWARE_TERRATEC, - tt_open, - tt_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - tt_ioctl, - NULL, - NULL + name: "TerraTec ActiveRadio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_TERRATEC, + open: tt_open, + close: tt_close, + ioctl: tt_ioctl, }; static int __init terratec_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-trust.c linux/drivers/media/radio/radio-trust.c --- v2.4.0-test10/linux/drivers/media/radio/radio-trust.c Thu Oct 28 16:13:07 1999 +++ linux/drivers/media/radio/radio-trust.c Fri Nov 17 17:56:51 2000 @@ -286,17 +286,12 @@ static struct video_device trust_radio= { - "Trust FM Radio", - VID_TYPE_TUNER, - VID_HARDWARE_TRUST, - tr_open, - tr_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - tr_ioctl, - NULL, - NULL + name: "Trust FM Radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_TRUST, + open: tr_open, + close: tr_close, + ioctl: tr_ioctl, }; static int __init trust_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-typhoon.c linux/drivers/media/radio/radio-typhoon.c --- v2.4.0-test10/linux/drivers/media/radio/radio-typhoon.c Fri Aug 4 18:36:46 2000 +++ linux/drivers/media/radio/radio-typhoon.c Fri Nov 17 17:56:51 2000 @@ -273,27 +273,19 @@ static struct typhoon_device typhoon_unit = { - 0, /* users */ - CONFIG_RADIO_TYPHOON_PORT, /* iobase */ - 0, /* curvol */ - 0, /* muted */ - CONFIG_RADIO_TYPHOON_MUTEFREQ, /* curfreq */ - CONFIG_RADIO_TYPHOON_MUTEFREQ /* mutefreq */ + iobase: CONFIG_RADIO_TYPHOON_PORT, + curfreq: CONFIG_RADIO_TYPHOON_MUTEFREQ, + mutefreq: CONFIG_RADIO_TYPHOON_MUTEFREQ, }; static struct video_device typhoon_radio = { - "Typhoon Radio", - VID_TYPE_TUNER, - VID_HARDWARE_TYPHOON, - typhoon_open, - typhoon_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* Can't poll */ - typhoon_ioctl, - NULL, - NULL + name: "Typhoon Radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_TYPHOON, + open: typhoon_open, + close: typhoon_close, + ioctl: typhoon_ioctl, }; #ifdef CONFIG_RADIO_TYPHOON_PROC_FS diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/radio/radio-zoltrix.c linux/drivers/media/radio/radio-zoltrix.c --- v2.4.0-test10/linux/drivers/media/radio/radio-zoltrix.c Thu Oct 28 16:13:13 1999 +++ linux/drivers/media/radio/radio-zoltrix.c Fri Nov 17 17:56:51 2000 @@ -341,17 +341,12 @@ static struct video_device zoltrix_radio = { - "Zoltrix Radio Plus", - VID_TYPE_TUNER, - VID_HARDWARE_ZOLTRIX, - zol_open, - zol_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, - zol_ioctl, - NULL, - NULL + name: "Zoltrix Radio Plus", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_ZOLTRIX, + open: zol_open, + close: zol_close, + ioctl: zol_ioctl, }; static int __init zoltrix_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/Makefile linux/drivers/media/video/Makefile --- v2.4.0-test10/linux/drivers/media/video/Makefile Tue Aug 22 11:29:02 2000 +++ linux/drivers/media/video/Makefile Sun Nov 12 20:47:19 2000 @@ -39,8 +39,8 @@ obj-$(CONFIG_VIDEO_DEV) += videodev.o obj-$(CONFIG_BUS_I2C) += i2c-old.o -obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \ - tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o tuner.o +obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tvaudio.o \ + tda7432.o tda9875.o tuner.o obj-$(CONFIG_SOUND_TVMIXER) += tvmixer.o obj-$(CONFIG_VIDEO_ZR36120) += zoran.o i2c-old.o tuner.o saa7110.o saa7111.o saa7185.o diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/audiochip.h linux/drivers/media/video/audiochip.h --- v2.4.0-test10/linux/drivers/media/video/audiochip.h Thu Dec 16 13:59:38 1999 +++ linux/drivers/media/video/audiochip.h Sun Nov 12 20:47:19 2000 @@ -11,6 +11,16 @@ /* select from TV,radio,extern,MUTE */ #define AUDC_SET_INPUT _IOW('m',17,int) +/* audio inputs */ +#define AUDIO_TUNER 0x00 +#define AUDIO_RADIO 0x01 +#define AUDIO_EXTERN 0x02 +#define AUDIO_INTERN 0x03 +#define AUDIO_OFF 0x04 +#define AUDIO_ON 0x05 +#define AUDIO_MUTE 0x80 +#define AUDIO_UNMUTE 0x81 + /* all the stuff below is obsolete and just here for reference. I'll * remove it once the driver is tested and works fine. * diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/bttv-cards.c linux/drivers/media/video/bttv-cards.c --- v2.4.0-test10/linux/drivers/media/video/bttv-cards.c Sun Aug 6 12:45:28 2000 +++ linux/drivers/media/video/bttv-cards.c Sun Nov 12 20:47:19 2000 @@ -1,7 +1,6 @@ /* bttv-cards.c -- this file has card-specific stuff - bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) @@ -31,21 +30,32 @@ #include #include #include +#include #include -#include "bttv.h" +#include "bttvp.h" #include "tuner.h" /* fwd decl */ static void hauppauge_eeprom(struct bttv *btv); -static void hauppauge_boot_msp34xx(struct bttv *btv); static void init_PXC200(struct bttv *btv); +#if 0 static void init_tea5757(struct bttv *btv); +#endif + +static void winview_audio(struct bttv *btv, struct video_audio *v, int set); +static void avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, + int set); +static void terratv_audio(struct bttv *btv, struct video_audio *v, int set); +static void gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set); MODULE_PARM(card,"1-4i"); +MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list"); MODULE_PARM(pll,"1-4i"); +MODULE_PARM_DESC(pll,"specify installed crystal (0=none, 28=28 MHz, 35=35 MHz)"); MODULE_PARM(autoload,"i"); +MODULE_PARM_DESC(autoload,"automatically load i2c modules like tuner.o, default is 1 (yes)"); static unsigned int card[4] = { -1, -1, -1, -1 }; static unsigned int pll[4] = { -1, -1, -1, -1 }; @@ -55,6 +65,14 @@ static unsigned int autoload = 0; #endif +MODULE_PARM(gpiomask,"i"); +MODULE_PARM(audioall,"i"); +MODULE_PARM(audiomux,"1-5i"); +static unsigned int gpiomask = -1; +static unsigned int audioall = -1; +static unsigned int audiomux[5] = { -1, -1, -1, -1, -1 }; + + /* ----------------------------------------------------------------------- */ /* list of card IDs for bt878+ cards */ @@ -66,8 +84,9 @@ { 0x00011002, BTTV_HAUPPAUGE878, "ATI TV Wonder" }, { 0x00011461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, { 0x00021461, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, + { 0x00031002, BTTV_HAUPPAUGE878, "ATI TV Wonder/VE" }, { 0x00031461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, - { 0x00041461, BTTV_AVPHONE98, "AVerMedia TVPhone98" }, + { 0x00041461, BTTV_AVERMEDIA98, "AVerMedia TVCapture 98" }, { 0x10b42636, BTTV_HAUPPAUGE878, "STB ???" }, { 0x1118153b, BTTV_TERRATVALUE, "Terratec TV Value" }, { 0x1123153b, BTTV_TERRATVRADIO, "Terratec TV/Radio+" }, @@ -77,12 +96,17 @@ { 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" }, { 0x217d6606, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, { 0x263610b4, BTTV_STB2, "STB TV PCI FM, P/N 6000704" }, + { 0x3000121a, 0/* no entry yet */,"VoodooTV 200" }, { 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" }, { 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" }, { 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" }, { 0x300214ff, BTTV_PHOEBE_TVMAS, "Phoebe TV Master" }, + { 0x39000070, BTTV_HAUPPAUGE878, "Hauppauge WinTV-D" }, { 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" }, - { 0x402010fc, 0 /* no tvcards entry yet */, "I-O Data Co. GV-BCV3/PCI" }, + { 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" }, + { 0x402010fc, BTTV_GVBCTV3PCI, "I-O Data Co. GV-BCV3/PCI" }, + { 0xff000070, BTTV_HAUPPAUGE878, "Osprey-100" }, + { 0xff010070, BTTV_HAUPPAUGE878, "Osprey-200" }, #if 0 /* probably wrong */ { 0x14610002, BTTV_AVERMEDIA98, "Avermedia TVCapture 98" }, { 0x6606217d, BTTV_WINFAST2000, "Leadtek WinFast TV 2000" }, @@ -93,286 +117,694 @@ /* ----------------------------------------------------------------------- */ /* array with description for bt848 / bt878 tv/grabber cards */ -struct tvcard bttv_tvcards[] = +struct tvcard bttv_tvcards[] = { { - /* 0x00 */ - { " *** UNKNOWN *** ", - 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "MIRO PCTV", - 4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Hauppauge old", - 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0,0,0,1, PLL_NONE, -1 }, - { "STB", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, - 0,1,1,1,1,0,0,1, PLL_NONE, -1 }, - - { "Intel", - 3, 1, 0, -1, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Diamond DTV2000", - 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "AVerMedia TVPhone", - 3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "MATRIX-Vision MV-Delta", - 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x08 */ - { "Fly Video II", - 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1}, - { 0, 0xc00, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "TurboTV", - 3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Hauppauge new (bt878)", - 4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,0,1,0,0,0,1, PLL_28, -1 }, - { "MIRO PCTV pro", - 3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0, - /* 3, 1, 0, 2, 0x3004F, { 2, 3, 1, 1}, {1, 0x10011, 5, 0,10}, 0x3004F, */ - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - { "ADS Technologies Channel Surfer TV", - 3, 1, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "AVerMedia TVCapture 98", - 3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Aimslab VHX", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Zoltrix TV-Max", - 3, 1, 0, 2,15, { 2, 3, 1, 1}, {0 , 0, 1 , 0, 10},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x10 */ - { "Pixelview PlayTV (bt878)", - 3, 1, 0, 2, 0x01fe00, { 2, 3, 1, 1}, - { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Leadtek WinView 601", - 3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0}, - { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "AVEC Intercapture", - 3, 2, 0, 2, 0, {2, 3, 1, 1}, {1, 0, 0, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "LifeView FlyKit w/o Tuner", - 3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}, { 0 },0, - 0,0,0,0,0,0,0,1, PLL_NONE, -1 }, - - { "CEI Raffles Card", - 3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Lucky Star Image World ConferenceTV", - 3, 1, 0, 2, 0x00fffe07, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_28, TUNER_PHILIPS_PAL_I }, - { "Phoebe Tv Master + FM", - 3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Modular Technology MM205 PCTV, bt878", - 2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 },0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x18 */ - { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)", - 3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Terratec/Vobis TV-Boostar", - 3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Newer Hauppauge WinCam (bt878)", - 4, 1, 0, 3, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "MAXI TV Video PCI2", - 3, 1, 0, 2, 0xffff, { 2, 3, 1, 1}, { 0, 1, 2, 3, 0xc00},0, - 1,1,1,1,0,0,0,1, PLL_NONE, TUNER_PHILIPS_SECAM }, - - { "Terratec TerraTV+", - 3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, - { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Imagenation PXC200", - 5, 1, -1, 4, 0, { 2, 3, 1, 0, 0}, { 0 }, 0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "FlyVideo 98", - 3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, - { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "iProTV", - 3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - - /* 0x20 */ - { "Intel Create and Share PCI", - 4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Terratec TerraTValue", - 3, 1, 0, 2, 0xffff00, { 2, 3, 1, 1}, - { 0x500, 0, 0x300, 0x900, 0x900},0, - 1,1,1,1,0,0,0,1, PLL_NONE, -1 }, - { "Leadtek WinFast 2000", - 3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0}, - { 0x621000,0x6ddf07,0x621100,0x620000,0xE210000,0x620000},0, - 1,1,1,1,1,0,0,1, PLL_28, -1 }, - { "Chronos Video Shuttle II", - 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - - { "Typhoon TView TV/FM Tuner", - 3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "PixelView PlayTV pro", - 3, 1, 0, 2, 0xff, { 2, 3, 1, 1 }, - { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0, - 0,0,0,0,0,0,0,1, PLL_28, -1 }, - { "TView99 CPH063", - 3, 1, 0, 2, 0x551e00, { 2, 3, 1, 1}, - { 0x551400, 0x551200, 0, 0, 0, 0x551200 }, 0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - { "Pinnacle PCTV Rave", - 3, 1, 0, 2, 0x03000F, { 2, 3, 1, 1}, { 2, 0, 0, 0, 1},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, - - /* 0x28 */ - { "STB2", - 3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0, - 0,1,1,1,0,1,1,1, PLL_NONE, -1 }, - { "AVerMedia TVPhone 98", - 3, 4, 0, 2, 4, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0, - 1,1,1,1,0,0,0,1, PLL_28, 5 }, - { "ProVideo PV951", /* pic16c54 */ - 3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0, - 0,0,0,0,0,0,0,0, PLL_28, 1 }, - { "Little OnAir TV", - 3, 1, 0, 2, 0xe00b, {2, 3, 1, 1}, - {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc},0, - 0,0,0,0,0,0,0,0, PLL_NONE, -1 }, - - { "Sigma TVII-FM", - 2, 1, 0, -1, 3, {2, 3, 1, 1}, {1, 1, 0, 2, 3},0, - 0,0,0,0,0,0,0,0, PLL_NONE, -1 }, - { "MATRIX-Vision MV-Delta 2", - 5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0, - 0,0,0,0,0,0,0,0, PLL_28, -1 }, - { "Zoltrix Genie TV", - 3, 1, 0, 2, 0xbcf03f, { 2, 3, 1, 1}, - { 0xbc803f, 0, 0xbcb03f, 0, 0xbcb03f}, 0, - 0,0,0,0,0,0,0,0, PLL_28, 5 }, - { "Terratec TV/Radio+", /* Radio ?? */ - 3, 1, 0, 2, 0x1f0000, { 2, 3, 1, 1}, - { 0xe2ffff, 0xebffff, 0, 0, 0xe0ffff, 0xe2ffff },0, - 0,0,0,0,0,0,0,0, PLL_35, 1 }, - - /* 0x30 */ - { "Dynalink Magic TView ", - 3, 1, 0, 2, 15, { 2, 3, 1, 1}, {2,0,0,0,1},0, - 1,1,1,1,0,0,0,1, PLL_28, -1 }, -}; +/* ---- card 0x00 ---------------------------------- */ + name: " *** UNKNOWN *** ", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + muxsel: { 2, 3, 1, 0}, + tuner_type: -1, +},{ + name: "MIRO PCTV", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 15, + muxsel: { 2, 3, 1, 1}, + audiomux: { 2, 0, 0, 0, 10}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Hauppauge old", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 1, 2, 3, 4}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "STB", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 3, 1, 1}, + audiomux: { 4, 0, 2, 3, 1}, + no_msp34xx: 1, + needs_tvaudio: 1, + tuner_type: -1, +},{ + +/* ---- card 0x04 ---------------------------------- */ + name: "Intel", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: -1, + gpiomask: 7, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 1, 2, 3, 4}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Diamond DTV2000", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 3, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 1, 0, 1, 3}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "AVerMedia TVPhone", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 3, + gpiomask: 15, + muxsel: { 2, 3, 1, 1}, + audiomux: {12, 4,11,11, 0}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "MATRIX-Vision MV-Delta", + video_inputs: 5, + audio_inputs: 1, + tuner: -1, + svhs: 3, + gpiomask: 0, + muxsel: { 2, 3, 1, 0, 0}, + audiomux: {0 }, + needs_tvaudio: 1, + tuner_type: -1, +},{ + +/* ---- card 0x08 ---------------------------------- */ + name: "Fly Video II", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xc00, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 0xc00, 0x800, 0x400, 0xc00, 0}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "TurboTV", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 3, + muxsel: { 2, 3, 1, 1}, + audiomux: { 1, 1, 2, 3, 0}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Hauppauge new (bt878)", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 0, 1, 1}, + audiomux: { 0, 1, 2, 3, 4}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "MIRO PCTV pro", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 65551, + muxsel: { 2, 3, 1, 1}, + audiomux: {1,65537, 0, 0,10}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + +/* ---- card 0x0c ---------------------------------- */ + name: "ADS Technologies Channel Surfer TV", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 15, + muxsel: { 2, 3, 1, 1}, + audiomux: { 13, 14, 11, 7, 0, 0}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "AVerMedia TVCapture 98", + video_inputs: 3, + audio_inputs: 4, + tuner: 0, + svhs: 2, + gpiomask: 15, + muxsel: { 2, 3, 1, 1}, + audiomux: { 13, 14, 11, 7, 0, 0}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: 5, +},{ + name: "Aimslab VHX", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 1, 2, 3, 4}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Zoltrix TV-Max", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 15, + muxsel: { 2, 3, 1, 1}, + audiomux: {0 , 0, 1 , 0, 10}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + +/* ---- card 0x10 ---------------------------------- */ + name: "Pixelview PlayTV (bt878)", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x01fe00, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 }, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "Leadtek WinView 601", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x8300f8, + muxsel: { 2, 3, 1, 1,0}, + audiomux: { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007}, + needs_tvaudio: 1, + tuner_type: -1, + audio_hook: winview_audio, +},{ + name: "AVEC Intercapture", + video_inputs: 3, + audio_inputs: 2, + tuner: 0, + svhs: 2, + gpiomask: 0, + muxsel: {2, 3, 1, 1}, + audiomux: {1, 0, 0, 0, 0}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "LifeView FlyKit w/o Tuner", + video_inputs: 3, + audio_inputs: 1, + tuner: -1, + svhs: -1, + gpiomask: 0x8dff00, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0 }, + no_msp34xx: 1, + tuner_type: -1, +},{ + +/* ---- card 0x14 ---------------------------------- */ + name: "CEI Raffles Card", + video_inputs: 3, + audio_inputs: 3, + tuner: 0, + svhs: 2, + muxsel: {2, 3, 1, 1}, + tuner_type: -1, +},{ + name: "Lucky Star Image World ConferenceTV", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x00fffe07, + muxsel: { 2, 3, 1, 1}, + audiomux: { 131072, 1, 1638400, 3, 4}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: TUNER_PHILIPS_PAL_I, +},{ + name: "Phoebe Tv Master + FM", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xc00, + muxsel: { 2, 3, 1, 1}, + audiomux: {0, 1, 0x800, 0x400, 0xc00, 0}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Modular Technology MM205 PCTV, bt878", + video_inputs: 2, + audio_inputs: 1, + tuner: 0, + svhs: -1, + gpiomask: 7, + muxsel: { 2, 3 }, + audiomux: { 0, 0, 0, 0, 0 }, + no_msp34xx: 1, + needs_tvaudio: 1, + tuner_type: -1, +},{ + +/* ---- card 0x18 ---------------------------------- */ + name: "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xe00, + muxsel: { 2, 3, 1, 1}, + audiomux: {0x400, 0x400, 0x400, 0x400, 0}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "Terratec/Vobis TV-Boostar", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 16777215, + muxsel: { 2, 3, 1, 1}, + audiomux: { 131072, 1, 1638400, 3,4}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Newer Hauppauge WinCam (bt878)", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 3, + gpiomask: 7, + muxsel: { 2, 0, 1, 1}, + audiomux: { 0, 1, 2, 3, 4}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "MAXI TV Video PCI2", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xffff, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 1, 2, 3, 0xc00}, + needs_tvaudio: 1, + tuner_type: TUNER_PHILIPS_SECAM, +},{ + +/* ---- card 0x1c ---------------------------------- */ + name: "Terratec TerraTV+", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x70000, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000}, + needs_tvaudio: 1, + tuner_type: -1, + audio_hook: terratv_audio, +},{ + name: "Imagenation PXC200", + video_inputs: 5, + audio_inputs: 1, + tuner: -1, + svhs: 4, + gpiomask: 0, + muxsel: { 2, 3, 1, 0, 0}, + audiomux: { 0 }, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "FlyVideo 98", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x8dfe00, + muxsel: {2, 3, 1, 1}, + audiomux: { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 }, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "iProTV", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 1, + muxsel: { 2, 3, 1, 1}, + audiomux: { 1, 0, 0, 0, 0 }, + tuner_type: -1, +},{ + +/* ---- card 0x20 ---------------------------------- */ + name: "Intel Create and Share PCI", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 3, 1, 1}, + audiomux: { 4, 4, 4, 4, 4}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Terratec TerraTValue", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xffff00, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0x500, 0, 0x300, 0x900, 0x900}, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "Leadtek WinFast 2000", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xfff000, + muxsel: { 2, 3, 1, 1,0}, + audiomux: { 0x621000,0x6ddf07,0x621100,0x620000,0xE210000,0x620000}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "Chronos Video Shuttle II", + video_inputs: 3, + audio_inputs: 3, + tuner: 0, + svhs: 2, + gpiomask: 0x1800, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 0, 0x1000, 0x1000, 0x0800}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + +/* ---- card 0x24 ---------------------------------- */ + name: "Typhoon TView TV/FM Tuner", + video_inputs: 3, + audio_inputs: 3, + tuner: 0, + svhs: 2, + gpiomask: 0x1800, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 0x800, 0, 0, 0x1800, 0 }, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "PixelView PlayTV pro", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xff, + muxsel: { 2, 3, 1, 1 }, + audiomux: { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, + no_msp34xx: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "TView99 CPH063", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x551e00, + muxsel: { 2, 3, 1, 0}, + audiomux: { 0x551400, 0x551200, 0, 0, 0, 0x551200 }, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "Pinnacle PCTV Rave", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x03000F, + muxsel: { 2, 3, 1, 1}, + audiomux: { 2, 0, 0, 0, 1}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + +/* ---- card 0x28 ---------------------------------- */ + name: "STB2", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 3, 1, 1}, + audiomux: { 4, 0, 2, 3, 1}, + no_msp34xx: 1, + needs_tvaudio: 1, + tuner_type: -1, +},{ + name: "AVerMedia TVPhone 98", + video_inputs: 3, + audio_inputs: 4, + tuner: 0, + svhs: 2, + gpiomask: 4, + muxsel: { 2, 3, 1, 1}, + audiomux: { 13, 14, 11, 7, 0, 0}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: 5, + audio_hook: avermedia_tvphone_audio, +},{ + name: "ProVideo PV951", /* pic16c54 */ + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0, 0, 0, 0, 0}, + no_msp34xx: 1, + pll: PLL_28, + tuner_type: 1, +},{ + name: "Little OnAir TV", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xe00b, + muxsel: {2, 3, 1, 1}, + audiomux: {0xff9ff6, 0xff9ff6, 0xff1ff7, 0, 0xff3ffc}, + no_msp34xx: 1, + tuner_type: -1, +},{ + +/* ---- card 0x2c ---------------------------------- */ + name: "Sigma TVII-FM", + video_inputs: 2, + audio_inputs: 1, + tuner: 0, + svhs: -1, + gpiomask: 3, + muxsel: {2, 3, 1, 1}, + audiomux: {1, 1, 0, 2, 3}, + no_msp34xx: 1, + pll: PLL_NONE, + tuner_type: -1, +},{ + name: "MATRIX-Vision MV-Delta 2", + video_inputs: 5, + audio_inputs: 1, + tuner: -1, + svhs: 3, + gpiomask: 0, + muxsel: { 2, 3, 1, 0, 0}, + audiomux: {0 }, + no_msp34xx: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "Zoltrix Genie TV", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xbcf03f, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0xbc803f, 0, 0xbcb03f, 0, 0xbcb03f}, + no_msp34xx: 1, + pll: PLL_28, + tuner_type: 5, +},{ + name: "Terratec TV/Radio+", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x1f0000, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0xe2ffff, 0xebffff, 0, 0, 0xe0ffff, 0xe2ffff }, + no_msp34xx: 1, + pll: PLL_35, + tuner_type: 1, +},{ + +/* ---- card 0x30 ---------------------------------- */ + name: "Dynalink Magic TView ", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 15, + muxsel: { 2, 3, 1, 1}, + audiomux: {2,0,0,0,1}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "GV-BCTV3", + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x010f00, + muxsel: {2, 3, 0, 0}, + audiomux: {0x10000, 0, 0x10000, 0, 0, 0}, + no_msp34xx: 1, + pll: PLL_28, + tuner_type: TUNER_ALPS_TSHC6_NTSC, + audio_hook: gvbctv3pci_audio, +},{ + name: "Prolink PV-BT878P+4E (PixelView PlayTV PAK)", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0xAA0000, + muxsel: { 2,3,1,1 }, + audiomux: { 0x20000, 0, 0x80000, 0x80000, 0xa8000, 0x46000 }, + no_msp34xx: 1, + pll: PLL_28, + tuner_type: TUNER_PHILIPS_PAL_I, +},{ + name: "Eagle Wireless Capricorn2 (bt878A)", + video_inputs: 4, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 7, + muxsel: { 2, 0, 1, 1}, + audiomux: { 0, 1, 2, 3, 4}, + pll: PLL_28, + tuner_type: -1 /* TUNER_ALPS_TMDH2_NTSC */, +},{ + +/* ---- card 0x34 ---------------------------------- */ + name: "Pinnacle Studio PCTV Pro", /* David Härdeman */ + video_inputs: 3, + audio_inputs: 1, + tuner: 0, + svhs: 2, + gpiomask: 0x03000F, + muxsel: { 2, 3, 1, 1}, + audiomux: { 1, 65537, 0, 0, 10}, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: -1, +},{ + name: "Typhoon TView RDS", /* Claas Langbehn */ + video_inputs: 3, + audio_inputs: 3, + tuner: 0, + svhs: 2, + gpiomask: 0xffff, + muxsel: { 2, 3, 1, 1}, + audiomux: { 0xb002, 0, 0x12, 0x12, 0x3007 }, + needs_tvaudio: 1, + pll: PLL_28, + tuner_type: TUNER_PHILIPS_PAL_I, +}}; + const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard)); /* ----------------------------------------------------------------------- */ static unsigned char eeprom_data[256]; -static void __devinit bttv_dump_eeprom(struct bttv *btv,int addr) -{ - int i; - - if (bttv_verbose < 2) - return; - /* for debugging: dump eeprom to syslog */ - printk(KERN_DEBUG "bttv%d: dump eeprom @ 0x%02x\n",btv->nr,addr); - for (i = 0; i < 256;) { - printk(KERN_DEBUG " %02x:",i); - do { - printk(" %02x",eeprom_data[i++]); - } while (i % 16); - printk("\n"); - } -} - -static int __devinit bttv_idcard_eeprom(struct bttv *btv) -{ - unsigned id; - int i,n; - - id = (eeprom_data[252] << 24) | - (eeprom_data[253] << 16) | - (eeprom_data[254] << 8) | - (eeprom_data[255]); - if (id == 0 || id == 0xffffffff) - return -1; - - /* look for the card */ - btv->cardid = id; - for (n = -1, i = 0; cards[i].id != 0; i++) - if (cards[i].id == id) - n = i; - - if (n != -1) { - /* found it */ - printk(KERN_INFO "bttv%d: card id: %s (0x%08x) => card=%d\n", - btv->nr,cards[n].name,id,cards[n].cardnr); - return cards[n].cardnr; - } else { - /* 404 */ - printk(KERN_INFO "bttv%d: id: unknown (0x%08x)\n", - btv->nr, id); - printk(KERN_INFO "please mail id, board name and " - "the correct card= insmod option to " - "kraxel@goldbach.in-berlin.de\n"); - return -1; - } -} - -#ifndef HAVE_TVAUDIO -/* can tda9855.c handle this too maybe? */ -static void __devinit init_tda9840(struct bttv *btv) -{ - /* Horrible Hack */ - bttv_I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1); /* sound mode switching */ - /* 00 - mute - 10 - mono / averaged stereo - 2a - stereo - 12 - dual A - 1a - dual AB - 16 - dual BA - 1e - dual B - 7a - external */ -} -#endif - +/* + * identify card + */ void __devinit bttv_idcard(struct bttv *btv) { - int type,eeprom = 0; - - btwrite(0, BT848_GPIO_OUT_EN); - - /* try to autodetect the card */ - /* many bt878 cards have a eeprom @ 0xa0 => read ID - and try to identify it */ - if (bttv_I2CRead(btv, I2C_HAUPEE, "eeprom") >= 0) { - eeprom = 0xa0; - bttv_readee(btv,eeprom_data,0xa0); - bttv_dump_eeprom(btv,0xa0); /* DEBUG */ - type = bttv_idcard_eeprom(btv); - if (-1 != type) { - btv->type = type; - } else if (btv->id <= 849) { - /* for unknown bt848, assume old Hauppauge */ - btv->type=BTTV_HAUPPAUGE; - } + unsigned int gpiobits; + int i,type; + unsigned short tmp; + + /* read PCI subsystem ID */ + pci_read_config_word(btv->dev, PCI_SUBSYSTEM_ID, &tmp); + btv->cardid = tmp << 16; + pci_read_config_word(btv->dev, PCI_SUBSYSTEM_VENDOR_ID, &tmp); + btv->cardid |= tmp; + + if (0 != btv->cardid && 0xffffffff != btv->cardid) { + /* look for the card */ + for (type = -1, i = 0; cards[i].id != 0; i++) + if (cards[i].id == btv->cardid) + type = i; - /* STB cards have a eeprom @ 0xae (old bt848) */ - } else if (bttv_I2CRead(btv, I2C_STBEE, "eeprom")>=0) { - btv->type=BTTV_STB; + if (type != -1) { + /* found it */ + printk(KERN_INFO "bttv%d: subsystem: %04x:%04x => %s => card=%d\n", + btv->nr, btv->cardid & 0xffff, btv->cardid >> 16, + cards[type].name,cards[type].cardnr); + btv->type = cards[type].cardnr; + } else { + /* 404 */ + printk(KERN_INFO "bttv%d: subsystem: %04x:%04x (UNKNOWN)\n", + btv->nr, btv->cardid&0xffff, btv->cardid>>16); + printk(KERN_DEBUG "please mail id, board name and " + "the correct card= insmod option to " + "kraxel@goldbach.in-berlin.de\n"); + } } /* let the user override the autodetected type */ @@ -387,8 +819,39 @@ printk(KERN_INFO "bttv%d: model: %s [%s]\n",btv->nr,btv->video_dev.name, (card[btv->nr] >= 0 && card[btv->nr] < bttv_num_tvcards) ? "insmod option" : "autodetected"); - - /* board specific initialisations */ + + /* overwrite gpio stuff ?? */ + if (-1 == audioall && -1 == audiomux[0]) + return; + + if (-1 != audiomux[0]) { + gpiobits = 0; + for (i = 0; i < 5; i++) { + bttv_tvcards[btv->type].audiomux[i] = audiomux[i]; + gpiobits |= audiomux[i]; + } + } else { + gpiobits = audioall; + for (i = 0; i < 5; i++) { + bttv_tvcards[btv->type].audiomux[i] = audioall; + } + } + bttv_tvcards[btv->type].gpiomask = (-1 != gpiomask) ? gpiomask : gpiobits; + printk(KERN_INFO "bttv%d: gpio config override: mask=0x%x, mux=", + btv->nr,bttv_tvcards[btv->type].gpiomask); + for (i = 0; i < 5; i++) { + printk("%s0x%x", i ? "," : "", bttv_tvcards[btv->type].audiomux[i]); + } + printk("\n"); +} + +/* + * (most) board specific initialisations goes here + */ +void __devinit bttv_init_card(struct bttv *btv) +{ + int eeprom = 0; + if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) { /* auto detect tuner for MIRO cards */ btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7; @@ -407,7 +870,6 @@ bttv_readee(btv,eeprom_data,0xa0); } hauppauge_eeprom(btv); - hauppauge_boot_msp34xx(btv); } if (btv->type == BTTV_PXC200) init_PXC200(btv); @@ -419,6 +881,10 @@ btv->pll.pll_ifreq=28636363; btv->pll.pll_crystal=BT848_IFORM_XT0; } + if (PLL_35 == bttv_tvcards[btv->type].pll) { + btv->pll.pll_ifreq=35468950; + btv->pll.pll_crystal=BT848_IFORM_XT1; + } /* insmod options can override */ switch (pll[btv->nr]) { case 0: /* none */ @@ -427,18 +893,19 @@ btv->pll.pll_ofreq = 0; break; case 1: /* 28 MHz */ + case 28: btv->pll.pll_ifreq = 28636363; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal=BT848_IFORM_XT0; + btv->pll.pll_crystal = BT848_IFORM_XT0; break; case 2: /* 35 MHz */ + case 35: btv->pll.pll_ifreq = 35468950; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal=BT848_IFORM_XT1; + btv->pll.pll_crystal = BT848_IFORM_XT1; break; } } - /* tuner configuration */ if (-1 != bttv_tvcards[btv->type].tuner_type) @@ -447,62 +914,25 @@ bttv_call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type); /* try to detect audio/fader chips */ - if (bttv_tvcards[btv->type].msp34xx && + if (!bttv_tvcards[btv->type].no_msp34xx && bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx") >=0) { if (autoload) request_module("msp3400"); } -#ifndef HAVE_TVAUDIO - if (bttv_tvcards[btv->type].tda8425 && - bttv_I2CRead(btv, I2C_TDA8425, "TDA8425") >=0) { - if (autoload) - request_module("tda8425"); - } - - if (bttv_tvcards[btv->type].tda9840 && - bttv_I2CRead(btv, I2C_TDA9840, "TDA9840") >=0) { - init_tda9840(btv); - btv->audio_chip = TDA9840; - /* move this to a module too? */ - init_tda9840(btv); - } - - if (bttv_tvcards[btv->type].tda985x && - bttv_I2CRead(btv, I2C_TDA9850, "TDA985x") >=0) { - if (autoload) - request_module("tda985x"); - } - if (bttv_tvcards[btv->type].tea63xx) { - if (autoload) - request_module("tea6300"); - } -#else - if (bttv_tvcards[btv->type].tda8425 || - bttv_tvcards[btv->type].tda9840 || - bttv_tvcards[btv->type].tda985x || - bttv_tvcards[btv->type].tea63xx) { - if (autoload) - request_module("tvaudio"); - } -#endif - - if (bttv_tvcards[btv->type].tda9875 && - bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { + if (bttv_I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) { if (autoload) request_module("tda9875"); } - if (bttv_tvcards[btv->type].tda7432 && - bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { + if (bttv_I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) { if (autoload) request_module("tda7432"); } - - if (bttv_tvcards[btv->type].tea64xx) { + if (bttv_tvcards[btv->type].needs_tvaudio) { if (autoload) - request_module("tea6420"); + request_module("tvaudio"); } if (bttv_tvcards[btv->type].tuner != -1) { @@ -574,40 +1004,25 @@ { btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id; if (bttv_verbose) - printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr, + printk("bttv%d: Hauppauge eeprom: model=%d, tuner=%s (%d)\n",btv->nr, + eeprom_data[12] << 8 | eeprom_data[11], hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type); } } -static void __devinit hauppauge_boot_msp34xx(struct bttv *btv) +void __devinit bttv_hauppauge_boot_msp34xx(struct bttv *btv) { - int i; - /* reset/enable the MSP on some Hauppauge cards */ /* Thanks to Kyösti Mälkki (kmalkki@cc.hut.fi)! */ btaor(32, ~32, BT848_GPIO_OUT_EN); btaor(0, ~32, BT848_GPIO_DATA); udelay(2500); btaor(32, ~32, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"msp34xx"); if (bttv_verbose) printk("bttv%d: Hauppauge msp34xx: reset line init\n",btv->nr); - - /* look if the msp3400 driver is already registered */ - for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] != NULL && - btv->i2c_clients[i]->driver->id == I2C_DRIVERID_MSP3400) { - return; - } - } - - /* if not: look for the chip ... */ - if (bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx")) { - /* ... if found re-register to trigger a i2c bus rescan, */ - /* this time with the msp34xx chip activated */ - i2c_bit_del_bus(&btv->i2c_adap); - i2c_bit_add_bus(&btv->i2c_adap); - } } @@ -632,6 +1047,8 @@ /* GPIO inputs are pulled up, so no need to drive * reset pin any longer */ btwrite(0,BT848_GPIO_OUT_EN); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pxc200"); /* we could/should try and reset/control the AD pots? but right now we simply turned off the crushing. Without @@ -716,6 +1133,8 @@ /* better safe than sorry */ btaor((1<mode |= VIDEO_AUDIO_VOLUME; + return; + } /* 32 levels logarithmic */ vol = 32 - ((v->volume>>11)); @@ -826,6 +1255,68 @@ udelay(10); data &= ~WINVIEW_PT2254_STROBE; btwrite(data, BT848_GPIO_DATA); +} + +/* ----------------------------------------------------------------------- */ +/* mono/stereo control for various cards (which don't use i2c chips but */ +/* connect something to the GPIO pins */ + +static void +gvbctv3pci_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int con = 0; + + if (set) { + btor(0x100, BT848_GPIO_OUT_EN); + if (v->mode & VIDEO_SOUND_LANG1) + con = 0x000; + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x300; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x200; +// if (v->mode & VIDEO_SOUND_MONO) +// con = 0x100; + btaor(con, ~0x300, BT848_GPIO_DATA); + } else { + v->mode = VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } +} + +/* + * Mario Medina Nussbaum + * I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo, + * 0xdde enables mono and 0xccd enables sap + * + * Petr Vandrovec + * P.S.: At least mask in line above is wrong - GPIO pins 3,2 select + * input/output sound connection, so both must be set for output mode. + * + */ +static void +avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set) +{ + /* TODO */ +} + +static void +terratv_audio(struct bttv *btv, struct video_audio *v, int set) +{ + unsigned int con = 0; + + if (set) { + btor(0x180000, BT848_GPIO_OUT_EN); + if (v->mode & VIDEO_SOUND_LANG2) + con = 0x080000; + if (v->mode & VIDEO_SOUND_STEREO) + con = 0x180000; + btaor(con, ~0x180000, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"terratv"); + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } } /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c --- v2.4.0-test10/linux/drivers/media/video/bttv-driver.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/media/video/bttv-driver.c Fri Nov 17 17:56:51 2000 @@ -44,34 +44,40 @@ #include #include #include -#ifdef HACKING -# include -#endif -#include "bttv.h" +#include "bttvp.h" #include "tuner.h" #define DEBUG(x) /* Debug driver */ -#define IDEBUG(x) /* Debug interrupt handler */ #define MIN(a,b) (((a)>(b))?(b):(a)) #define MAX(a,b) (((a)>(b))?(a):(b)) - static void bt848_set_risc_jmps(struct bttv *btv, int state); int bttv_num; /* number of Bt848s in use */ struct bttv bttvs[BTTV_MAX]; - /* insmod args */ MODULE_PARM(triton1,"i"); MODULE_PARM(radio,"1-4i"); +MODULE_PARM_DESC(radio,"The TV card supports radio, default is 0 (no)"); MODULE_PARM(bigendian,"i"); +MODULE_PARM_DESC(bigendian,"byte order of the framebuffer, default is native endian"); MODULE_PARM(fieldnr,"i"); +MODULE_PARM_DESC(fieldnr,"count fields, default is 0 (no)"); MODULE_PARM(bttv_verbose,"i"); +MODULE_PARM_DESC(bttv_verbose,"verbose startup messages, default is 1 (yes)"); +MODULE_PARM(bttv_gpio,"i"); +MODULE_PARM_DESC(bttv_gpio,"log gpio changes, default is 0 (no)"); MODULE_PARM(bttv_debug,"i"); +MODULE_PARM_DESC(bttv_debug,"debug messages, default is 0 (no)"); +MODULE_PARM(irq_debug,"i"); +MODULE_PARM_DESC(irq_debug,"irq handler debug messages, default is 0 (no)"); MODULE_PARM(gbuffers,"i"); +MODULE_PARM_DESC(gbuffers,"number of capture buffers, default is 2 (64 max)"); MODULE_PARM(gbufsize,"i"); +MODULE_PARM_DESC(gbufsize,"size of the capture buffers, default is 0x208000"); +MODULE_PARM(combfilter,"i"); MODULE_DESCRIPTION("bttv - v4l driver module for bt848/878 based cards"); MODULE_AUTHOR("Ralph Metzler & Marcus Metzler & Gerd Knorr"); @@ -84,10 +90,13 @@ static int triton1=0; static unsigned int radio[BTTV_MAX]; static unsigned int fieldnr = 0; +static unsigned int irq_debug = 0; static unsigned int gbuffers = 2; static unsigned int gbufsize = BTTV_MAX_FBUF; +static unsigned int combfilter = 0; unsigned int bttv_debug = 0; unsigned int bttv_verbose = 1; +unsigned int bttv_gpio = 0; #define I2C_TIMING (0x7<<4) #define I2C_DELAY 10 @@ -133,8 +142,9 @@ ptep = pte_offset(pmd, adr); pte = *ptep; if(pte_present(pte)) { - ret = (unsigned long) page_address(pte_page(pte)); - ret |= (adr & (PAGE_SIZE - 1)); + ret = (unsigned long) page_address(pte_page(pte)); + ret |= (adr & (PAGE_SIZE - 1)); + } } } @@ -239,9 +249,9 @@ } +/* init + register i2c algo-bit adapter */ static int __devinit init_bttv_i2c(struct bttv *btv) { - /* i2c bit_adapter */ memcpy(&btv->i2c_adap, &bttv_i2c_adap_template, sizeof(struct i2c_adapter)); memcpy(&btv->i2c_algo, &bttv_i2c_algo_template, sizeof(struct i2c_algo_bit_data)); memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client)); @@ -256,13 +266,25 @@ bttv_bit_setscl(btv,1); bttv_bit_setsda(btv,1); - btv->i2c_ok = i2c_bit_add_bus(&btv->i2c_adap); - return btv->i2c_ok; + btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap); + return btv->i2c_rc; } /* ----------------------------------------------------------------------- */ +void bttv_gpio_tracking(struct bttv *btv, char *comment) +{ + unsigned int outbits, data; + outbits = btread(BT848_GPIO_OUT_EN); + data = btread(BT848_GPIO_DATA); + printk(KERN_DEBUG "bttv%d: gpio: en=%08x, out=%08x in=%08x [%s]\n", + btv->nr,outbits,data & outbits, data & ~outbits, comment); +} + +static char *audio_modes[] = { "audio: tuner", "audio: radio", "audio: extern", + "audio: intern", "audio: off" }; + static void audio(struct bttv *btv, int mode, int no_irq_context) { btaor(bttv_tvcards[btv->type].gpiomask, ~bttv_tvcards[btv->type].gpiomask, @@ -295,6 +317,8 @@ mode = AUDIO_RADIO; btaor(bttv_tvcards[btv->type].audiomux[mode], ~bttv_tvcards[btv->type].gpiomask, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,audio_modes[mode]); if (no_irq_context) bttv_call_i2c_clients(btv,AUDC_SET_INPUT,&(mode)); } @@ -406,14 +430,16 @@ static void bt848_muxsel(struct bttv *btv, unsigned int input) { + +#if 0 /* seems no card uses this ... */ btaor(bttv_tvcards[btv->type].gpiomask2,~bttv_tvcards[btv->type].gpiomask2, BT848_GPIO_OUT_EN); +#endif /* This seems to get rid of some synchronization problems */ btand(~(3<<5), BT848_IFORM); mdelay(10); - input %= bttv_tvcards[btv->type].video_inputs; if (input==bttv_tvcards[btv->type].svhs) { @@ -428,8 +454,13 @@ btaor((bttv_tvcards[btv->type].muxsel[input&7]&3)<<5, ~(3<<5), BT848_IFORM); audio(btv, (input!=bttv_tvcards[btv->type].tuner) ? AUDIO_EXTERN : AUDIO_TUNER, 1); + +#if 0 /* seems no card uses this ... */ btaor(bttv_tvcards[btv->type].muxsel[input]>>4, ~bttv_tvcards[btv->type].gpiomask2, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"muxsel"); +#endif } @@ -942,9 +973,9 @@ lastbit=cbit; sx += dx; dx = 1; - if (ro - btv->risc_scr_odd>RISCMEM_LEN/2 - 16) + if (ro - btv->risc_scr_odd>(RISCMEM_LEN>>3) - 16) outofmem++; - if (re - btv->risc_scr_even>RISCMEM_LEN/2 - 16) + if (re - btv->risc_scr_even>(RISCMEM_LEN>>3) - 16) outofmem++; } x++; @@ -997,17 +1028,17 @@ ((tvn->sheight>>4)&0x30)|((tvn->vdelay>>2)&0xc0); vscale |= inter ? (BT848_VSCALE_INT<<8) : 0; -#if 0 - /* Some people say interpolation looks bad ... */ - vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); - if (width < 767) - btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - else + if (combfilter) { + /* Some people say interpolation looks bad ... */ + vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + if (width < 769) + btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); + else + btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); + } else { + vtc = 0; btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); -#else - vtc = 0; - btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); -#endif + } btwrite(vtc, BT848_E_VTC+off); btwrite(hscale>>8, BT848_E_HSCALE_HI+off); @@ -1133,131 +1164,6 @@ bt848_set_geo(btv,1); } -#ifdef HACKING -/* playing with kiobufs and dma-to-userspace. 2.4.x only - Yes, I know: cut+paste programming is ugly. - will fix later, this is proof-of-concept right now. */ -static int make_vrisctab_kiobuf(struct bttv *btv, unsigned int *ro, - unsigned int *re, struct kiobuf *iobuf, - unsigned short width, unsigned short height, - unsigned short palette) -{ - unsigned long bpl; /* bytes per line */ - unsigned long bl; - unsigned long todo; - unsigned long pageaddr; - unsigned int **rp; - unsigned long line,inter,offset,page; - - inter = (height>tvnorms[btv->win.norm].sheight/2) ? 1 : 0; - bpl=width*fmtbppx2[palette2fmt[palette]&0xf]/2; - - *(ro++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(ro++)=cpu_to_le32(0); - *(re++)=cpu_to_le32(BT848_RISC_SYNC|BT848_FIFO_STATUS_FM1); - *(re++)=cpu_to_le32(0); - - offset = iobuf->offset; - page = 0; - pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); - for (line=0; line < (height<<(1^inter)); line++) - { - if (inter) - rp= (line&1) ? &re : &ro; - else - rp= (line>=height) ? &ro : &re; - - bl = PAGE_SIZE - offset; - if (bpl <= bl) { - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| - BT848_RISC_EOL|bpl); - *((*rp)++)=cpu_to_le32(pageaddr+offset); - offset+=bpl; - } else { - todo = bpl; - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL|bl); - *((*rp)++)=cpu_to_le32(pageaddr+offset); - todo -= bl; - offset = 0; - page++; - pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); - while (todo>PAGE_SIZE) - { - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|PAGE_SIZE); - *((*rp)++)=cpu_to_le32(pageaddr); - page++; - pageaddr = virt_to_bus(page_address(iobuf->maplist[page])); - } - *((*rp)++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|todo); - *((*rp)++)=cpu_to_le32(pageaddr); - offset += todo; - } - } - - *(ro++)=cpu_to_le32(BT848_RISC_JUMP); - *(ro++)=cpu_to_le32(btv->bus_vbi_even); - *(re++)=cpu_to_le32(BT848_RISC_JUMP|BT848_RISC_IRQ|(2<<16)); - *(re++)=cpu_to_le32(btv->bus_vbi_odd); - - return 0; -} - -static int vgrab_kiobuf(struct bttv *btv, struct bttv_just_hacking *mp, - struct kiobuf *iobuf) -{ - unsigned int *ro, *re; - unsigned long flags; - - if(btv->gbuf[0].stat != GBUFFER_UNUSED) - return -EBUSY; - - if(mp->height < 32 || mp->width < 32) - return -EINVAL; - if (mp->format >= 12 /* more is'nt yet ... PALETTEFMT_MAX */) - return -EINVAL; - - if(-1 == palette2fmt[mp->format]) - return -EINVAL; - - /* - * Ok load up the BT848 - */ - - ro=btv->gbuf[0].risc; - re=ro+2048; - make_vrisctab_kiobuf(btv, ro, re, iobuf, mp->width, mp->height, mp->format); - - if (bttv_debug) - printk("bttv%d: cap vgrab_kiobuf: queue %d (%d:%dx%d)\n", - btv->nr,0,mp->format,mp->width,mp->height); - spin_lock_irqsave(&btv->s_lock, flags); - btv->gbuf[0].stat = GBUFFER_GRABBING; - btv->gbuf[0].fmt = palette2fmt[mp->format]; - btv->gbuf[0].width = mp->width; - btv->gbuf[0].height = mp->height; - btv->gbuf[0].ro = virt_to_bus(ro); - btv->gbuf[0].re = virt_to_bus(re); - -#if 1 - if (mp->height <= tvnorms[btv->win.norm].sheight/2 && - mp->format != VIDEO_PALETTE_RAW) - btv->gbuf[0].ro = 0; -#endif - - if (-1 == btv->gq_grab && btv->gq_in == btv->gq_out) { - btv->gq_start = 1; - btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ); - } - btv->gqueue[btv->gq_in++] = 0; - btv->gq_in = btv->gq_in % MAX_GBUFFERS; - - btor(3, BT848_CAP_CTL); - btor(3, BT848_GPIO_DMA_CTL); - spin_unlock_irqrestore(&btv->s_lock, flags); - return 0; -} -#endif - /* * Grab into virtual memory. */ @@ -1393,6 +1299,39 @@ tvnorms[2].hdelayx1 = 186 - (on?BURSTOFFSET :0); } +/* + * called from irq handler on fatal errors. Takes the grabber chip + * offline, flag it needs a reinitialization (which can't be done + * from irq context) and wake up all sleeping proccesses. They would + * block forever else. We also need someone who actually does the + * reinitialization from process context... + */ +static void bt848_offline(struct bttv *btv) +{ + int i; + spin_lock(&btv->s_lock); + + /* cancel all outstanding grab requests */ + btv->gq_in = 0; + btv->gq_out = 0; + btv->gq_grab = -1; + for (i = 0; i < gbuffers; i++) + if (btv->gbuf[i].stat == GBUFFER_GRABBING) + btv->gbuf[i].stat = GBUFFER_ERROR; + + /* disable screen overlay and DMA */ + btv->risc_cap_odd = 0; + btv->risc_cap_even = 0; + bt848_set_risc_jmps(btv,0); + + /* flag the chip needs a restart */ + btv->needs_restart = 1; + spin_unlock(&btv->s_lock); + + wake_up_interruptible(&btv->vbiq); + wake_up_interruptible(&btv->capq); +} + static void bt848_restart(struct bttv *btv) { unsigned long irq_flags; @@ -1427,6 +1366,8 @@ int i,ret; ret = -EBUSY; + if (bttv_debug) + printk("bttv%d: open called\n",btv->nr); MOD_INC_USE_COUNT; down(&btv->lock); @@ -1724,6 +1665,7 @@ btv->scr_on = 0; bt848_set_risc_jmps(btv,-1); spin_unlock_irqrestore(&btv->s_lock, irq_flags); + up(&btv->lock); return -EINVAL; } if (btv->win.bpp < 4) @@ -1747,20 +1689,26 @@ * Do any clips. */ if(vw.clipcount<0) { - if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) + if((vcp=vmalloc(VIDEO_CLIPMAP_SIZE))==NULL) { + up(&btv->lock); return -ENOMEM; + } if(copy_from_user(vcp, vw.clips, VIDEO_CLIPMAP_SIZE)) { + up(&btv->lock); vfree(vcp); return -EFAULT; } } else if (vw.clipcount) { if((vcp=vmalloc(sizeof(struct video_clip)* - (vw.clipcount))) == NULL) + (vw.clipcount))) == NULL) { + up(&btv->lock); return -ENOMEM; + } if(copy_from_user(vcp,vw.clips, sizeof(struct video_clip)* vw.clipcount)) { + up(&btv->lock); vfree(vcp); return -EFAULT; } @@ -1898,21 +1846,9 @@ v.mode = VIDEO_SOUND_MONO; bttv_call_i2c_clients(btv,cmd,&v); - if (btv->type == BTTV_TERRATV) { - v.mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } -#ifndef HAVE_TVAUDIO - else if (btv->audio_chip == TDA9840) { - /* begin of Horrible Hack */ - v.flags|=VIDEO_AUDIO_VOLUME; - v.mode = VIDEO_SOUND_MONO; - v.mode |= VIDEO_SOUND_STEREO; - v.mode |= VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2; - v.volume = 32768; /* fixme */ - v.step = 4096; - } -#endif + /* card specific hooks */ + if (bttv_tvcards[btv->type].audio_hook) + bttv_tvcards[btv->type].audio_hook(btv,&v,0); if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; @@ -1938,17 +1874,9 @@ bttv_call_i2c_clients(btv,cmd,&v); - if (btv->type == BTTV_TERRATV) { - unsigned int con = 0; - btor(0x180000, BT848_GPIO_OUT_EN); - if (v.mode & VIDEO_SOUND_LANG2) - con = 0x080000; - if (v.mode & VIDEO_SOUND_STEREO) - con = 0x180000; - btaor(con, ~0x180000, BT848_GPIO_DATA); - - } else if (btv->type == BTTV_WINVIEW_601) - winview_setvol(btv,&v); + /* card specific hooks */ + if (bttv_tvcards[btv->type].audio_hook) + bttv_tvcards[btv->type].audio_hook(btv,&v,0); btv->audio_dev=v; up(&btv->lock); @@ -2082,90 +2010,12 @@ return 0; } -#ifdef HACKING - /* playing with kiobufs and dma-to-userspace */ - case BTTV_JUST_HACKING: - { - DECLARE_WAITQUEUE(wait, current); - struct bttv_just_hacking hack; - struct kiobuf *iobuf; - int err; - - if(copy_from_user((void *) &hack, (void *) arg, sizeof(hack))) - return -EFAULT; - printk("bttv%d: hack: userland args: %dx%d, fmt=%d, buf=%lx, len=%d\n", - btv->nr,hack.width,hack.height,hack.format, - hack.buf,hack.len); - - /* pin down */ - err = alloc_kiovec(1,&iobuf); - if (err) - goto hack_oops; - err = map_user_kiobuf(READ, iobuf, hack.buf, hack.len); - if (err) - goto hack_oops; - err = lock_kiovec(1,&iobuf,1); - if (err) - goto hack_oops; - - /* have a look */ - printk("bttv%d: hack: kiobuf: nr_pages=%d, offset=%d, length=%d, locked=%d\n", - btv->nr,iobuf->nr_pages,iobuf->offset,iobuf->length, - iobuf->locked); - printk("bttv%d: hack: pages (bus addr):",btv->nr); - for (i = 0; i < iobuf->nr_pages; i++) { - printk(" %lx", virt_to_bus(page_address(iobuf->maplist[i]))); - } - printk("\n"); - - /* start capture */ - err = -EINVAL; - if (hack.height * hack.width * 2 * /* fixme: *2 */ - fmtbppx2[palette2fmt[hack.format]&0x0f]/2 > hack.len) - goto hack_oops; - err = vgrab_kiobuf(btv,&hack,iobuf); - if (err) - goto hack_oops; - printk("bttv%d: hack: capture started\n",btv->nr); - - /* wait */ - add_wait_queue(&btv->capq, &wait); - current->state = TASK_INTERRUPTIBLE; - while(btv->gbuf[0].stat==GBUFFER_GRABBING) { - if (bttv_debug) - printk("bttv%d: hack: cap sync: sleep on %d\n",btv->nr,0); - schedule(); -#if 0 - if(signal_pending(current)) { - remove_wait_queue(&btv->capq, &wait); - current->state = TASK_RUNNING; - return -EINTR; - } -#endif - } - remove_wait_queue(&btv->capq, &wait); - current->state = TASK_RUNNING; - printk("bttv%d: hack: capture done\n",btv->nr); - - /* release */ - err = 0; - hack_oops: - free_kiovec(1,&iobuf); - return 0; - } -#endif - default: return -ENOIOCTLCMD; } return 0; } -static int bttv_init_done(struct video_device *dev) -{ - return 0; -} - /* * This maps the vmalloced and reserved fbuffer to user space. * @@ -2212,20 +2062,16 @@ static struct video_device bttv_template= { - "UNSET", - VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY|VID_TYPE_TELETEXT, - VID_HARDWARE_BT848, - bttv_open, - bttv_close, - bttv_read, - bttv_write, - NULL, - bttv_ioctl, - bttv_mmap, - bttv_init_done, - NULL, - 0, - -1 + name: "UNSET", + type: VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY|VID_TYPE_TELETEXT, + hardware: VID_HARDWARE_BT848, + open: bttv_open, + close: bttv_close, + read: bttv_read, + write: bttv_write, + ioctl: bttv_ioctl, + mmap: bttv_mmap, + minor: -1, }; @@ -2353,7 +2199,8 @@ } case VIDIOCGFREQ: case VIDIOCSFREQ: - return bttv_ioctl((struct video_device *)btv,cmd,arg); + case BTTV_VERSION: + return bttv_ioctl(dev,cmd,arg); case BTTV_VBISIZE: /* make alevt happy :-) */ return VBIBUF_SIZE; @@ -2364,20 +2211,16 @@ static struct video_device vbi_template= { - "bttv vbi", - VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, - VID_HARDWARE_BT848, - vbi_open, - vbi_close, - vbi_read, - bttv_write, - vbi_poll, - vbi_ioctl, - NULL, /* no mmap yet */ - bttv_init_done, - NULL, - 0, - -1 + name: "bttv vbi", + type: VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, + hardware: VID_HARDWARE_BT848, + open: vbi_open, + close: vbi_close, + read: vbi_read, + write: bttv_write, + poll: vbi_poll, + ioctl: vbi_ioctl, + minor: -1, }; @@ -2456,6 +2299,7 @@ v.rangehigh=(int)(108*16); /* eu: 87.5MHz - 108.0MHz */ v.flags= 0; /* XXX */ v.mode = 0; /* XXX */ + bttv_call_i2c_clients(btv,cmd,&v); if(copy_to_user(arg,&v,sizeof(v))) return -EFAULT; return 0; @@ -2485,20 +2329,15 @@ static struct video_device radio_template= { - "bttv radio", - VID_TYPE_TUNER, - VID_HARDWARE_BT848, - radio_open, - radio_close, - radio_read, /* just returns -EINVAL */ - bttv_write, /* just returns -EINVAL */ - NULL, /* no poll */ - radio_ioctl, - NULL, /* no mmap */ - bttv_init_done, /* just returns 0 */ - NULL, - 0, - -1 + name: "bttv radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_BT848, + open: radio_open, + close: radio_close, + read: radio_read, /* just returns -EINVAL */ + write: bttv_write, /* just returns -EINVAL */ + ioctl: radio_ioctl, + minor: -1, }; @@ -2579,7 +2418,8 @@ printk(" e%d=%08x",btv->gq_grab,btv->risc_cap_odd); flags |= 3; btv->risc_jmp[5]=cpu_to_le32(btv->risc_cap_odd); - } else if (flags&2) { + } else if ((flags&2) && + (!btv->win.interlace || 0 == btv->risc_cap_even)) { if (bttv_debug > 1) printk(" eo=%08lx",virt_to_bus(btv->risc_scr_odd)); btv->risc_jmp[5]=cpu_to_le32(virt_to_bus(btv->risc_scr_odd)); @@ -2614,7 +2454,8 @@ printk(" o%d=%08x",btv->gq_grab,btv->risc_cap_even); flags |= 3; btv->risc_jmp[11]=cpu_to_le32(btv->risc_cap_even); - } else if (flags&1) { + } else if ((flags&1) && + btv->win.interlace) { if (bttv_debug > 1) printk(" oo=%08lx",virt_to_bus(btv->risc_scr_even)); btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_scr_even)); @@ -2648,7 +2489,6 @@ memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template)); memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template)); - bttv_idcard(btv); audio(btv, AUDIO_MUTE, 1); if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0) @@ -2680,12 +2520,8 @@ /* dump current state of the gpio registers before changing them, * might help to make a new card work */ - if (bttv_verbose >= 2) - printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n", - btv->nr, - btread(BT848_GPIO_OUT_EN), - btread(BT848_GPIO_DATA), - btread(BT848_GPIO_REG_INP)); + if (bttv_gpio) + bttv_gpio_tracking(btv,"init #1"); /* reset the bt848 */ btwrite(0, BT848_SRESET); @@ -2724,10 +2560,6 @@ btv->errors=0; btv->needs_restart=0; - /* i2c */ - btv->tuner_type=-1; - init_bttv_i2c(btv); - if (!(btv->risc_scr_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) return -1; if (!(btv->risc_scr_even=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL))) @@ -2772,6 +2604,9 @@ /* select direct input */ btwrite(0x00, BT848_GPIO_REG_INP); + btwrite(0x00, BT848_GPIO_OUT_EN); + if (bttv_gpio) + bttv_gpio_tracking(btv,"init #2"); btwrite(BT848_IFORM_MUX1 | BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); @@ -2814,6 +2649,17 @@ bt848_set_risc_jmps(btv,-1); spin_unlock_irqrestore(&btv->s_lock, irq_flags); + /* needs to be done before i2c is registered */ + if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) + bttv_hauppauge_boot_msp34xx(btv); + + /* register i2c */ + btv->tuner_type=-1; + init_bttv_i2c(btv); + + /* some card-specific stuff (needs working i2c) */ + bttv_init_card(btv); + /* * Now add the template and register the device unit. */ @@ -2822,11 +2668,18 @@ return 0; } +/* ----------------------------------------------------------------------- */ + +static char *irq_name[] = { "FMTCHG", "VSYNC", "HSYNC", "OFLOW", "HLOCK", + "VPRES", "6", "7", "I2CDONE", "GPINT", "10", + "RISCI", "FBUS", "FTRGT", "FDSR", "PPERR", + "RIPERR", "PABORT", "OCERR", "SCERR" }; + static void bttv_irq(int irq, void *dev_id, struct pt_regs * regs) { u32 stat,astat; u32 dstat; - int count,i; + int count; struct bttv *btv; btv=(struct bttv *)dev_id; @@ -2838,33 +2691,39 @@ astat=stat&btread(BT848_INT_MASK); if (!astat) return; - btwrite(astat,BT848_INT_STAT); - IDEBUG(printk ("bttv%d: astat=%08x\n", btv->nr, astat)); - IDEBUG(printk ("bttv%d: stat=%08x\n", btv->nr, stat)); + btwrite(stat,BT848_INT_STAT); /* get device status bits */ dstat=btread(BT848_DSTATUS); - - if (astat&BT848_INT_GPINT) { - IDEBUG(printk ("bttv%d: IRQ_GPINT\n", btv->nr)); - wake_up_interruptible(&btv->gpioq); - } - if (astat&BT848_INT_FMTCHG) - { - IDEBUG(printk ("bttv%d: IRQ_FMTCHG\n", btv->nr)); - /*btv->win.norm&= - (dstat&BT848_DSTATUS_NUML) ? (~1) : (~0); */ - } - if (astat&BT848_INT_VPRES) - { - IDEBUG(printk ("bttv%d: IRQ_VPRES\n", btv->nr)); + if (irq_debug) { + int i; + printk(KERN_DEBUG "bttv%d: irq loop=%d risc=%x, bits:", + btv->nr, count, stat>>28); + for (i = 0; i < (sizeof(irq_name)/sizeof(char*)); i++) { + if (stat & (1 << i)) + printk(" %s",irq_name[i]); + if (astat & (1 << i)) + printk("*"); + } + if (stat & BT848_INT_HLOCK) + printk(" HLOC => %s", (dstat & BT848_DSTATUS_HLOC) + ? "yes" : "no"); + if (stat & BT848_INT_VPRES) + printk(" PRES => %s", (dstat & BT848_DSTATUS_PRES) + ? "yes" : "no"); + if (stat & BT848_INT_FMTCHG) + printk(" NUML => %s", (dstat & BT848_DSTATUS_PRES) + ? "625" : "525"); + printk("\n"); } + + if (astat&BT848_INT_GPINT) + wake_up_interruptible(&btv->gpioq); + if (astat&BT848_INT_VSYNC) - { - IDEBUG(printk ("bttv%d: IRQ_VSYNC\n", btv->nr)); btv->field++; - } + if (astat&(BT848_INT_SCERR|BT848_INT_OCERR)) { if (bttv_verbose) printk("bttv%d: irq:%s%s risc_count=%08x\n", @@ -2884,23 +2743,7 @@ } else { if (bttv_verbose) printk("bttv%d: aiee: error loops\n",btv->nr); - /* cancel all outstanding grab requests */ - spin_lock(&btv->s_lock); - btv->gq_in = 0; - btv->gq_out = 0; - btv->gq_grab = -1; - for (i = 0; i < gbuffers; i++) - if (btv->gbuf[i].stat == GBUFFER_GRABBING) - btv->gbuf[i].stat = GBUFFER_ERROR; - /* disable DMA */ - btv->risc_cap_odd = 0; - btv->risc_cap_even = 0; - bt848_set_risc_jmps(btv,0); - btv->needs_restart = 1; - spin_unlock(&btv->s_lock); - - wake_up_interruptible(&btv->vbiq); - wake_up_interruptible(&btv->capq); + bt848_offline(btv); } } if (astat&BT848_INT_RISCI) @@ -2968,55 +2811,20 @@ spin_unlock(&btv->s_lock); } } - if (astat&BT848_INT_OCERR) - { - IDEBUG(printk ("bttv%d: IRQ_OCERR\n", btv->nr)); - } - if (astat&BT848_INT_PABORT) - { - IDEBUG(printk ("bttv%d: IRQ_PABORT\n", btv->nr)); - } - if (astat&BT848_INT_RIPERR) - { - IDEBUG(printk ("bttv%d: IRQ_RIPERR\n", btv->nr)); - } - if (astat&BT848_INT_PPERR) - { - IDEBUG(printk ("bttv%d: IRQ_PPERR\n", btv->nr)); - } - if (astat&BT848_INT_FDSR) - { - IDEBUG(printk ("bttv%d: IRQ_FDSR\n", btv->nr)); - } - if (astat&BT848_INT_FTRGT) - { - IDEBUG(printk ("bttv%d: IRQ_FTRGT\n", btv->nr)); - } - if (astat&BT848_INT_FBUS) - { - IDEBUG(printk ("bttv%d: IRQ_FBUS\n", btv->nr)); - } - if (astat&BT848_INT_HLOCK) - { + + if (astat&BT848_INT_HLOCK) { if ((dstat&BT848_DSTATUS_HLOC) || (btv->radio)) audio(btv, AUDIO_ON,0); else audio(btv, AUDIO_OFF,0); } - if (astat&BT848_INT_I2CDONE) - { - IDEBUG(printk ("bttv%d: IRQ_I2CDONE\n", btv->nr)); - } count++; - if (count > 10) - printk (KERN_WARNING "bttv%d: irq loop %d\n", - btv->nr,count); - if (count > 20) - { + if (count > 20) { btwrite(0, BT848_INT_MASK); printk(KERN_ERR "bttv%d: IRQ lockup, cleared int mask\n", btv->nr); + bt848_offline(btv); } } } @@ -3033,8 +2841,11 @@ int j; struct bttv *btv = pci_get_drvdata(pci_dev); + if (bttv_verbose) + printk("bttv%d: unloading\n",btv->nr); + /* unregister i2c_bus */ - if (0 == btv->i2c_ok) + if (0 == btv->i2c_rc) i2c_bit_del_bus(&btv->i2c_adap); /* turn off all capturing, DMA and IRQs */ @@ -3044,6 +2855,8 @@ btwrite(0, BT848_INT_MASK); btwrite(~0x0UL,BT848_INT_STAT); btwrite(0x0, BT848_GPIO_OUT_EN); + if (bttv_gpio) + bttv_gpio_tracking(btv,"cleanup"); /* disable PCI bus-mastering */ pci_read_config_byte(btv->dev, PCI_COMMAND, &command); @@ -3084,7 +2897,7 @@ if (radio[btv->nr] && btv->radio_dev.minor != -1) video_unregister_device(&btv->radio_dev); - release_mem_region(btv->bt848_adr, + release_mem_region(pci_resource_start(btv->dev,0), pci_resource_len(btv->dev,0)); /* wake up any waiting processes because shutdown flag is set, no new processes (in this queue) @@ -3094,7 +2907,6 @@ wake_up(&btv->gpioq); pci_set_drvdata(pci_dev, NULL); - return; } @@ -3102,7 +2914,7 @@ static int __devinit bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { int result; - unsigned char command; + unsigned char command,lat; struct bttv *btv; #if defined(__powerpc__) unsigned int cmd; @@ -3141,11 +2953,14 @@ btv->i2c_command=(I2C_TIMING | BT848_I2C_SCL | BT848_I2C_SDA); pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); - printk(KERN_INFO "bttv%d: Brooktree Bt%d (rev %d) ", - bttv_num,btv->id, btv->revision); - printk("bus: %d, devfn: %d, ",dev->bus->number, dev->devfn); - printk("irq: %d, ",btv->irq); - printk("memory: 0x%lx.\n", btv->bt848_adr); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %02x:%02x.%x, ", + bttv_num,btv->id, btv->revision, dev->bus->number, + PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn)); + printk("irq: %d, latency: %d, memory: 0x%lx\n", + btv->irq, lat, btv->bt848_adr); + + bttv_idcard(btv); #if defined(__powerpc__) /* on OpenFirmware machines (PowerMac at least), PCI memory cycle */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/bttv-if.c linux/drivers/media/video/bttv-if.c --- v2.4.0-test10/linux/drivers/media/video/bttv-if.c Tue Jul 18 22:35:33 2000 +++ linux/drivers/media/video/bttv-if.c Sun Nov 12 20:47:19 2000 @@ -3,7 +3,6 @@ all the i2c code is here also the gpio interface exported by bttv (used by lirc) - bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) @@ -34,7 +33,7 @@ #include -#include "bttv.h" +#include "bttvp.h" #include "tuner.h" @@ -79,6 +78,8 @@ btv = &bttvs[card]; btaor(data, ~mask, BT848_GPIO_OUT_EN); + if (bttv_gpio) + bttv_gpio_tracking(btv,"extern enable"); return 0; } @@ -115,6 +116,8 @@ /* prior setting BT848_GPIO_REG_INP is (probably) not needed because direct input is set on init */ btaor(data & mask, ~mask, BT848_GPIO_DATA); + if (bttv_gpio) + bttv_gpio_tracking(btv,"extern write"); return 0; } @@ -195,8 +198,7 @@ int i; for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (btv->i2c_clients[i] == NULL || - btv->i2c_clients[i]->driver->id == client->driver->id) { + if (btv->i2c_clients[i] == NULL) { btv->i2c_clients[i] = client; break; } @@ -216,8 +218,7 @@ if (bttv_verbose) printk("bttv%d: i2c detach [%s]\n",btv->nr,client->name); for (i = 0; i < I2C_CLIENTS_MAX; i++) { - if (NULL != btv->i2c_clients[i] && - btv->i2c_clients[i]->driver->id == client->driver->id) { + if (btv->i2c_clients[i] == client) { btv->i2c_clients[i] = NULL; break; } @@ -240,33 +241,27 @@ } struct i2c_algo_bit_data bttv_i2c_algo_template = { - NULL, - bttv_bit_setsda, - bttv_bit_setscl, - bttv_bit_getsda, - bttv_bit_getscl, - 10, 10, 100, + setsda: bttv_bit_setsda, + setscl: bttv_bit_setscl, + getsda: bttv_bit_getsda, + getscl: bttv_bit_getscl, + udelay: 40, + mdelay: 10, + timeout: 200, }; struct i2c_adapter bttv_i2c_adap_template = { - "bt848", - I2C_HW_B_BT848, - NULL, - NULL, - bttv_inc_use, - bttv_dec_use, - attach_inform, - detach_inform, - NULL, + name: "bt848", + id: I2C_HW_B_BT848, + inc_use: bttv_inc_use, + dec_use: bttv_dec_use, + client_register: attach_inform, + client_unregister: detach_inform, }; struct i2c_client bttv_i2c_client_template = { - "bttv internal", - -1, - 0, - 0, - NULL, - NULL + name: "bttv internal use only", + id: -1, }; @@ -275,7 +270,7 @@ { unsigned char buffer = 0; - if (0 != btv->i2c_ok) + if (0 != btv->i2c_rc) return -1; if (bttv_verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", @@ -302,7 +297,7 @@ unsigned char buffer[2]; int bytes = both ? 2 : 1; - if (0 != btv->i2c_ok) + if (0 != btv->i2c_rc) return -1; btv->i2c_client.addr = addr >> 1; buffer[0] = b1; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/bttv.h linux/drivers/media/video/bttv.h --- v2.4.0-test10/linux/drivers/media/video/bttv.h Sun Oct 8 10:50:18 2000 +++ linux/drivers/media/video/bttv.h Sun Nov 12 20:47:19 2000 @@ -1,42 +1,19 @@ /* - bttv - Bt848 frame grabber driver - - Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) - - 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. -*/ + * bttv - Bt848 frame grabber driver + * + * card ID's and external interfaces of the bttv driver + * basically stuff needed by other drivers (i2c, lirc, ...) + * and is supported not to change much over time. + * + * Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + * (c) 1999,2000 Gerd Knorr + * + */ #ifndef _BTTV_H_ #define _BTTV_H_ -#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,38) - -#include -#include #include -#include -#include - -#include "audiochip.h" -#include "bt848.h" - -#ifdef __KERNEL__ - -/* fwd decl */ -struct bttv; - /* ---------------------------------------------------------- */ /* exported by bttv-cards.c */ @@ -90,6 +67,35 @@ #define BTTV_ZOLTRIX_GENIE 0x2e #define BTTV_TERRATVRADIO 0x2f #define BTTV_DYNALINK 0x30 +#define BTTV_GVBCTV3PCI 0x31 +#define BTTV_PXELVWPLTVPAK 0x32 +#define BTTV_EAGLE 0x33 +#define BTTV_PINNACLESTUDIO 0x34 + +/* i2c address list */ +#define I2C_TSA5522 0xc2 +#define I2C_TDA7432 0x8a +#define I2C_TDA8425 0x82 +#define I2C_TDA9840 0x84 +#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ +#define I2C_TDA9875 0xb0 +#define I2C_HAUPEE 0xa0 +#define I2C_STBEE 0xae +#define I2C_VHX 0xc0 +#define I2C_MSP3400 0x80 +#define I2C_TEA6300 0x80 +#define I2C_DPL3518 0x84 + +/* more card-specific defines */ +#define PT2254_L_CHANEL 0x10 +#define PT2254_R_CHANEL 0x08 +#define PT2254_DBS_IN_2 0x400 +#define PT2254_DBS_IN_10 0x20000 +#define WINVIEW_PT2254_CLK 0x40 +#define WINVIEW_PT2254_DATA 0x20 +#define WINVIEW_PT2254_STROBE 0x80 + +struct bttv; struct tvcard { @@ -103,15 +109,9 @@ u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ u32 gpiomask2; /* GPIO MUX mask */ - /* look for these i2c audio chips */ - int msp34xx:1; - int tda8425:1; - int tda9840:1; - int tda985x:1; - int tea63xx:1; - int tea64xx:1; - int tda7432:1; - int tda9875:1; + /* i2c audio flags */ + int no_msp34xx:1; + int needs_tvaudio:1; /* other settings */ int pll; @@ -120,6 +120,7 @@ #define PLL_35 2 int tuner_type; + void (*audio_hook)(struct bttv *btv, struct video_audio *v, int set); }; extern struct tvcard bttv_tvcards[]; @@ -127,10 +128,11 @@ /* identification / initialization of the card */ extern void bttv_idcard(struct bttv *btv); +extern void bttv_init_card(struct bttv *btv); /* card-specific funtions */ extern void tea5757_set_freq(struct bttv *btv, unsigned short freq); -extern void winview_setvol(struct bttv *btv, struct video_audio *v); +extern void bttv_hauppauge_boot_msp34xx(struct bttv *btv); /* ---------------------------------------------------------- */ /* exported by bttv-if.c */ @@ -176,6 +178,7 @@ extern wait_queue_head_t* bttv_get_gpio_queue(unsigned int card); /* i2c */ +#define I2C_CLIENTS_MAX 8 struct i2c_algo_bit_data bttv_i2c_algo_template; struct i2c_adapter bttv_i2c_adap_template; struct i2c_client bttv_i2c_client_template; @@ -187,234 +190,4 @@ unsigned char b2, int both); void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr); - -/* ---------------------------------------------------------- */ -/* bttv-driver.c */ - -/* insmod options */ -extern unsigned int bttv_verbose; -extern unsigned int bttv_debug; - -/* Anybody who uses more than four? */ -#define BTTV_MAX 4 -extern int bttv_num; /* number of Bt848s in use */ -extern struct bttv bttvs[BTTV_MAX]; - - -#ifndef O_NONCAP -#define O_NONCAP O_TRUNC -#endif - -#define MAX_GBUFFERS 64 -#define RISCMEM_LEN (32744*2) -#define VBI_MAXLINES 16 -#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) - -#define BTTV_MAX_FBUF 0x208000 -#define I2C_CLIENTS_MAX 8 - -struct bttv_window -{ - int x, y; - ushort width, height; - ushort bpp, bpl; - ushort swidth, sheight; - unsigned long vidadr; - ushort freq; - int norm; - int interlace; - int color_fmt; - ushort depth; -}; - -struct bttv_pll_info { - unsigned int pll_ifreq; /* PLL input frequency */ - unsigned int pll_ofreq; /* PLL output frequency */ - unsigned int pll_crystal; /* Crystal used for input */ - unsigned int pll_current; /* Currently programmed ofreq */ -}; - -struct bttv_gbuf { - int stat; -#define GBUFFER_UNUSED 0 -#define GBUFFER_GRABBING 1 -#define GBUFFER_DONE 2 -#define GBUFFER_ERROR 3 - struct timeval tv; - - u16 width; - u16 height; - u16 fmt; - - u32 *risc; - unsigned long ro; - unsigned long re; -}; - -struct bttv { - struct video_device video_dev; - struct video_device radio_dev; - struct video_device vbi_dev; - struct video_picture picture; /* Current picture params */ - struct video_audio audio_dev; /* Current audio params */ - - spinlock_t s_lock; - struct semaphore lock; - int user; - int capuser; - - /* i2c */ - struct i2c_adapter i2c_adap; - struct i2c_algo_bit_data i2c_algo; - struct i2c_client i2c_client; - int i2c_state, i2c_ok; - struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; - - int tuner_type; - int channel; - - unsigned int nr; - unsigned short id; - struct pci_dev *dev; - unsigned int irq; /* IRQ used by Bt848 card */ - unsigned char revision; - unsigned long bt848_adr; /* bus address of IO mem returned by PCI BIOS */ - unsigned char *bt848_mem; /* pointer to mapped IO memory */ - unsigned long busriscmem; - u32 *riscmem; - - unsigned char *vbibuf; - struct bttv_window win; - int fb_color_ctl; - int type; /* card type */ - int cardid; - int audio; /* audio mode */ - int audio_chip; /* set to one of the chips supported by bttv.c */ - int radio; - - u32 *risc_jmp; - u32 *vbi_odd; - u32 *vbi_even; - u32 bus_vbi_even; - u32 bus_vbi_odd; - wait_queue_head_t vbiq; - wait_queue_head_t capq; - int vbip; - - u32 *risc_scr_odd; - u32 *risc_scr_even; - u32 risc_cap_odd; - u32 risc_cap_even; - int scr_on; - int vbi_on; - struct video_clip *cliprecs; - - struct bttv_gbuf *gbuf; - int gqueue[MAX_GBUFFERS]; - int gq_in,gq_out,gq_grab,gq_start; - char *fbuffer; - - struct bttv_pll_info pll; - unsigned int Fsc; - unsigned int field; - unsigned int last_field; /* number of last grabbed field */ - int i2c_command; - int triton1; - - int errors; - int needs_restart; - - wait_queue_head_t gpioq; - int shutdown; -}; -#endif - -#if defined(__powerpc__) /* big-endian */ -extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) -{ - __asm__ __volatile__ ("stwbrx %1,0,%2" : \ - "=m" (*addr) : "r" (val), "r" (addr)); - __asm__ __volatile__ ("eieio" : : : "memory"); -} - -#define btwrite(dat,adr) io_st_le32((unsigned *)(btv->bt848_mem+(adr)),(dat)) -#define btread(adr) ld_le32((unsigned *)(btv->bt848_mem+(adr))) -#else -#define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mem+(adr))) -#define btread(adr) readl(btv->bt848_mem+(adr)) -#endif - -#define btand(dat,adr) btwrite((dat) & btread(adr), adr) -#define btor(dat,adr) btwrite((dat) | btread(adr), adr) -#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) - -/* bttv ioctls */ - -#define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]) -#define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]) -#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int) -#define BTTV_PLLSET _IOW('v' , BASE_VIDIOCPRIVATE+3, struct bttv_pll_info) -#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int) -#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int) -#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) -#define BTTV_PICNR _IOR('v' , BASE_VIDIOCPRIVATE+7, int) -#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) - -#define AUDIO_TUNER 0x00 -#define AUDIO_RADIO 0x01 -#define AUDIO_EXTERN 0x02 -#define AUDIO_INTERN 0x03 -#define AUDIO_OFF 0x04 -#define AUDIO_ON 0x05 -#define AUDIO_MUTE 0x80 -#define AUDIO_UNMUTE 0x81 - -#define TDA9850 0x01 -#define TDA9840 0x02 -#define TDA8425 0x03 -#define TEA6300 0x04 - -#define I2C_TSA5522 0xc2 -#define I2C_TDA7432 0x8a -#define I2C_TDA8425 0x82 -#define I2C_TDA9840 0x84 -#define I2C_TDA9850 0xb6 /* also used by 9855,9873 */ -#define I2C_TDA9875 0xb0 -#define I2C_HAUPEE 0xa0 -#define I2C_STBEE 0xae -#define I2C_VHX 0xc0 -#define I2C_MSP3400 0x80 -#define I2C_TEA6300 0x80 -#define I2C_DPL3518 0x84 - -#ifndef HAVE_TVAUDIO -#define TDA9840_SW 0x00 -#define TDA9840_LVADJ 0x02 -#define TDA9840_STADJ 0x03 -#define TDA9840_TEST 0x04 -#endif - -#define PT2254_L_CHANEL 0x10 -#define PT2254_R_CHANEL 0x08 -#define PT2254_DBS_IN_2 0x400 -#define PT2254_DBS_IN_10 0x20000 -#define WINVIEW_PT2254_CLK 0x40 -#define WINVIEW_PT2254_DATA 0x20 -#define WINVIEW_PT2254_STROBE 0x80 - -struct bttv_just_hacking { - int height,width; /* size */ - unsigned int format; /* should be VIDEO_PALETTE_* */ - long buf; - int len; -}; - -#define BTTV_JUST_HACKING _IOR('v' , BASE_VIDIOCPRIVATE+31,struct bttv_just_hacking) - -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ +#endif /* _BTTV_H_ */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/bttvp.h linux/drivers/media/video/bttvp.h --- v2.4.0-test10/linux/drivers/media/video/bttvp.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/video/bttvp.h Sun Nov 12 20:47:19 2000 @@ -0,0 +1,226 @@ +/* + bttv - Bt848 frame grabber driver + + bttv's *private* header file -- nobody else than bttv itself + should ever include this file. + + Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de) + (c) 1999,2000 Gerd Knorr + + 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. +*/ + +#ifndef _BTTVP_H_ +#define _BTTVP_H_ + +#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,48) + + +#include +#include +#include +#include + +#include "bt848.h" +#include "bttv.h" +#include "audiochip.h" + +#ifdef __KERNEL__ + +/* ---------------------------------------------------------- */ +/* bttv-driver.c */ + +/* insmod options */ +extern unsigned int bttv_verbose; +extern unsigned int bttv_debug; +extern unsigned int bttv_gpio; +extern void bttv_gpio_tracking(struct bttv *btv, char *comment); + +/* Anybody who uses more than four? */ +#define BTTV_MAX 4 +extern int bttv_num; /* number of Bt848s in use */ +extern struct bttv bttvs[BTTV_MAX]; + + +#ifndef O_NONCAP +#define O_NONCAP O_TRUNC +#endif + +#define MAX_GBUFFERS 64 +#define RISCMEM_LEN (32744*2) +#define VBI_MAXLINES 16 +#define VBIBUF_SIZE (2048*VBI_MAXLINES*2) + +#define BTTV_MAX_FBUF 0x208000 + +struct bttv_window +{ + int x, y; + ushort width, height; + ushort bpp, bpl; + ushort swidth, sheight; + unsigned long vidadr; + ushort freq; + int norm; + int interlace; + int color_fmt; + ushort depth; +}; + +struct bttv_pll_info { + unsigned int pll_ifreq; /* PLL input frequency */ + unsigned int pll_ofreq; /* PLL output frequency */ + unsigned int pll_crystal; /* Crystal used for input */ + unsigned int pll_current; /* Currently programmed ofreq */ +}; + +struct bttv_gbuf { + int stat; +#define GBUFFER_UNUSED 0 +#define GBUFFER_GRABBING 1 +#define GBUFFER_DONE 2 +#define GBUFFER_ERROR 3 + struct timeval tv; + + u16 width; + u16 height; + u16 fmt; + + u32 *risc; + unsigned long ro; + unsigned long re; +}; + +struct bttv { + struct video_device video_dev; + struct video_device radio_dev; + struct video_device vbi_dev; + struct video_picture picture; /* Current picture params */ + struct video_audio audio_dev; /* Current audio params */ + + spinlock_t s_lock; + struct semaphore lock; + int user; + int capuser; + + /* i2c */ + struct i2c_adapter i2c_adap; + struct i2c_algo_bit_data i2c_algo; + struct i2c_client i2c_client; + int i2c_state, i2c_rc; + struct i2c_client *i2c_clients[I2C_CLIENTS_MAX]; + + int tuner_type; + int channel; + + unsigned int nr; + unsigned short id; + struct pci_dev *dev; + unsigned int irq; /* IRQ used by Bt848 card */ + unsigned char revision; + unsigned long bt848_adr; /* bus address of IO mem returned by PCI BIOS */ + unsigned char *bt848_mem; /* pointer to mapped IO memory */ + unsigned long busriscmem; + u32 *riscmem; + + unsigned char *vbibuf; + struct bttv_window win; + int fb_color_ctl; + int type; /* card type */ + int cardid; + int audio; /* audio mode */ + int audio_chip; /* set to one of the chips supported by bttv.c */ + int radio; + + u32 *risc_jmp; + u32 *vbi_odd; + u32 *vbi_even; + u32 bus_vbi_even; + u32 bus_vbi_odd; + wait_queue_head_t vbiq; + wait_queue_head_t capq; + int vbip; + + u32 *risc_scr_odd; + u32 *risc_scr_even; + u32 risc_cap_odd; + u32 risc_cap_even; + int scr_on; + int vbi_on; + struct video_clip *cliprecs; + + struct bttv_gbuf *gbuf; + int gqueue[MAX_GBUFFERS]; + int gq_in,gq_out,gq_grab,gq_start; + char *fbuffer; + + struct bttv_pll_info pll; + unsigned int Fsc; + unsigned int field; + unsigned int last_field; /* number of last grabbed field */ + int i2c_command; + int triton1; + + int errors; + int needs_restart; + + wait_queue_head_t gpioq; + int shutdown; +}; +#endif + +#if defined(__powerpc__) /* big-endian */ +extern __inline__ void io_st_le32(volatile unsigned *addr, unsigned val) +{ + __asm__ __volatile__ ("stwbrx %1,0,%2" : \ + "=m" (*addr) : "r" (val), "r" (addr)); + __asm__ __volatile__ ("eieio" : : : "memory"); +} + +#define btwrite(dat,adr) io_st_le32((unsigned *)(btv->bt848_mem+(adr)),(dat)) +#define btread(adr) ld_le32((unsigned *)(btv->bt848_mem+(adr))) +#else +#define btwrite(dat,adr) writel((dat), (char *) (btv->bt848_mem+(adr))) +#define btread(adr) readl(btv->bt848_mem+(adr)) +#endif + +#define btand(dat,adr) btwrite((dat) & btread(adr), adr) +#define btor(dat,adr) btwrite((dat) | btread(adr), adr) +#define btaor(dat,mask,adr) btwrite((dat) | ((mask) & btread(adr)), adr) + +/* bttv ioctls */ + +#define BTTV_READEE _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]) +#define BTTV_WRITEE _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]) +#define BTTV_FIELDNR _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int) +#define BTTV_PLLSET _IOW('v' , BASE_VIDIOCPRIVATE+3, struct bttv_pll_info) +#define BTTV_BURST_ON _IOR('v' , BASE_VIDIOCPRIVATE+4, int) +#define BTTV_BURST_OFF _IOR('v' , BASE_VIDIOCPRIVATE+5, int) +#define BTTV_VERSION _IOR('v' , BASE_VIDIOCPRIVATE+6, int) +#define BTTV_PICNR _IOR('v' , BASE_VIDIOCPRIVATE+7, int) +#define BTTV_VBISIZE _IOR('v' , BASE_VIDIOCPRIVATE+8, int) + +#define TDA9850 0x01 +#define TDA9840 0x02 +#define TDA8425 0x03 +#define TEA6300 0x04 + +#endif /* _BTTVP_H_ */ + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/buz.c linux/drivers/media/video/buz.c --- v2.4.0-test10/linux/drivers/media/video/buz.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/media/video/buz.c Fri Nov 17 17:56:51 2000 @@ -3027,28 +3027,18 @@ return 0; } -static int zoran_init_done(struct video_device *dev) -{ - return 0; -} - static struct video_device zoran_template = { - BUZ_NAME, - VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | - VID_TYPE_SCALES | VID_TYPE_SUBCAPTURE, - VID_HARDWARE_ZR36067, - zoran_open, - zoran_close, - zoran_read, - zoran_write, - NULL, - zoran_ioctl, - zoran_mmap, - zoran_init_done, - NULL, - 0, - 0 + name: BUZ_NAME, + type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | + VID_TYPE_SCALES | VID_TYPE_SUBCAPTURE, + hardware: VID_HARDWARE_ZR36067, + open: zoran_open, + close: zoran_close, + read: zoran_read, + write: zoran_write, + ioctl: zoran_ioctl, + mmap: zoran_mmap, }; static int zr36057_init(int i) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/bw-qcam.c linux/drivers/media/video/bw-qcam.c --- v2.4.0-test10/linux/drivers/media/video/bw-qcam.c Sat Oct 2 07:35:15 1999 +++ linux/drivers/media/video/bw-qcam.c Fri Nov 17 17:56:51 2000 @@ -705,11 +705,6 @@ MOD_DEC_USE_COUNT; } -static int qcam_init_done(struct video_device *dev) -{ - return 0; -} - static long qcam_write(struct video_device *v, const char *buf, unsigned long count, int noblock) { return -EINVAL; @@ -926,20 +921,14 @@ static struct video_device qcam_template= { - "Connectix Quickcam", - VID_TYPE_CAPTURE, - VID_HARDWARE_QCAM_BW, - qcam_open, - qcam_close, - qcam_read, - qcam_write, - NULL, - qcam_ioctl, - NULL, - qcam_init_done, - NULL, - 0, - 0 + name: "Connectix Quickcam", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_QCAM_BW, + open: qcam_open, + close: qcam_close, + read: qcam_read, + write: qcam_write, + ioctl: qcam_ioctl, }; #define MAX_CAMS 4 diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/c-qcam.c linux/drivers/media/video/c-qcam.c --- v2.4.0-test10/linux/drivers/media/video/c-qcam.c Mon Jun 19 17:59:42 2000 +++ linux/drivers/media/video/c-qcam.c Fri Nov 17 17:56:51 2000 @@ -509,11 +509,6 @@ MOD_DEC_USE_COUNT; } -static int qcam_init_done(struct video_device *dev) -{ - return 0; -} - static long qcam_write(struct video_device *v, const char *buf, unsigned long count, int noblock) { return -EINVAL; @@ -733,20 +728,14 @@ /* video device template */ static struct video_device qcam_template= { - "Colour QuickCam", - VID_TYPE_CAPTURE, - VID_HARDWARE_QCAM_C, - qcam_open, - qcam_close, - qcam_read, - qcam_write, - NULL, - qcam_ioctl, - NULL, - qcam_init_done, - NULL, - 0, - 0 + name: "Colour QuickCam", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_QCAM_C, + open: qcam_open, + close: qcam_close, + read: qcam_read, + write: qcam_write, + ioctl: qcam_ioctl, }; /* Initialize the QuickCam driver control structure. */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/cpia.c linux/drivers/media/video/cpia.c --- v2.4.0-test10/linux/drivers/media/video/cpia.c Mon Aug 7 21:01:35 2000 +++ linux/drivers/media/video/cpia.c Fri Nov 17 17:56:51 2000 @@ -3031,20 +3031,16 @@ } static struct video_device cpia_template = { - "CPiA Camera", - VID_TYPE_CAPTURE, - VID_HARDWARE_CPIA, /* FIXME */ - cpia_open, /* open */ - cpia_close, /* close */ - cpia_read, /* read */ - NULL, /* no write */ - NULL, /* no poll */ - cpia_ioctl, /* ioctl */ - cpia_mmap, /* mmap */ - cpia_video_init, /* initialize */ - NULL, /* priv */ - 0, /* busy */ - -1 /* minor - unset */ + name: "CPiA Camera", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_CPIA, /* FIXME */ + open: cpia_open, + close: cpia_close, + read: cpia_read, + ioctl: cpia_ioctl, + mmap: cpia_mmap, + initialize: cpia_video_init, + minor: -1, }; /* initialise cam_data structure */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/cpia_usb.c linux/drivers/media/video/cpia_usb.c --- v2.4.0-test10/linux/drivers/media/video/cpia_usb.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/media/video/cpia_usb.c Sat Nov 11 19:04:30 2000 @@ -432,11 +432,21 @@ ucpia->sbuf[1].urb = NULL; } + if (ucpia->sbuf[1].data) { + kfree(ucpia->sbuf[1].data); + ucpia->sbuf[1].data = NULL; + } + if (ucpia->sbuf[0].urb) { usb_unlink_urb(ucpia->sbuf[0].urb); usb_free_urb(ucpia->sbuf[0].urb); ucpia->sbuf[0].urb = NULL; } + + if (ucpia->sbuf[0].data) { + kfree(ucpia->sbuf[0].data); + ucpia->sbuf[0].data = NULL; + } } static int cpia_usb_close(void *privdata) @@ -461,7 +471,8 @@ /* Probing and initializing */ -static void *cpia_probe(struct usb_device *udev, unsigned int ifnum) +static void *cpia_probe(struct usb_device *udev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_interface_descriptor *interface; struct usb_cpia *ucpia; @@ -474,13 +485,6 @@ interface = &udev->actconfig->interface[ifnum].altsetting[0]; - /* Is it a CPiA? */ - if (udev->descriptor.idVendor != 0x0553) - return NULL; - if (udev->descriptor.idProduct != 0x0002) - return NULL; - - /* We found a CPiA */ printk(KERN_INFO "USB CPiA camera found\n"); ucpia = kmalloc(sizeof(*ucpia), GFP_KERNEL); @@ -552,11 +556,18 @@ static void cpia_disconnect(struct usb_device *dev, void *ptr); +static struct usb_device_id cpia_id_table [] = { + { idVendor: 0x0553, idProduct: 0x0002 }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, cpia_id_table); + static struct usb_driver cpia_driver = { - "cpia", - cpia_probe, - cpia_disconnect, - { NULL, NULL } + name: "cpia", + probe: cpia_probe, + disconnect: cpia_disconnect, + id_table: cpia_id_table, }; /* don't use dev, it may be NULL! (see usb_cpia_cleanup) */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/id.h linux/drivers/media/video/id.h --- v2.4.0-test10/linux/drivers/media/video/id.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/video/id.h Sun Nov 12 20:47:19 2000 @@ -0,0 +1,26 @@ +/* FIXME: this temporarely, until these are included in linux/i2c-id.h */ + +/* drivers */ +#ifndef I2C_DRIVERID_TVMIXER +# define I2C_DRIVERID_TVMIXER I2C_DRIVERID_EXP0 +#endif +#ifndef I2C_DRIVERID_TVAUDIO +# define I2C_DRIVERID_TVAUDIO I2C_DRIVERID_EXP1 +#endif + +/* chips */ +#ifndef I2C_DRIVERID_DPL3518 +# define I2C_DRIVERID_DPL3518 I2C_DRIVERID_EXP2 +#endif +#ifndef I2C_DRIVERID_TDA9873 +# define I2C_DRIVERID_TDA9873 I2C_DRIVERID_EXP3 +#endif +#ifndef I2C_DRIVERID_TDA9875 +# define I2C_DRIVERID_TDA9875 I2C_DRIVERID_EXP0+4 +#endif +#ifndef I2C_DRIVERID_PIC16C54_PV951 +# define I2C_DRIVERID_PIC16C54_PV951 I2C_DRIVERID_EXP0+5 +#endif +#ifndef I2C_DRIVERID_TDA7432 +# define I2C_DRIVERID_TDA7432 I2C_DRIVERID_EXP0+6 +#endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/msp3400.c linux/drivers/media/video/msp3400.c --- v2.4.0-test10/linux/drivers/media/video/msp3400.c Sun Aug 6 12:45:28 2000 +++ linux/drivers/media/video/msp3400.c Sun Nov 12 20:47:19 2000 @@ -88,8 +88,10 @@ int norm; int stereo; int nicam_on; + int acb; int main, second; /* sound carrier */ + int muted; int left, right; /* volume */ int bass, treble; @@ -299,6 +301,43 @@ #define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT)) +/* ----------------------------------------------------------------------- */ + +#define SCART_MASK 0 +#define SCART_IN1 1 +#define SCART_IN2 2 +#define SCART_IN1_DA 3 +#define SCART_IN2_DA 4 +#define SCART_IN3 5 +#define SCART_IN4 6 +#define SCART_MONO 7 +#define SCART_MUTE 8 + +static int scarts[3][9] = { + /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, +}; + +static char *scart_names[] = { + "mask", "in1", "in2", "in1 da", "in2 da", "in3", "in4", "mono", "mute" +}; + +static void +msp3400c_set_scart(struct i2c_client *client, int in, int out) +{ + struct msp3400c *msp = client->data; + + if (-1 == scarts[out][in]) + return; + + dprintk("msp34xx: scart switch: %s => %d\n",scart_names[in],out); + msp->acb &= ~scarts[out][SCART_MASK]; + msp->acb |= scarts[out][in]; + msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb); +} + /* ------------------------------------------------------------------------ */ static void msp3400c_setcarrier(struct i2c_client *client, int cdo1, int cdo2) @@ -310,18 +349,21 @@ msp3400c_write(client,I2C_MSP3400C_DEM, 0x0056, 0); /*LOAD_REG_1/2*/ } -static void msp3400c_setvolume(struct i2c_client *client, int left, int right) +static void msp3400c_setvolume(struct i2c_client *client, + int muted, int left, int right) { - int vol,val,balance; + int vol = 0,val = 0,balance = 0; - vol = (left > right) ? left : right; - val = (vol * 0x73 / 65535) << 8; - balance = 0; - if (vol > 0) + if (!muted) { + vol = (left > right) ? left : right; + val = (vol * 0x73 / 65535) << 8; + } + if (vol > 0) { balance = ((right-left) * 127) / vol; + } - dprintk("msp34xx: setvolume: %d:%d 0x%02x 0x%02x\n", - left,right,val>>8,balance); + dprintk("msp34xx: setvolume: mute=%s %d:%d v=0x%02x b=0x%02x\n", + muted ? "on" : "off", left, right, val>>8, balance); msp3400c_write(client,I2C_MSP3400C_DFP, 0x0000, val); /* loudspeaker */ msp3400c_write(client,I2C_MSP3400C_DFP, 0x0006, val); /* headphones */ /* scart - on/off only */ @@ -470,11 +512,8 @@ if (msp->mode == MSP_MODE_AM_NICAM) { dprintk("msp3400: switching to AM mono\n"); /* AM mono decoding is handled by tuner, not MSP chip */ - /* so let's redirect sound from tuner via SCART */ - /* volume prescale for SCART */ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); - /* SCART switching control register*/ - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, 0xe900); + /* SCART switching control register */ + msp3400c_set_scart(client,SCART_MONO,0); src = 0x0200; break; } @@ -711,7 +750,7 @@ restart: msp->restart = 0; - msp3400c_setvolume(client, 0, 0); + msp3400c_setvolume(client, msp->muted, 0, 0); msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ ); val1 = val2 = 0; max1 = max2 = -1; @@ -829,6 +868,8 @@ msp->nicam_on = 0; msp3400c_setstereo(client, VIDEO_SOUND_MONO); msp3400c_setcarrier(client, msp->second, msp->main); + /* volume prescale for SCART (AM mono input) */ + msp3400c_write(client,I2C_MSP3400C_DFP, 0x000d, 0x1900); msp->watch_stereo = 1; } else if (max2 == 0 && msp->nicam) { /* D/K NICAM */ @@ -854,7 +895,7 @@ } /* unmute */ - msp3400c_setvolume(client, msp->left, msp->right); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); if (msp->watch_stereo) mod_timer(&msp->wake_stereo, jiffies+5*HZ); @@ -941,9 +982,6 @@ if (msp->rmmod || signal_pending(current)) goto done; - if (VIDEO_MODE_RADIO == msp->norm) - continue; /* nothing to do */ - msp->active = 1; if (msp->watch_stereo) { @@ -966,6 +1004,11 @@ /* put into sane state (and mute) */ msp3400c_reset(client); + /* set various prescales */ + msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */ + msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */ + msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */ + /* start autodetect */ switch (msp->norm) { case VIDEO_MODE_PAL: @@ -978,7 +1021,11 @@ break; case VIDEO_MODE_SECAM: mode = 0x0003; - std = 1; + std = 1; + break; + case VIDEO_MODE_RADIO: + mode = 0x0003; + std = 0x0040; break; default: mode = 0x0003; @@ -987,8 +1034,7 @@ } msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, mode); msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, std); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); + if (debug) { int i; for (i = 0; modelist[i].name != NULL; i++) @@ -1019,7 +1065,7 @@ } } for (i = 0; modelist[i].name != NULL; i++) - if (modelist[i].retval == val) + if (modelist[i].retval == val) break; dprintk("msp3410: current mode: %s (0x%04x)\n", modelist[i].name ? modelist[i].name : "unknown", @@ -1035,11 +1081,24 @@ msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val); } - /* set prescale / stereo */ + /* set stereo */ switch (val) { + case 0x0008: /* B/G NICAM */ + case 0x000a: /* I NICAM */ + if (val == 0x0008) + msp->mode = MSP_MODE_FM_NICAM1; + else + msp->mode = MSP_MODE_FM_NICAM2; + /* just turn on stereo */ + msp->stereo = VIDEO_SOUND_STEREO; + msp->nicam_on = 1; + msp->watch_stereo = 1; + msp3400c_setstereo(client,VIDEO_SOUND_STEREO); + break; case 0x0009: msp->mode = MSP_MODE_AM_NICAM; msp->stereo = VIDEO_SOUND_MONO; + msp->nicam_on = 1; msp3400c_setstereo(client,VIDEO_SOUND_MONO); msp->watch_stereo = 1; break; @@ -1047,26 +1106,31 @@ /* just turn on stereo */ msp->mode = MSP_MODE_BTSC; msp->stereo = VIDEO_SOUND_STEREO; + msp->nicam_on = 0; msp->watch_stereo = 1; msp3400c_setstereo(client,VIDEO_SOUND_STEREO); - /* set prescale */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */ + break; + case 0x0040: /* FM radio */ + msp->mode = MSP_MODE_FM_RADIO; + msp->stereo = VIDEO_SOUND_STEREO; + msp->nicam_on = 0; + msp->watch_stereo = 0; + /* scart routing */ + msp3400c_set_scart(client,SCART_IN2,0); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x08, 0x0220); break; case 0x0003: msp->mode = MSP_MODE_FM_TERRA; msp->stereo = VIDEO_SOUND_MONO; + msp->nicam_on = 0; msp->watch_stereo = 1; - /* fall */ - default: - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* NICAM */ break; } - + /* unmute */ msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->left, msp->right); + msp3400c_setvolume(client, msp->muted, msp->left, msp->right); if (msp->watch_stereo) mod_timer(&msp->wake_stereo, jiffies+HZ); @@ -1093,22 +1157,18 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg); static struct i2c_driver driver = { - "i2c msp3400 driver", - I2C_DRIVERID_MSP3400, - I2C_DF_NOTIFY, - msp_probe, - msp_detach, - msp_command, + name: "i2c msp3400 driver", + id: I2C_DRIVERID_MSP3400, + flags: I2C_DF_NOTIFY, + attach_adapter: msp_probe, + detach_client: msp_detach, + command: msp_command, }; static struct i2c_client client_template = { - "unset", - -1, - 0, - 0, - NULL, - &driver + name: "(unset)", + driver: &driver, }; static int msp_attach(struct i2c_adapter *adap, int addr, @@ -1150,8 +1210,9 @@ } rev1 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1e); - rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f); - if (0 == rev1 && 0 == rev2) { + if (-1 != rev1) + rev2 = msp3400c_read(c, I2C_MSP3400C_DFP, 0x1f); + if ((-1 == rev1) || (0 == rev1 && 0 == rev2)) { kfree(msp); printk("msp3400: error while reading chip version\n"); return -1; @@ -1180,7 +1241,7 @@ msp->wake_stereo.data = (unsigned long)msp; /* hello world :-) */ - printk(KERN_INFO "msp3400: init: chip=%s",c->name); + printk(KERN_INFO "msp34xx: init: chip=%s",c->name); if (msp->nicam) printk(", has NICAM support"); printk("\n"); @@ -1194,11 +1255,6 @@ msp->notify = NULL; wake_up_interruptible(&msp->wq); -#ifdef REGISTER_MIXER - if ((msp->mixer_num = register_sound_mixer(&msp3400c_mixer_fops,mixer)) < 0) - printk(KERN_ERR "msp3400c: cannot allocate mixer device\n"); -#endif - /* update our own array */ for (i = 0; i < MSP3400_MAX; i++) { if (NULL == msps[i]) { @@ -1218,11 +1274,6 @@ struct msp3400c *msp = (struct msp3400c*)client->data; int i; -#ifdef REGISTER_MIXER - if (msp->mixer_num >= 0) - unregister_sound_mixer(msp->mixer_num); -#endif - /* shutdown control thread */ del_timer(&msp->wake_stereo); if (msp->thread) @@ -1260,29 +1311,47 @@ static int msp_command(struct i2c_client *client,unsigned int cmd, void *arg) { struct msp3400c *msp = (struct msp3400c*)client->data; + __u16 *sarg = arg; #if 0 int *iarg = (int*)arg; - __u16 *sarg = arg; #endif switch (cmd) { + case AUDC_SET_INPUT: +#if 1 + /* hauppauge 44xxx scart switching */ + switch (*sarg) { + case AUDIO_RADIO: + msp3400c_set_scart(client,SCART_IN2,0); + break; + case AUDIO_EXTERN: + msp3400c_set_scart(client,SCART_IN1,0); + break; + default: + if (*sarg & AUDIO_MUTE) + msp3400c_set_scart(client,SCART_MUTE,0); + break; + } +#endif + break; + case AUDC_SET_RADIO: msp->norm = VIDEO_MODE_RADIO; msp->watch_stereo=0; del_timer(&msp->wake_stereo); + dprintk("msp34xx: switching to radio mode\n"); if (msp->simple) { - msp3400c_reset(client); - msp3400c_write(client, I2C_MSP3400C_DEM, 0x30, 0x0003); /* automatic */ - msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, 0x0040); /* FM Radio */ - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM prescale */ - msp3400c_setbass(client, msp->bass); - msp3400c_settreble(client, msp->treble); - msp3400c_setvolume(client, msp->left, msp->right); + /* the thread will do for us */ + msp3400c_setvolume(client,msp->muted,0,0); + if (msp->active) + msp->restart = 1; + wake_up_interruptible(&msp->wq); } else { + /* set msp3400 to FM radio mode */ msp3400c_setmode(client,MSP_MODE_FM_RADIO); msp3400c_setcarrier(client, MSP_CARRIER(10.7),MSP_CARRIER(10.7)); - msp3400c_setvolume(client,msp->left, msp->right); + msp3400c_setvolume(client,msp->muted,msp->left,msp->right); } break; @@ -1295,7 +1364,10 @@ va->flags |= VIDEO_AUDIO_VOLUME | VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; + VIDEO_AUDIO_TREBLE | + VIDEO_AUDIO_MUTABLE; + if (msp->muted) + va->flags |= VIDEO_AUDIO_MUTE; va->volume=MAX(msp->left,msp->right); va->balance=(32768*MIN(msp->left,msp->right))/ (va->volume ? va->volume : 1); @@ -1304,21 +1376,24 @@ va->bass = msp->bass; va->treble = msp->treble; - autodetect_stereo(client); - va->mode = msp->stereo; + if (msp->norm != VIDEO_MODE_RADIO) { + autodetect_stereo(client); + va->mode = msp->stereo; + } break; } case VIDIOCSAUDIO: { struct video_audio *va = arg; + msp->muted = (va->flags & VIDEO_AUDIO_MUTE); msp->left = (MIN(65536 - va->balance,32768) * va->volume) / 32768; msp->right = (MIN(va->balance,32768) * va->volume) / 32768; msp->bass = va->bass; msp->treble = va->treble; - msp3400c_setvolume(client,msp->left, msp->right); + msp3400c_setvolume(client,msp->muted,msp->left,msp->right); msp3400c_setbass(client,msp->bass); msp3400c_settreble(client,msp->treble); @@ -1334,13 +1409,14 @@ { struct video_channel *vc = arg; + dprintk("msp34xx: switching to TV mode\n"); msp->norm = vc->norm; break; } case VIDIOCSFREQ: { /* new channel -- kick audio carrier scan */ - msp3400c_setvolume(client,0,0); + msp3400c_setvolume(client,msp->muted,0,0); msp->watch_stereo=0; del_timer(&msp->wake_stereo); if (msp->active) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/planb.c linux/drivers/media/video/planb.c --- v2.4.0-test10/linux/drivers/media/video/planb.c Mon Aug 7 21:01:36 2000 +++ linux/drivers/media/video/planb.c Fri Nov 17 17:56:51 2000 @@ -2035,31 +2035,17 @@ return 0; } -/* This gets called upon device registration */ -/* we could do some init here */ -static int planb_init_done(struct video_device *dev) -{ - return 0; -} - static struct video_device planb_template= { - PLANB_DEVICE_NAME, - VID_TYPE_OVERLAY, - VID_HARDWARE_PLANB, - planb_open, - planb_close, - planb_read, - planb_write, -#if LINUX_VERSION_CODE >= 0x020100 - NULL, /* poll */ -#endif - planb_ioctl, - planb_mmap, /* mmap? */ - planb_init_done, - NULL, /* pointer to private data */ - 0, - 0 + name: PLANB_DEVICE_NAME, + type: VID_TYPE_OVERLAY, + hardware: VID_HARDWARE_PLANB, + open: planb_open, + close: planb_close, + read: planb_read, + write: planb_write, + ioctl: planb_ioctl, + mmap: planb_mmap, /* mmap? */ }; static int init_planb(struct planb *pb) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/pms.c linux/drivers/media/video/pms.c --- v2.4.0-test10/linux/drivers/media/video/pms.c Wed Nov 10 13:39:06 1999 +++ linux/drivers/media/video/pms.c Fri Nov 17 17:56:51 2000 @@ -681,11 +681,6 @@ MOD_DEC_USE_COUNT; } -static int pms_init_done(struct video_device *dev) -{ - return 0; -} - static long pms_write(struct video_device *v, const char *buf, unsigned long count, int noblock) { return -EINVAL; @@ -907,20 +902,14 @@ struct video_device pms_template= { - "Mediavision PMS", - VID_TYPE_CAPTURE, - VID_HARDWARE_PMS, - pms_open, - pms_close, - pms_read, - pms_write, - NULL, /* FIXME - we can use POLL on this board with the irq */ - pms_ioctl, - NULL, - pms_init_done, - NULL, - 0, - 0 + name: "Mediavision PMS", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_PMS, + open: pms_open, + close: pms_close, + read: pms_read, + write: pms_write, + ioctl: pms_ioctl, }; struct pms_device pms_device; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/saa5249.c linux/drivers/media/video/saa5249.c --- v2.4.0-test10/linux/drivers/media/video/saa5249.c Wed Feb 9 18:48:03 2000 +++ linux/drivers/media/video/saa5249.c Fri Nov 17 17:56:51 2000 @@ -669,15 +669,12 @@ static struct video_device saa_template = { - IF_NAME, - VID_TYPE_TELETEXT, /*| VID_TYPE_TUNER ?? */ - VID_HARDWARE_SAA5249, - saa5249_open, - saa5249_release, - NULL, /* read */ - saa5249_write, - NULL, /* poll */ - saa5249_ioctl, - /* the rest are null */ + name: IF_NAME, + type: VID_TYPE_TELETEXT, /*| VID_TYPE_TUNER ?? */ + hardware: VID_HARDWARE_SAA5249, + open: saa5249_open, + close: saa5249_release, + write: saa5249_write, + ioctl: saa5249_ioctl, }; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/stradis.c linux/drivers/media/video/stradis.c --- v2.4.0-test10/linux/drivers/media/video/stradis.c Wed Jul 5 10:56:13 2000 +++ linux/drivers/media/video/stradis.c Fri Nov 17 17:56:51 2000 @@ -1827,11 +1827,6 @@ return 0; } -static int saa_init_done(struct video_device *dev) -{ - return 0; -} - static int saa_mmap(struct video_device *dev, const char *adr, unsigned long size) { @@ -1993,20 +1988,15 @@ /* template for video_device-structure */ static struct video_device saa_template = { - "SAA7146A", - VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, - VID_HARDWARE_SAA7146, - saa_open, - saa_close, - saa_read, - saa_write, - NULL, /* poll */ - saa_ioctl, - saa_mmap, - saa_init_done, - NULL, - 0, - 0 + name: "SAA7146A", + type: VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, + hardware: VID_HARDWARE_SAA7146, + open: saa_open, + close: saa_close, + read: saa_read, + write: saa_write, + ioctl: saa_ioctl, + mmap: saa_mmap, }; static int configure_saa7146(struct pci_dev *dev, int num) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tda7432.c linux/drivers/media/video/tda7432.c --- v2.4.0-test10/linux/drivers/media/video/tda7432.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/media/video/tda7432.c Sun Nov 12 20:47:19 2000 @@ -25,10 +25,6 @@ * Added I2C_DRIVERID_TDA7432 * added loudness insmod control * Revision: 0.1 - initial version - * - * Changes: - * Arnaldo Carvalho de Melo - 08/14/2000 - * - resource allocation fixes in tda7432_attach */ #include @@ -45,12 +41,7 @@ #include "bttv.h" #include "audiochip.h" - -/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ -#ifndef I2C_DRIVERID_TDA7432 - #define I2C_DRIVERID_TDA7432 27 -#endif - +#include "id.h" MODULE_AUTHOR("Eric Sandeen "); MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip"); @@ -87,6 +78,7 @@ int tone; int lf, lr, rf, rr; int loud; + struct i2c_client c; }; static struct i2c_driver driver; @@ -316,19 +308,18 @@ struct tda7432 *t; struct i2c_client *client; d2printk("tda7432: In tda7432_attach\n"); - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; + + t = kmalloc(sizeof *t,GFP_KERNEL); + if (!t) + return -ENOMEM; + memset(t,0,sizeof *t); + + client = &t->c; memcpy(client,&client_template,sizeof(struct i2c_client)); client->adapter = adap; client->addr = addr; + client->data = t; - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) { - kfree(client); - return -ENOMEM; - } - memset(t,0,sizeof *t); do_tda7432_init(client); MOD_INC_USE_COUNT; strcpy(client->name,"TDA7432"); @@ -353,7 +344,6 @@ i2c_detach_client(client); kfree(t); - kfree(client); MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tda8425.c linux/drivers/media/video/tda8425.c --- v2.4.0-test10/linux/drivers/media/video/tda8425.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/media/video/tda8425.c Wed Dec 31 16:00:00 1969 @@ -1,330 +0,0 @@ -/* - * for the TDA8425 chip (I don't know which cards have this) - * WARNING: THIS DRIVER WILL LOAD WITHOUT COMPLAINTS EVEN IF A DIFFERENT - * CHIP IS AT ADDRESS 0x82 (it relies on i2c to make sure that there is a - * device acknowledging that address) - * - * Copyright (c) 1998 Greg Alexander - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from msp3400.c, which is by Gerd Knorr - * - * All of this should work, though it would be nice to eventually support - * balance (different left,right values). Also, the chip seems (?) to have - * two stereo inputs, so if someone has this card, could they tell me if the - * second one can be used for anything (i.e., does it have an external input - * that you can't hear even if you set input to composite?) - * - * Changes: - * Arnaldo Carvalho de Melo - 08/14/2000 - * - resource allocation fixes in tda8425_attach - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { - I2C_TDA8425 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ -#define dprintk if (debug) printk - - -struct tda8425 { - int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ - int stereo; - __u16 left,right; - __u16 bass,treble; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - - -#define TDA8425_VL 0x00 /* volume left */ -#define TDA8425_VR 0x01 /* volume right */ -#define TDA8425_BA 0x02 /* bass */ -#define TDA8425_TR 0x03 /* treble */ -#define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ -#define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ -#define TDA8425_S1_ON 0xCE /* audio on (mute off) - "linear stereo" mode */ - - -/* ******************************** * - * functions for talking to TDA8425 * - * ******************************** */ - -static int tda8425_write(struct i2c_client *client, int addr, int val) -{ - unsigned char buffer[2]; - - buffer[0] = addr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda8425: I/O error, trying (write %d 0x%x)\n", - addr, val); - return -1; - } - return 0; -} - -static void tda8425_set(struct i2c_client *client) -{ - struct tda8425 *tda = client->data; - - /* mode is ignored today */ - dprintk(KERN_DEBUG "tda8425_set(%04x,%04x,%04x,%04x)\n",tda->left>>10,tda->right>>10,tda->bass>>12,tda->treble>>12); - tda8425_write(client, TDA8425_VL, tda->left>>10 |0xC0); - tda8425_write(client, TDA8425_VR, tda->right>>10 |0xC0); - tda8425_write(client, TDA8425_BA, tda->bass>>12 |0xF0); - tda8425_write(client, TDA8425_TR, tda->treble>>12|0xF0); -} - -static void do_tda8425_init(struct i2c_client *client) -{ - struct tda8425 *tda = client->data; - - tda->left=tda->right =61440; /* 0dB */ - tda->bass=tda->treble=24576; /* 0dB */ - tda->mode=AUDIO_OFF; - tda->stereo=1; - /* left=right=0x27<<10, bass=treble=0x07<<12 */ - tda8425_write(client, TDA8425_S1, TDA8425_S1_OFF); /* mute */ - tda8425_set(client); -} - -static void tda8425_audio(struct i2c_client *client, int mode) -{ - struct tda8425 *tda = client->data; - - /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ - dprintk(KERN_DEBUG "tda8425_audio:%d (T,R,E,I,O)\n",mode); - tda->mode=mode; - tda8425_write(client, TDA8425_S1, - (mode==AUDIO_OFF)?TDA8425_S1_OFF:TDA8425_S1_ON); - /* this is the function we'll need to change if it turns out the - * input-selecting capabilities should be used. */ -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda8425_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda8425 *tda; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = tda = kmalloc(sizeof *tda,GFP_KERNEL); - if (!tda) { - kfree(client); - return -ENOMEM; - } - memset(tda,0,sizeof *tda); - do_tda8425_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA8425"); - printk(KERN_INFO "tda8425: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda8425_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda8425_attach); - return 0; -} - - -static int tda8425_detach(struct i2c_client *client) -{ - struct tda8425 *tda = client->data; - - do_tda8425_init(client); - i2c_detach_client(client); - - kfree(tda); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda8425_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda8425 *tda = client->data; - __u16 *sarg = arg; - - switch (cmd) { - case AUDC_SET_RADIO: - tda8425_audio(client,AUDIO_RADIO); - break; - case AUDC_SET_INPUT: - tda8425_audio(client,*sarg); - break; - - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - va->volume=MAX(tda->left,tda->right); - va->balance=(32768*MIN(tda->left,tda->right))/ - (va->volume ? va->volume : 1); - va->balance=(tda->leftright)? - (65535-va->balance) : va->balance; - va->bass = tda->bass; - va->treble = tda->treble; - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - tda->left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - tda->right = (MIN(va->balance,32768) * - va->volume) / 32768; - tda->bass = va->bass; - tda->treble = va->treble; - tda8425_set(client); - break; - } - -#if 0 - /* --- old, obsolete interface --- */ - case AUDC_GET_VOLUME_LEFT: - *sarg = tda->left; - break; - case AUDC_GET_VOLUME_RIGHT: - *sarg = tda->right; - break; - case AUDC_SET_VOLUME_LEFT: - tda->left = *sarg; - tda8425_set(client); - break; - case AUDC_SET_VOLUME_RIGHT: - tda->right = *sarg; - tda8425_set(client); - break; - - case AUDC_GET_BASS: - *sarg = tda->bass; - break; - case AUDC_SET_BASS: - tda->bass = *sarg; - tda8425_set(client); - break; - - case AUDC_GET_TREBLE: - *sarg = tda->treble; - break; - case AUDC_SET_TREBLE: - tda->treble = *sarg; - tda8425_set(client); - break; - - case AUDC_GET_STEREO: - *sarg = tda->stereo?VIDEO_SOUND_STEREO:VIDEO_SOUND_MONO; - break; - case AUDC_SET_STEREO: - tda->stereo=(*sarg==VIDEO_SOUND_MONO)?0:1; - /* TODO: make this write to the TDA9850? */ - break; - -/* case AUDC_SWITCH_MUTE: someday, maybe -- not a lot of point to - case AUDC_NEWCHANNEL: it and it would require preserving state - case AUDC_GET_DC: huh?? (not used by bttv.c) -*/ -#endif - default: - /* nothing */ - } - return 0; -} - - -static struct i2c_driver driver = { - "i2c tda8424 driver", - I2C_DRIVERID_TDA8425, - I2C_DF_NOTIFY, - tda8425_probe, - tda8425_detach, - tda8425_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda8425_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tda985x.c linux/drivers/media/video/tda985x.c --- v2.4.0-test10/linux/drivers/media/video/tda985x.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/media/video/tda985x.c Wed Dec 31 16:00:00 1969 @@ -1,542 +0,0 @@ -/* - * For the TDA9850 and TDA9855 chips - * (The TDA9855 is used on the Diamond DTV2000 and the TDA9850 is used - * on STB cards. Other cards probably use these chips as well.) - * This driver will not complain if used with any - * other i2c device with the same address. - * - * Copyright (c) 1999 Gerd Knorr - * TDA9850 code and TDA9855.c merger by Eric Sandeen (eric_sandeen@bigfoot.com) - * This code is placed under the terms of the GNU General Public License - * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) - * Which was based on tda8425.c by Greg Alexander (c) 1998 - * - * Contributors: - * Arnaldo Carvalho de Melo - * - * OPTIONS: - * debug - set to 1 if you'd like to see debug messages - * - set to 2 if you'd like to be flooded with debug messages - * chip - set to 9850 or 9855 to select your chip (default 9855) - * - * TODO: - * Fix channel change bug - sound goes out when changeing channels, mute - * and unmote to fix. - Is this still here? - * Fine tune sound - * Get rest of capabilities into video_audio struct... - * - * Revision 0.6 - resource allocation fixes in tda985x_attach (08/14/2000) - * Revision 0.5 - cleaned up debugging messages, added debug level=2 - * Revision: 0.4 - check for correct chip= insmod value - * also cleaned up comments a bit - * Revision: 0.3 - took out extraneous tda985x_write in tda985x_command - * Revision: 0.2 - added insmod option chip= - * Revision: 0.1 - original version - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - -MODULE_PARM(debug,"i"); -MODULE_PARM(chip,"i"); -MODULE_PARM_DESC(chip, "Type of chip to handle: 9850 or 9855"); - -static int debug = 0; /* insmod parameter */ -static int chip = 9855; /* insmod parameter */ - -/* Addresses to scan */ -#define I2C_TDA985x_L 0xb4 -#define I2C_TDA985x_H 0xb6 -static unsigned short normal_i2c[] = {I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = { - I2C_TDA985x_L >> 1, - I2C_TDA985x_H >> 1, - I2C_CLIENT_END -}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - -/* This is a superset of the TDA9850 and TDA9855 members */ - -struct tda985x { - int addr; - int rvol, lvol; - int bass, treble, sub; - int c4, c5, c6, c7; - int a1, a2, a3; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define dprintk if (debug) printk -#define d2printk if (debug == 2) printk - -/* The TDA9850 and TDA9855 are both made by Philips Semiconductor - * http://www.semiconductors.philips.com - * TDA9850: I2C-bus controlled BTSC stereo/SAP decoder - * TDA9855: I2C-bus controlled BTSC stereo/SAP decoder and audio processor - * - * The TDA9850 has more or less a subset of the functions that the TDA9855 - * has. As a result, we can re-use many of these defines. Anything with - * TDA9855 is specific to that chip, anything with TDA9850 is specific - * to that chip, and anything with TDA985x is valid for either. - * - * To complicate things further, the TDA9850 uses labels C1 through C4 - * for subaddresses 0x04 through 0x07, while the TDA9855 uses - * C1 through C3 for subadresses 0x05 through 0x07 - quite confusing. - * To help keep things straight, I have renamed the various C[1,4] labels - * to C[4,7] so that the numerical label matches the hex value of the - * subaddress for both chips. At least the A[1,3] labels line up. :) - */ - - /* subaddresses for TDA9855 */ -#define TDA9855_VR 0x00 /* Volume, right */ -#define TDA9855_VL 0x01 /* Volume, left */ -#define TDA9855_BA 0x02 /* Bass */ -#define TDA9855_TR 0x03 /* Treble */ -#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */ - - /* subaddresses for TDA9850 */ -#define TDA9850_C4 0x04 /* Control 1 for TDA9850 */ - - /* subaddesses for both chips */ -#define TDA985x_C5 0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */ -#define TDA985x_C6 0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */ -#define TDA985x_C7 0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */ -#define TDA985x_A1 0x08 /* Alignment 1 for both chips */ -#define TDA985x_A2 0x09 /* Alignment 2 for both chips */ -#define TDA985x_A3 0x0a /* Alignment 3 for both chips */ - - /* Masks for bits in TDA9855 subaddresses */ -/* 0x00 - VR in TDA9855 */ -/* 0x01 - VL in TDA9855 */ -/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f) - * in 1dB steps - mute is 0x27 */ - - -/* 0x02 - BA in TDA9855 */ -/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19) - * in .5dB steps - 0 is 0x0E */ - - -/* 0x03 - TR in TDA9855 */ -/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb) - * in 3dB steps - 0 is 0x7 */ - - /* Masks for bits in both chips' subaddresses */ -/* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */ -/* Unique to TDA9855: */ -/* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf) - * in 3dB steps - mute is 0x0 */ - -/* Unique to TDA9850: */ -/* lower 4 bits control stereo noise threshold, over which stereo turns off - * set to values of 0x00 through 0x0f for Ster1 through Ster16 */ - - -/* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/ -/* Unique to TDA9855: */ -#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */ -#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */ -#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ -#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ - /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ -#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ -#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ - -/* Unique to TDA9850: */ -/* lower 4 bits contol SAP noise threshold, over which SAP turns off - * set to values of 0x00 through 0x0f for SAP1 through SAP16 */ - - -/* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */ -/* Common to TDA9855 and TDA9850: */ -#define TDA985x_SAP 3<<6 /* Selects SAP output, mute if not received */ -#define TDA985x_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */ -#define TDA985x_MONO 0 /* Forces Mono output */ -#define TDA985x_LMU 1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */ - -/* Unique to TDA9855: */ -#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */ -#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/ -#define TDA9855_LINEAR 0 /* Linear Stereo */ -#define TDA9855_PSEUDO 1 /* Pseudo Stereo */ -#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */ -#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */ -#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/ - - -/* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */ -/* Common to both TDA9855 and TDA9850: */ -/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF) - * in .5dB steps - 0dB is 0x7 */ - - -/* 0x08, 0x09 - A1 and A2 (read/write) */ -/* Common to both TDA9855 and TDA9850: */ -/* lower 5 bites are wideband and spectral expander alignment - * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */ -#define TDA985x_STP 1<<5 /* Stereo Pilot/detect (read-only) */ -#define TDA985x_SAPP 1<<6 /* SAP Pilot/detect (read-only) */ -#define TDA985x_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/ - - -/* 0x0a - A3 */ -/* Common to both TDA9855 and TDA9850: */ -/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1), - * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */ -#define TDA985x_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral */ - -/* Unique to TDA9855: */ -/* 2 bits << 5 control AVL attack time: 420ohm (0x0), 730ohm (0x2), - * 1200ohm (0x1), 2100ohm (0x3) */ - - -/* Begin code */ - -static int tda985x_write(struct i2c_client *client, int subaddr, int val) -{ - unsigned char buffer[2]; - d2printk("tda985x: In tda985x_write\n"); - dprintk("tda985x: Writing %d 0x%x\n", subaddr, val); - buffer[0] = subaddr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tda985x: I/O error, trying (write %d 0x%x)\n", - subaddr, val); - return -1; - } - return 0; -} - -static int tda985x_read(struct i2c_client *client) -{ - unsigned char buffer; - d2printk("tda985x: In tda985x_read\n"); - if (1 != i2c_master_recv(client,&buffer,1)) { - printk(KERN_WARNING "tda985x: I/O error, trying (read)\n"); - return -1; - } - dprintk("tda985x: Read 0x%02x\n", buffer); - return buffer; -} - -static int tda985x_set(struct i2c_client *client) -{ - struct tda985x *t = client->data; - unsigned char buf[16]; - d2printk("tda985x: In tda985x_set\n"); - - if (chip == 9855) - { - dprintk(KERN_INFO - "tda985x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - t->rvol,t->lvol,t->bass,t->treble,t->sub, - t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); - buf[0] = TDA9855_VR; - buf[1] = t->rvol; - buf[2] = t->lvol; - buf[3] = t->bass; - buf[4] = t->treble; - buf[5] = t->sub; - buf[6] = t->c5; - buf[7] = t->c6; - buf[8] = t->c7; - buf[9] = t->a1; - buf[10] = t->a2; - buf[11] = t->a3; - if (12 != i2c_master_send(client,buf,12)) { - printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); - return -1; - } - } - - else if (chip == 9850) - { - dprintk(KERN_INFO - "tda986x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n", - t->c4,t->c5,t->c6,t->c7,t->a1,t->a2,t->a3); - buf[0] = TDA9850_C4; - buf[1] = t->c4; - buf[2] = t->c5; - buf[3] = t->c6; - buf[4] = t->c7; - buf[5] = t->a1; - buf[6] = t->a2; - buf[7] = t->a3; - if (8 != i2c_master_send(client,buf,8)) { - printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n"); - return -1; - } - } - - return 0; -} - -static void do_tda985x_init(struct i2c_client *client) -{ - struct tda985x *t = client->data; - d2printk("tda985x: In tda985x_init\n"); - - if (chip == 9855) - { - printk("tda985x: Using tda9855 options\n"); - t->rvol = 0x6f; /* 0dB */ - t->lvol = 0x6f; /* 0dB */ - t->bass = 0x0e; /* 0dB */ - t->treble = (0x07 << 1); /* 0dB */ - t->sub = 0x8 << 2; /* 0dB */ - t->c5 = TDA9855_MUTE | TDA9855_AVL | - TDA9855_LOUD | TDA9855_INT; - /* Set Mute, AVL, Loudness off, Internal sound */ - t->c6 = TDA985x_STEREO | TDA9855_LINEAR | - TDA9855_TZCM | TDA9855_VZCM; - /* Stereo linear mode, also wait til zero crossings */ - t->c7 = 0x07; /* 0dB input gain */ - } - - else if (chip == 9850) - { - printk("tda985x: Using tda9850 options\n"); - t->c4 = 0x08; /* Set stereo noise thresh to nominal */ - t->c5 = 0x08; /* Set SAP noise threshold to nominal */ - t->c6 = TDA985x_STEREO; /* Select Stereo mode for decoder */ - t->c7 = 0x07; /* 0dB input gain */ - } - - /* The following is valid for both chip types */ - t->a1 = 0x10; /* Select nominal wideband expander */ - t->a2 = 0x10; /* Select nominal spectral expander and 30mV trigger */ - t->a3 = 0x3; /* Set: nominal timing current, 420ohm AVL attack */ - - tda985x_set(client); -} - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tda985x_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tda985x *t; - struct i2c_client *client; - d2printk("tda985x: In tda985x_attach\n"); - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) { - kfree(client); - return -ENOMEM; - } - memset(t,0,sizeof *t); - do_tda985x_init(client); - MOD_INC_USE_COUNT; - strcpy(client->name,"TDA985x"); - printk(KERN_INFO "tda985x: init\n"); - - i2c_attach_client(client); - return 0; -} - -static int tda985x_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tda985x_attach); - return 0; -} - -static int tda985x_detach(struct i2c_client *client) -{ - struct tda985x *t = client->data; - - do_tda985x_init(client); - i2c_detach_client(client); - - kfree(t); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int tda985x_command(struct i2c_client *client, - unsigned int cmd, void *arg) -{ - struct tda985x *t = client->data; - d2printk("tda985x: In tda985x_command\n"); -#if 0 - __u16 *sarg = arg; -#endif - - switch (cmd) { - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - dprintk("tda985x: VIDIOCGAUDIO\n"); - if (chip == 9855) - { - int left,right; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - - /* min is 0x27 max is 0x7f, vstep is 2e8 */ - left = (t->lvol-0x27)*0x2e8; - right = (t->rvol-0x27)*0x2e8; - va->volume=MAX(left,right); - va->balance=(32768*MIN(left,right))/ - (va->volume ? va->volume : 1); - va->balance=(leftbalance) : va->balance; - va->bass = (t->bass-0x6)*0xccc; /* min 0x6 max 0x19 */ - va->treble = ((t->treble>>1)-0x3)*0x1c71; - } - - /* Valid for both chips: */ - { - va->mode = ((TDA985x_STP | TDA985x_SAPP) & - tda985x_read(client)) >> 4; - /* Add mono mode regardless of SAP and stereo */ - /* Allows forced mono */ - va->mode |= VIDEO_SOUND_MONO; - } - - break; /* VIDIOCGAUDIO case */ - } - - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - dprintk("tda985x: VIDEOCSAUDIO\n"); - if (chip == 9855) - { - int left,right; - - left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - right = (MIN(va->balance,32768) * - va->volume) / 32768; - t->lvol = left/0x2e8+0x27; - t->rvol = right/0x2e8+0x27; - t->bass = va->bass/0xccc+0x6; - t->treble = (va->treble/0x1c71+0x3)<<1; - tda985x_write(client,TDA9855_VL,t->lvol); - tda985x_write(client,TDA9855_VR,t->rvol); - tda985x_write(client,TDA9855_BA, t->bass); - tda985x_write(client,TDA9855_TR,t->treble); - } - - /* The following is valid for both chips */ - - switch (va->mode) { - case VIDEO_SOUND_MONO: - dprintk("tda985x: VIDEO_SOUND_MONO\n"); - t->c6= TDA985x_MONO | (t->c6 & 0x3f); - tda985x_write(client,TDA985x_C6,t->c6); - break; - case VIDEO_SOUND_STEREO: - dprintk("tda985x: VIDEO_SOUND_STEREO\n"); - t->c6= TDA985x_STEREO | (t->c6 & 0x3f); - tda985x_write(client,TDA985x_C6,t->c6); - break; - case VIDEO_SOUND_LANG1: - dprintk("tda985x: VIDEO_SOUND_LANG1\n"); - t->c6= TDA985x_SAP | (t->c6 & 0x3f); - tda985x_write(client,TDA985x_C6,t->c6); - break; - } /* End of (va->mode) switch */ - - break; - - } /* end of VIDEOCSAUDIO case */ - - default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */ - - /* nothing */ - d2printk("tda985x: Default\n"); - - } /* end of (cmd) switch */ - - return 0; -} - - -static struct i2c_driver driver = { - "i2c tda985x driver", - I2C_DRIVERID_TDA9855, /* Get new one for TDA985x? */ - I2C_DF_NOTIFY, - tda985x_probe, - tda985x_detach, - tda985x_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tda985x_init(void) -#endif -{ - if ( (chip != 9850) && (chip != 9855) ) - { - printk(KERN_ERR "tda985x: chip parameter must be 9850 or 9855\n"); - return -EINVAL; - } - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tda9875.c linux/drivers/media/video/tda9875.c --- v2.4.0-test10/linux/drivers/media/video/tda9875.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/media/video/tda9875.c Sun Nov 12 20:47:19 2000 @@ -11,13 +11,9 @@ * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Which was based on tda8425.c by Greg Alexander (c) 1998 * - * Contributors: - * Arnaldo Carvalho de Melo (0.2) - * * OPTIONS: * debug - set to 1 if you'd like to see debug messages * - * Revision 0.2 - resource allocation fixes in tda9875_attach (08/14/2000) * Revision: 0.1 - original version */ @@ -35,12 +31,7 @@ #include "bttv.h" #include "audiochip.h" - -/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */ -#ifndef I2C_DRIVERID_TDA9875 - #define I2C_DRIVERID_TDA9875 28 -#endif - +#include "id.h" MODULE_PARM(debug,"i"); @@ -68,6 +59,7 @@ int mode; int rvol, lvol; int bass, treble; + struct i2c_client c; }; @@ -228,19 +220,18 @@ struct tda9875 *t; struct i2c_client *client; dprintk("In tda9875_attach\n"); - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; + + t = kmalloc(sizeof *t,GFP_KERNEL); + if (!t) + return -ENOMEM; + memset(t,0,sizeof *t); + + client = &t->c; memcpy(client,&client_template,sizeof(struct i2c_client)); client->adapter = adap; client->addr = addr; + client->data = t; - client->data = t = kmalloc(sizeof *t,GFP_KERNEL); - if (!t) { - kfree(client); - return -ENOMEM; - } - memset(t,0,sizeof *t); do_tda9875_init(client); MOD_INC_USE_COUNT; strcpy(client->name,"TDA9875"); @@ -265,7 +256,6 @@ i2c_detach_client(client); kfree(t); - kfree(client); MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tea6300.c linux/drivers/media/video/tea6300.c --- v2.4.0-test10/linux/drivers/media/video/tea6300.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/media/video/tea6300.c Wed Dec 31 16:00:00 1969 @@ -1,350 +0,0 @@ -/* - * for the TEA6300 chip (only found on Gateway STB TV/FM cards tho the best - * of my knowledge) - * WARNING: THIS DRIVER WILL LOAD WITHOUT COMPLAINTS EVEN IF THE WRONG - * CHIP (i.e., an MSP3400) IS ON I2C ADDRESS 0x80 (it relies on i2c to - * make sure that there is a device acknowledging that address). This - * is a potential problem because the MSP3400 is very popular and does - * use this address! You have been warned! - * - * Copyright (c) 1998 Greg Alexander - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from msp3400.c, which is by Gerd Knorr - * - * All of this should work, though it would be nice to eventually support - * balance (different left,right values) and, if someone ever finds a card - * with the support (or if you're careful with a soldering iron), fade - * (front/back). - * - * Changes: - * Arnaldo Carvalho de Melo - 08/14/2000 - * - resource allocation fixes in tea6300_attach - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - - -/* Addresses to scan */ -#define I2C_TEA6300 0x80 -static unsigned short normal_i2c[] = { - I2C_TEA6300 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ - -#define dprintk if (debug) printk - - -struct tea6300 { - int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ - int stereo; - __u16 left,right; - __u16 bass,treble; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define TEA6300_VL 0x00 /* volume left */ -#define TEA6300_VR 0x01 /* volume right */ -#define TEA6300_BA 0x02 /* bass */ -#define TEA6300_TR 0x03 /* treble */ -#define TEA6300_FA 0x04 /* fader control */ -#define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ -#define TEA6300_S_SA 0x01 /* stereo A input */ -#define TEA6300_S_SB 0x02 /* stereo B */ -#define TEA6300_S_SC 0x04 /* stereo C */ -#define TEA6300_S_GMU 0x80 /* general mute */ - - -/* ******************************** * - * functions for talking to TEA6300 * - * ******************************** */ - -static int tea6300_write(struct i2c_client *client, int addr, int val) -{ - unsigned char buffer[2]; - - buffer[0] = addr; - buffer[1] = val; - if (2 != i2c_master_send(client,buffer,2)) { - printk(KERN_WARNING "tea6300: I/O error, trying (write %d 0x%x)\n", - addr, val); - return -1; - } - return 0; -} - -static void tea6300_set(struct i2c_client *client) -{ - struct tea6300 *tea = client->data; - - /* mode is ignored today */ - dprintk(KERN_DEBUG "tea6300_set(%04x,%04x,%04x,%04x)\n",tea->left>>10,tea->right>>10,tea->bass>>12,tea->treble>>12); - tea6300_write(client, TEA6300_VL, tea->left>>10 ); - tea6300_write(client, TEA6300_VR, tea->right>>10 ); - tea6300_write(client, TEA6300_BA, tea->bass>>12 ); - tea6300_write(client, TEA6300_TR, tea->treble>>12); -} - -static void do_tea6300_init(struct i2c_client *client) -{ - struct tea6300 *tea = client->data; - - tea->left=tea->right =49152; /* -10dB (loud enough, but not beyond - normal line levels - so as to avoid - clipping */ - tea->bass=tea->treble=28672; /* 0dB */ - tea->mode=AUDIO_OFF; - tea->stereo=1; - /* left=right=0x27<<10, bass=treble=0x07<<12 */ - tea6300_write(client, TEA6300_FA, 0x3f ); /* fader off */ - tea6300_write(client, TEA6300_S , TEA6300_S_GMU); /* mute */ - tea6300_set(client); -} - -static void tea6300_audio(struct i2c_client *client, int mode) -{ - struct tea6300 *tea = client->data; - - /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ - dprintk(KERN_DEBUG "tea6300_audio:%d (T,R,E,I,O)\n",mode); - tea->mode=mode; - if (mode==AUDIO_OFF) { /* just mute it */ - tea6300_write(client, TEA6300_S, TEA6300_S_GMU); - return; - } - switch(mode) { - case AUDIO_TUNER: - tea6300_write(client, TEA6300_S, TEA6300_S_SA); - break; - case AUDIO_RADIO: - tea6300_write(client, TEA6300_S, TEA6300_S_SB); - break; - case AUDIO_EXTERN: - tea6300_write(client, TEA6300_S, TEA6300_S_SC); - break; - } -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tea6300_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tea6300 *tea; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = tea = kmalloc(sizeof *tea,GFP_KERNEL); - if (!tea) { - kfree(client); - return -ENOMEM; - } - memset(tea,0,sizeof *tea); - do_tea6300_init(client); - - MOD_INC_USE_COUNT; - strcpy(client->name,"TEA6300T"); - printk(KERN_INFO "tea6300: initialized\n"); - - i2c_attach_client(client); - return 0; -} - -static int tea6300_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tea6300_attach); - return 0; -} - -static int tea6300_detach(struct i2c_client *client) -{ - struct tea6300 *tea = client->data; - - do_tea6300_init(client); - i2c_detach_client(client); - - kfree(tea); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int -tea6300_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - struct tea6300 *tea = client->data; - __u16 *sarg = arg; - - switch (cmd) { - case AUDC_SET_RADIO: - tea6300_audio(client,AUDIO_RADIO); - break; - case AUDC_SET_INPUT: - tea6300_audio(client,*sarg); - break; - - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; - va->volume=MAX(tea->left,tea->right); - va->balance=(32768*MIN(tea->left,tea->right))/ - (va->volume ? va->volume : 1); - va->balance=(tea->leftright)? - (65535-va->balance) : va->balance; - va->bass = tea->bass; - va->treble = tea->treble; - break; - } - case VIDIOCSAUDIO: - { - struct video_audio *va = arg; - - tea->left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - tea->right = (MIN(va->balance,32768) * - va->volume) / 32768; - tea->bass = va->bass; - tea->treble = va->treble; - tea6300_set(client); - break; - } -#if 0 - /* --- old, obsolete interface --- */ - case AUDC_GET_VOLUME_LEFT: - *sarg = tea->left; - break; - case AUDC_GET_VOLUME_RIGHT: - *sarg = tea->right; - break; - case AUDC_SET_VOLUME_LEFT: - tea->left = *sarg; - tea6300_set(client); - break; - case AUDC_SET_VOLUME_RIGHT: - tea->right = *sarg; - tea6300_set(client); - break; - - case AUDC_GET_BASS: - *sarg = tea->bass; - break; - case AUDC_SET_BASS: - tea->bass = *sarg; - tea6300_set(client); - break; - - case AUDC_GET_TREBLE: - *sarg = tea->treble; - break; - case AUDC_SET_TREBLE: - tea->treble = *sarg; - tea6300_set(client); - break; - - case AUDC_GET_STEREO: - *sarg = tea->stereo?VIDEO_SOUND_STEREO:VIDEO_SOUND_MONO; - break; - case AUDC_SET_STEREO: - tea->stereo=(*sarg==VIDEO_SOUND_MONO)?0:1; - /* TODO: make this write to the TDA9850? */ - break; - -/* case AUDC_SWITCH_MUTE: someday, maybe -- not a lot of point to - case AUDC_NEWCHANNEL: it and it would require preserving state - case AUDC_GET_DC: huh?? (not used by bttv.c) -*/ -#endif - default: - /* nothing */ - } - return 0; -} - -static struct i2c_driver driver = { - "i2c tea6300 driver", - I2C_DRIVERID_TEA6300, - I2C_DF_NOTIFY, - tea6300_probe, - tea6300_detach, - tea6300_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tea6300_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tea6420.c linux/drivers/media/video/tea6420.c --- v2.4.0-test10/linux/drivers/media/video/tea6420.c Mon Aug 21 09:18:19 2000 +++ linux/drivers/media/video/tea6420.c Wed Dec 31 16:00:00 1969 @@ -1,273 +0,0 @@ -/* - * for the TEA6420 chip (only found on 3DFX (STB) TV/FM cards to the best - * of my knowledge) - * Copyright (C) 2000 Dave Stuart - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from tea6300 by . . . - * - * Copyright (c) 1998 Greg Alexander - * This code is placed under the terms of the GNU General Public License - * Code liberally copied from msp3400.c, which is by Gerd Knorr - * - * Changes: - * Arnaldo Carvalho de Melo - 08/14/2000 - * - resource allocation fixes in tea6300_attach - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bttv.h" -#include "audiochip.h" - - -/* Addresses to scan */ -#define I2C_TEA6420 0x98 -static unsigned short normal_i2c[] = { - I2C_TEA6420 >> 1, - I2C_CLIENT_END}; -static unsigned short normal_i2c_range[] = {I2C_CLIENT_END}; -static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; -static struct i2c_client_address_data addr_data = { - normal_i2c, normal_i2c_range, - probe, probe_range, - ignore, ignore_range, - force -}; - - -MODULE_PARM(debug,"i"); -static int debug = 0; /* insmod parameter */ - -#define dprintk if (debug) printk - - -struct tea6420 { - int mode; /* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */ - int stereo; -}; - -static struct i2c_driver driver; -static struct i2c_client client_template; - -#define TEA6420_S_SA 0x00 /* stereo A input */ -#define TEA6420_S_SB 0x01 /* stereo B */ -#define TEA6420_S_SC 0x02 /* stereo C */ -#define TEA6420_S_SD 0x03 /* stereo D */ -#define TEA6420_S_SE 0x04 /* stereo E */ -#define TEA6420_S_GMU 0x05 /* general mute */ - - -/* ******************************** * - * functions for talking to TEA6420 * - * ******************************** */ - -static int tea6420_write(struct i2c_client *client, int val) -{ - unsigned char buffer[2]; - int result; - -/* buffer[0] = addr; */ - buffer[0] = val; - result = i2c_master_send(client,buffer,1); - if (1 != result) { - printk(KERN_WARNING "tea6420: I/O error, trying (write -0x%x) result = %d\n", val, result); - return -1; - } - return 0; -} - - -static void do_tea6420_init(struct i2c_client *client) -{ - struct tea6420 *tea = client->data; - - tea->mode=AUDIO_OFF; - tea->stereo=1; - tea6420_write(client, TEA6420_S_GMU); /* mute */ -} - -static void tea6420_audio(struct i2c_client *client, int mode) -{ - struct tea6420 *tea = client->data; - - /* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */ - dprintk(KERN_DEBUG "tea6420_audio:%d (T,R,E,I,O)\n",mode); - tea->mode=mode; - if (mode==AUDIO_OFF) { /* just mute it */ - tea6420_write(client, TEA6420_S_GMU); - return; - } - switch(mode) { - case AUDIO_TUNER: - tea6420_write(client, TEA6420_S_SA); - break; - case AUDIO_RADIO: - tea6420_write(client, TEA6420_S_SB); - break; - case AUDIO_EXTERN: - tea6420_write(client, TEA6420_S_SC); - break; - } -} - - -/* *********************** * - * i2c interface functions * - * *********************** */ - -static int tea6420_attach(struct i2c_adapter *adap, int addr, - unsigned short flags, int kind) -{ - struct tea6420 *tea; - struct i2c_client *client; - - client = kmalloc(sizeof *client,GFP_KERNEL); - if (!client) - return -ENOMEM; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; - - client->data = tea = kmalloc(sizeof *tea,GFP_KERNEL); - if (!tea) { - kfree(client); - return -ENOMEM; - } - memset(tea,0,sizeof *tea); - do_tea6420_init(client); - - MOD_INC_USE_COUNT; - strcpy(client->name,"TEA6420"); - printk(KERN_INFO "tea6420: initialized\n"); - - i2c_attach_client(client); - return 0; -} - -static int tea6420_probe(struct i2c_adapter *adap) -{ - if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) - return i2c_probe(adap, &addr_data, tea6420_attach); - return 0; -} - -static int tea6420_detach(struct i2c_client *client) -{ - struct tea6420 *tea = client->data; - - do_tea6420_init(client); - i2c_detach_client(client); - - kfree(tea); - kfree(client); - MOD_DEC_USE_COUNT; - return 0; -} - -static int -tea6420_command(struct i2c_client *client, unsigned int cmd, void *arg) -{ - __u16 *sarg = arg; - - switch (cmd) { - case AUDC_SET_RADIO: - tea6420_audio(client,AUDIO_RADIO); - break; - case AUDC_SET_INPUT: - tea6420_audio(client,*sarg); - break; - - /* --- v4l ioctls --- */ - /* take care: bttv does userspace copying, we'll get a - kernel pointer here... */ - case VIDIOCGAUDIO: - { - struct video_audio *va = arg; - - va->flags |= VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE; -/* va->volume=MAX(tea->left,tea->right); - va->balance=(32768*MIN(tea->left,tea->right))/ - (va->volume ? va->volume : 1); - va->balance=(tea->leftright)? - (65535-va->balance) : va->balance; - va->bass = tea->bass; - va->treble = tea->treble; -*/ break; - } - case VIDIOCSAUDIO: - { - -/* tea->left = (MIN(65536 - va->balance,32768) * - va->volume) / 32768; - tea->right = (MIN(va->balance,32768) * - va->volume) / 32768; - tea->bass = va->bass; - tea->treble = va->treble; - tea6420_set(client); -*/ break; - } - -default: - /* nothing */ - } - return 0; -} - -static struct i2c_driver driver = { - "i2c tea6420 driver", - I2C_DRIVERID_TEA6420, - I2C_DF_NOTIFY, - tea6420_probe, - tea6420_detach, - tea6420_command, -}; - -static struct i2c_client client_template = -{ - "(unset)", /* name */ - -1, - 0, - 0, - NULL, - &driver -}; - -#ifdef MODULE -int init_module(void) -#else -int tea6420_init(void) -#endif -{ - i2c_add_driver(&driver); - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - i2c_del_driver(&driver); -} -#endif - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tuner.c linux/drivers/media/video/tuner.c --- v2.4.0-test10/linux/drivers/media/video/tuner.c Tue Jul 18 22:35:33 2000 +++ linux/drivers/media/video/tuner.c Sun Nov 12 20:47:19 2000 @@ -113,6 +113,8 @@ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, { "Temic 4006FH5", TEMIC, PAL_I, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, + { "Alps TSCH6",Alps,NTSC, + 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, }; #define TUNERS (sizeof(tuners)/sizeof(struct tunertype)) @@ -132,6 +134,20 @@ #define TUNER_MODE 0x38 #define TUNER_AFC 0x07 +#define TUNER_STEREO 0x10 /* radio mode */ +#define TUNER_SIGNAL 0x07 /* radio mode */ + +static int tuner_signal(struct i2c_client *c) +{ + return (tuner_getstatus(c) & TUNER_SIGNAL)<<13; +} + +static int tuner_stereo(struct i2c_client *c) +{ + return (tuner_getstatus (c) & TUNER_STEREO); +} + + static int tuner_islocked (struct i2c_client *c) { return (tuner_getstatus (c) & TUNER_FL); @@ -229,7 +245,7 @@ } tun=&tuners[t->type]; - config = 0xa5; + config = 0xa4 /* 0xa5 */; /* bit 0 is AFC (set) vs. RF-Signal (clear) */ div=freq + (int)(16*10.7); div&=0x7fff; @@ -248,8 +264,12 @@ printk ("tuner: PLL locked\n"); else printk ("tuner: PLL not locked\n"); - - printk ("tuner: AFC: %d\n", tuner_afcstatus (c)); + + if (config & 1) { + printk ("tuner: AFC: %d\n", tuner_afcstatus(c)); + } else { + printk ("tuner: Signal: %d\n", tuner_signal(c)); + } } } /* ---------------------------------------------------------------------- */ @@ -370,6 +390,22 @@ } return 0; } + case VIDIOCGTUNER: + { + struct video_tuner *vt = arg; + + if (t->radio) + vt->signal = tuner_signal(client); + return 0; + } + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + if (t->radio) + va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO); + return 0; + } + #if 0 /* --- old, obsolete interface --- */ case TUNER_SET_TVFREQ: diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tuner.h linux/drivers/media/video/tuner.h --- v2.4.0-test10/linux/drivers/media/video/tuner.h Thu Nov 18 19:25:28 1999 +++ linux/drivers/media/video/tuner.h Sun Nov 12 20:47:19 2000 @@ -36,6 +36,8 @@ #define TUNER_ALPS_TSBB5_PAL_I 11 #define TUNER_ALPS_TSBE5_PAL 12 #define TUNER_ALPS_TSBC5_PAL 13 +#define TUNER_TEMIC_4006FH5_PAL 14 +#define TUNER_ALPS_TSHC6_NTSC 15 #define NOTUNER 0 #define PAL 1 diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tvaudio.c linux/drivers/media/video/tvaudio.c --- v2.4.0-test10/linux/drivers/media/video/tvaudio.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/video/tvaudio.c Sun Nov 12 20:47:19 2000 @@ -0,0 +1,1107 @@ +/* + * experimental driver for simple i2c audio chips. + * + * Copyright (c) 2000 Gerd Knorr + * based on code by: + * Eric Sandeen (eric_sandeen@bigfoot.com) + * Steve VanDeBogart (vandebo@uclink.berkeley.edu) + * Greg Alexander (galexand@acm.org) + * + * This code is placed under the terms of the GNU General Public License + * + * OPTIONS: + * debug - set to 1 if you'd like to see debug messages + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "audiochip.h" +#include "tvaudio.h" +#include "id.h" + + +/* ---------------------------------------------------------------------- */ +/* insmod args */ + +MODULE_PARM(debug,"i"); +static int debug = 0; /* insmod parameter */ + +#define dprintk if (debug) printk + + +/* ---------------------------------------------------------------------- */ +/* our structs */ + +#define MAXREGS 64 + +struct CHIPSTATE; +typedef int (*getvalue)(int); +typedef int (*checkit)(struct CHIPSTATE*); +typedef int (*getmode)(struct CHIPSTATE*); +typedef void (*setmode)(struct CHIPSTATE*, int mode); +typedef void (*checkmode)(struct CHIPSTATE*); + +/* i2c command */ +typedef struct AUDIOCMD { + int count; /* # of bytes to send */ + unsigned char bytes[MAXREGS+1]; /* addr, data, data, ... */ +} audiocmd; + +/* chip description */ +struct CHIPDESC { + char *name; /* chip name */ + int id; /* ID */ + int addr_lo, addr_hi; /* i2c address range */ + int registers; /* # of registers */ + + int *insmodopt; + checkit checkit; + int flags; +#define CHIP_HAS_VOLUME 1 +#define CHIP_HAS_BASSTREBLE 2 +#define CHIP_HAS_INPUTSEL 4 + + /* various i2c command sequences */ + audiocmd init; + + /* which register has which value */ + int leftreg,rightreg,treblereg,bassreg; + + /* initialize with (defaults to 65535/65535/32768/32768 */ + int leftinit,rightinit,trebleinit,bassinit; + + /* functions to convert the values (v4l -> chip) */ + getvalue volfunc,treblefunc,bassfunc; + + /* get/set mode */ + getmode getmode; + setmode setmode; + + /* check / autoswitch audio after channel switches */ + checkmode checkmode; + + /* input switch register + values for v4l inputs */ + int inputreg; + int inputmap[8]; + int inputmute; +}; +static struct CHIPDESC chiplist[]; + +/* current state of the chip */ +struct CHIPSTATE { + struct i2c_client c; + + /* index into CHIPDESC array */ + int type; + + /* shadow register set */ + audiocmd shadow; + + /* current settings */ + __u16 left,right,treble,bass; + + /* thread */ + struct task_struct *thread; + struct semaphore *notify; + wait_queue_head_t wq; + int wake,done; +}; + + +/* ---------------------------------------------------------------------- */ +/* i2c adresses */ + +static unsigned short normal_i2c[] = { + I2C_TDA8425 >> 1, + I2C_TEA6300 >> 1, + I2C_TEA6420 >> 1, + I2C_TDA9840 >> 1, + I2C_TDA985x_L >> 1, + I2C_TDA985x_H >> 1, + I2C_PIC16C54 >> 1, + I2C_CLIENT_END }; +static unsigned short normal_i2c_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + normal_i2c, normal_i2c_range, + probe, probe_range, + ignore, ignore_range, + force +}; + +static struct i2c_driver driver; +static struct i2c_client client_template; + + +/* ---------------------------------------------------------------------- */ +/* i2c I/O functions */ + +static int chip_write(struct CHIPSTATE *chip, int subaddr, int val) +{ + unsigned char buffer[2]; + + if (-1 == subaddr) { + dprintk("%s: chip_write: 0x%x\n", chip->c.name, val); + chip->shadow.bytes[1] = val; + buffer[0] = val; + if (1 != i2c_master_send(&chip->c,buffer,1)) { + printk(KERN_WARNING "%s: I/O error (write 0x%x)\n", + chip->c.name, val); + return -1; + } + } else { + dprintk("%s: chip_write: reg%d=0x%x\n", chip->c.name, subaddr, val); + chip->shadow.bytes[subaddr+1] = val; + buffer[0] = subaddr; + buffer[1] = val; + if (2 != i2c_master_send(&chip->c,buffer,2)) { + printk(KERN_WARNING "%s: I/O error (write reg%d=0x%x)\n", + chip->c.name, subaddr, val); + return -1; + } + } + return 0; +} + +static int chip_read(struct CHIPSTATE *chip) +{ + unsigned char buffer; + + if (1 != i2c_master_recv(&chip->c,&buffer,1)) { + printk(KERN_WARNING "%s: I/O error (read)\n", + chip->c.name); + return -1; + } + dprintk("%s: chip_read: 0x%x\n",chip->c.name,buffer); + return buffer; +} + +static int chip_read2(struct CHIPSTATE *chip, int subaddr) +{ + unsigned char write[1]; + unsigned char read[1]; + struct i2c_msg msgs[2] = { + { chip->c.addr, 0, 1, write }, + { chip->c.addr, I2C_M_RD, 1, read } + }; + write[1] = subaddr; + + if (2 != i2c_transfer(chip->c.adapter,msgs,2)) { + printk(KERN_WARNING "%s: I/O error (read2)\n", + chip->c.name); + return -1; + } + dprintk("%s: chip_read2: reg%d=0x%x\n", + chip->c.name,subaddr,read[0]); + return read[0]; +} + +static int chip_cmd(struct CHIPSTATE *chip, char *name, audiocmd *cmd) +{ + int i; + + if (0 == cmd->count) + return 0; + + /* update our shadow register set; print bytes if (debug > 0) */ + dprintk("%s: chip_cmd(%s): reg=%d, data:", + chip->c.name,name,cmd->bytes[0]); + for (i = 1; i < cmd->count; i++) { + dprintk(" 0x%x",cmd->bytes[i]); + chip->shadow.bytes[i+cmd->bytes[0]] = cmd->bytes[i]; + } + dprintk("\n"); + + /* send data to the chip */ + if (cmd->count != i2c_master_send(&chip->c,cmd->bytes,cmd->count)) { + printk(KERN_WARNING "%s: I/O error (%s)\n", chip->c.name, name); + return -1; + } + return 0; +} + +/* ---------------------------------------------------------------------- */ +/* kernel thread for doing i2c stuff asyncronly + * right now it is used only to check the audio mode (mono/stereo/whatever) + * some time after switching to another TV channel, then turn on stereo + * if available, ... + */ + +static int chip_thread(void *data) +{ + struct CHIPSTATE *chip = data; + struct CHIPDESC *desc = chiplist + chip->type; + +#ifdef CONFIG_SMP + lock_kernel(); +#endif + daemonize(); + sigfillset(¤t->blocked); + strcpy(current->comm,chip->c.name); + chip->thread = current; +#ifdef CONFIG_SMP + unlock_kernel(); +#endif + + dprintk("%s: thread started\n", chip->c.name); + if(chip->notify != NULL) + up(chip->notify); + + for (;;) { + if (chip->done) + break; + if (!chip->wake) { + interruptible_sleep_on(&chip->wq); + dprintk("%s: thread wakeup\n", chip->c.name); + if (chip->done || signal_pending(current)) + break; + } + chip->wake = 0; + + /* wait some time -- let the audio hardware + figure the current mode */ + current->state = TASK_INTERRUPTIBLE; + schedule_timeout(HZ); + if (signal_pending(current)) + break; + if (chip->wake) + continue; + + dprintk("%s: thread checkmode\n", chip->c.name); + desc->checkmode(chip); + } + + chip->thread = NULL; + dprintk("%s: thread exiting\n", chip->c.name); + if(chip->notify != NULL) + up(chip->notify); + + return 0; +} + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - defines+functions for tda9840 */ + +#define TDA9840_SW 0x00 +#define TDA9840_LVADJ 0x02 +#define TDA9840_STADJ 0x03 +#define TDA9840_TEST 0x04 + +#define TDA9840_MONO 0x10 +#define TDA9840_STEREO 0x2a +#define TDA9840_DUALA 0x12 +#define TDA9840_DUALB 0x1e +#define TDA9840_DUALAB 0x1a +#define TDA9840_DUALBA 0x16 +#define TDA9840_EXTERNAL 0x7a + +int tda9840_getmode(struct CHIPSTATE *chip) +{ + return VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; +} + +void tda9840_setmode(struct CHIPSTATE *chip, int mode) +{ + int update = 1; + int t = chip->shadow.bytes[TDA9840_SW + 1] & ~0x7e; + + switch (mode) { + case VIDEO_SOUND_MONO: + t |= TDA9840_MONO; + break; + case VIDEO_SOUND_STEREO: + t |= TDA9840_STEREO; + break; + case VIDEO_SOUND_LANG1: + t |= TDA9840_DUALA; + break; + case VIDEO_SOUND_LANG2: + t |= TDA9840_DUALB; + break; + default: + update = 0; + } + + if (update) + chip_write(chip, TDA9840_SW, t); +} + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - defines+functions for tda985x */ + +/* subaddresses for TDA9855 */ +#define TDA9855_VR 0x00 /* Volume, right */ +#define TDA9855_VL 0x01 /* Volume, left */ +#define TDA9855_BA 0x02 /* Bass */ +#define TDA9855_TR 0x03 /* Treble */ +#define TDA9855_SW 0x04 /* Subwoofer - not connected on DTV2000 */ + +/* subaddresses for TDA9850 */ +#define TDA9850_C4 0x04 /* Control 1 for TDA9850 */ + +/* subaddesses for both chips */ +#define TDA985x_C5 0x05 /* Control 2 for TDA9850, Control 1 for TDA9855 */ +#define TDA985x_C6 0x06 /* Control 3 for TDA9850, Control 2 for TDA9855 */ +#define TDA985x_C7 0x07 /* Control 4 for TDA9850, Control 3 for TDA9855 */ +#define TDA985x_A1 0x08 /* Alignment 1 for both chips */ +#define TDA985x_A2 0x09 /* Alignment 2 for both chips */ +#define TDA985x_A3 0x0a /* Alignment 3 for both chips */ + +/* Masks for bits in TDA9855 subaddresses */ +/* 0x00 - VR in TDA9855 */ +/* 0x01 - VL in TDA9855 */ +/* lower 7 bits control gain from -71dB (0x28) to 16dB (0x7f) + * in 1dB steps - mute is 0x27 */ + + +/* 0x02 - BA in TDA9855 */ +/* lower 5 bits control bass gain from -12dB (0x06) to 16.5dB (0x19) + * in .5dB steps - 0 is 0x0E */ + + +/* 0x03 - TR in TDA9855 */ +/* 4 bits << 1 control treble gain from -12dB (0x3) to 12dB (0xb) + * in 3dB steps - 0 is 0x7 */ + +/* Masks for bits in both chips' subaddresses */ +/* 0x04 - SW in TDA9855, C4/Control 1 in TDA9850 */ +/* Unique to TDA9855: */ +/* 4 bits << 2 control subwoofer/surround gain from -14db (0x1) to 14db (0xf) + * in 3dB steps - mute is 0x0 */ + +/* Unique to TDA9850: */ +/* lower 4 bits control stereo noise threshold, over which stereo turns off + * set to values of 0x00 through 0x0f for Ster1 through Ster16 */ + + +/* 0x05 - C5 - Control 1 in TDA9855 , Control 2 in TDA9850*/ +/* Unique to TDA9855: */ +#define TDA9855_MUTE 1<<7 /* GMU, Mute at outputs */ +#define TDA9855_AVL 1<<6 /* AVL, Automatic Volume Level */ +#define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ +#define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ + /* Bits 0 to 3 select various combinations + * of line in and line out, only the + * interesting ones are defined */ +#define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ +#define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ + +/* Unique to TDA9850: */ +/* lower 4 bits contol SAP noise threshold, over which SAP turns off + * set to values of 0x00 through 0x0f for SAP1 through SAP16 */ + + +/* 0x06 - C6 - Control 2 in TDA9855, Control 3 in TDA9850 */ +/* Common to TDA9855 and TDA9850: */ +#define TDA985x_SAP 3<<6 /* Selects SAP output, mute if not received */ +#define TDA985x_STEREO 1<<6 /* Selects Stereo ouput, mono if not received */ +#define TDA985x_MONO 0 /* Forces Mono output */ +#define TDA985x_LMU 1<<3 /* Mute (LOR/LOL for 9855, OUTL/OUTR for 9850) */ + +/* Unique to TDA9855: */ +#define TDA9855_TZCM 1<<5 /* If set, don't mute till zero crossing */ +#define TDA9855_VZCM 1<<4 /* If set, don't change volume till zero crossing*/ +#define TDA9855_LINEAR 0 /* Linear Stereo */ +#define TDA9855_PSEUDO 1 /* Pseudo Stereo */ +#define TDA9855_SPAT_30 2 /* Spatial Stereo, 30% anti-phase crosstalk */ +#define TDA9855_SPAT_50 3 /* Spatial Stereo, 52% anti-phase crosstalk */ +#define TDA9855_E_MONO 7 /* Forced mono - mono select elseware, so useless*/ + +/* 0x07 - C7 - Control 3 in TDA9855, Control 4 in TDA9850 */ +/* Common to both TDA9855 and TDA9850: */ +/* lower 4 bits control input gain from -3.5dB (0x0) to 4dB (0xF) + * in .5dB steps - 0dB is 0x7 */ + +/* 0x08, 0x09 - A1 and A2 (read/write) */ +/* Common to both TDA9855 and TDA9850: */ +/* lower 5 bites are wideband and spectral expander alignment + * from 0x00 to 0x1f - nominal at 0x0f and 0x10 (read/write) */ +#define TDA985x_STP 1<<5 /* Stereo Pilot/detect (read-only) */ +#define TDA985x_SAPP 1<<6 /* SAP Pilot/detect (read-only) */ +#define TDA985x_STS 1<<7 /* Stereo trigger 1= <35mV 0= <30mV (write-only)*/ + +/* 0x0a - A3 */ +/* Common to both TDA9855 and TDA9850: */ +/* lower 3 bits control timing current for alignment: -30% (0x0), -20% (0x1), + * -10% (0x2), nominal (0x3), +10% (0x6), +20% (0x5), +30% (0x4) */ +#define TDA985x_ADJ 1<<7 /* Stereo adjust on/off (wideband and spectral */ + +int tda9855_volume(int val) { return val/0x2e8+0x27; } +int tda9855_bass(int val) { return val/0xccc+0x06; } +int tda9855_treble(int val) { return (val/0x1c71+0x3)<<1; } + +int tda985x_getmode(struct CHIPSTATE *chip) +{ + int mode; + + mode = ((TDA985x_STP | TDA985x_SAPP) & + chip_read(chip)) >> 4; + /* Add mono mode regardless of SAP and stereo */ + /* Allows forced mono */ + return mode | VIDEO_SOUND_MONO; +} + +void tda985x_setmode(struct CHIPSTATE *chip, int mode) +{ + int update = 1; + int c6 = chip->shadow.bytes[TDA985x_C6+1] & 0x3f; + + switch (mode) { + case VIDEO_SOUND_MONO: + c6 |= TDA985x_MONO; + break; + case VIDEO_SOUND_STEREO: + c6 |= TDA985x_STEREO; + break; + case VIDEO_SOUND_LANG1: + c6 |= TDA985x_SAP; + break; + default: + update = 0; + } + if (update) + chip_write(chip,TDA985x_C6,c6); +} + + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - defines+functions for tda9873h */ + +/* Subaddresses for TDA9873H */ + +#define TDA9873_SW 0x00 /* Switching */ +#define TDA9873_AD 0x01 /* Adjust */ +#define TDA9873_PT 0x02 /* Port */ + +/* Subaddress 0x00: Switching Data + * B7..B0: + * + * B1, B0: Input source selection + * 0, 0 internal + * 1, 0 external stereo + * 0, 1 external mono + */ +#define TDA9873_INTERNAL 0 +#define TDA9873_EXT_STEREO 2 +#define TDA9873_EXT_MONO 1 + +/* B3, B2: output signal select + * B4 : transmission mode + * 0, 0, 1 Mono + * 1, 0, 0 Stereo + * 1, 1, 1 Stereo (reversed channel) + * 0, 0, 0 Dual AB + * 0, 0, 1 Dual AA + * 0, 1, 0 Dual BB + * 0, 1, 1 Dual BA + */ + +#define TDA9873_TR_MONO 4 +#define TDA9873_TR_STEREO 1 << 4 +#define TDA9873_TR_REVERSE (1 << 3) & (1 << 2) +#define TDA9873_TR_DUALA 1 << 2 +#define TDA9873_TR_DUALB 1 << 3 + +/* output level controls + * B5: output level switch (0 = reduced gain, 1 = normal gain) + * B6: mute (1 = muted) + * B7: auto-mute (1 = auto-mute enabled) + */ + +#define TDA9873_GAIN_NORMAL 1 << 5 +#define TDA9873_MUTE 1 << 6 +#define TDA9873_AUTOMUTE 1 << 7 + +/* Subaddress 0x01: Adjust/standard */ + +/* Lower 4 bits (C3..C0) control stereo adjustment on R channel (-0.6 - +0.7 dB) + * Recommended value is +0 dB + */ + +#define TDA9873_STEREO_ADJ 0x06 /* 0dB gain */ + +/* Bits C6..C4 control FM stantard + * C6, C5, C4 + * 0, 0, 0 B/G (PAL FM) + * 0, 0, 1 M + * 0, 1, 0 D/K(1) + * 0, 1, 1 D/K(2) + * 1, 0, 0 D/K(3) + * 1, 0, 1 I + */ +#define TDA9873_BG 0 +#define TDA9873_M 1 +#define TDA9873_DK1 2 +#define TDA9873_DK2 3 +#define TDA9873_DK3 4 +#define TDA9873_I 5 + +/* C7 controls identification response time (1=fast/0=normal) + */ +#define TDA9873_IDR_NORM 0 +#define TDA9873_IDR_FAST 1 << 7 + + +/* Subaddress 0x02: Port data */ + +/* E1, E0 free programmable ports P1/P2 + 0, 0 both ports low + 0, 1 P1 high + 1, 0 P2 high + 1, 1 both ports high +*/ + +#define TDA9873_PORTS 3 + +/* E2: test port */ +#define TDA9873_TST_PORT 1 << 2 + +/* E5..E3 control mono output channel (together with transmission mode bit B4) + * + * E5 E4 E3 B4 OUTM + * 0 0 0 0 mono + * 0 0 1 0 DUAL B + * 0 1 0 1 mono (from stereo decoder) + */ +#define TDA9873_MOUT_MONO 0 +#define TDA9873_MOUT_FMONO 0 +#define TDA9873_MOUT_DUALA 0 +#define TDA9873_MOUT_DUALB 1 << 3 +#define TDA9873_MOUT_ST 1 << 4 +#define TDA9873_MOUT_EXTM (1 << 4 ) & (1 << 3) +#define TDA9873_MOUT_EXTL 1 << 5 +#define TDA9873_MOUT_EXTR (1 << 5 ) & (1 << 3) +#define TDA9873_MOUT_EXTLR (1 << 5 ) & (1 << 4) +#define TDA9873_MOUT_MUTE (1 << 5 ) & (1 << 4) & (1 << 3) + +/* Status bits: (chip read) */ +#define TDA9873_PONR 0 /* Power-on reset detected if = 1 */ +#define TDA9873_STEREO 2 /* Stereo sound is identified */ +#define TDA9873_DUAL 4 /* Dual sound is identified */ + +int tda9873_getmode(struct CHIPSTATE *chip) +{ + int val,mode; + + val = chip_read(chip); + mode = VIDEO_SOUND_MONO; + if (val & TDA9873_STEREO) + mode |= VIDEO_SOUND_STEREO; + if (val & TDA9873_DUAL) + mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + dprintk ("tda9873_getmode(): raw chip read: %d, return: %d\n", + val, mode); + return mode; +} + +void tda9873_setmode(struct CHIPSTATE *chip, int mode) +{ + int sw_data = chip->shadow.bytes[TDA9873_SW+1] & 0xe3; + /* int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */ + dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]); + dprintk("tda9873_setmode(): sw_data = %d\n", sw_data); + + switch (mode) { + case VIDEO_SOUND_MONO: + sw_data |= TDA9873_TR_MONO; + break; + case VIDEO_SOUND_STEREO: + sw_data |= TDA9873_TR_STEREO; + break; + case VIDEO_SOUND_LANG1: + sw_data |= TDA9873_TR_DUALA; + break; + case VIDEO_SOUND_LANG2: + sw_data |= TDA9873_TR_DUALB; + break; + } + dprintk("tda9873_setmode(): req. mode %d; chip_write: %d\n", mode, sw_data); + chip_write(chip,TDA9873_SW,sw_data); +} + +void tda9873_checkmode(struct CHIPSTATE *chip) +{ + int mode = tda9873_getmode(chip); + + if (mode & VIDEO_SOUND_STEREO) + tda9873_setmode(chip,VIDEO_SOUND_STEREO); + if (mode & VIDEO_SOUND_LANG1) + tda9873_setmode(chip,VIDEO_SOUND_LANG1); +} + +int tda9873_checkit(struct CHIPSTATE *chip) +{ + int rc; + + if (-1 == (rc = chip_read2(chip,254))) + return 0; + return (rc & ~0x1f) == 0x80; +} + + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - defines+functions for tea6420 */ + +#define TEA6300_VL 0x00 /* volume left */ +#define TEA6300_VR 0x01 /* volume right */ +#define TEA6300_BA 0x02 /* bass */ +#define TEA6300_TR 0x03 /* treble */ +#define TEA6300_FA 0x04 /* fader control */ +#define TEA6300_S 0x05 /* switch register */ + /* values for those registers: */ +#define TEA6300_S_SA 0x01 /* stereo A input */ +#define TEA6300_S_SB 0x02 /* stereo B */ +#define TEA6300_S_SC 0x04 /* stereo C */ +#define TEA6300_S_GMU 0x80 /* general mute */ + +#define TEA6420_S_SA 0x00 /* stereo A input */ +#define TEA6420_S_SB 0x01 /* stereo B */ +#define TEA6420_S_SC 0x02 /* stereo C */ +#define TEA6420_S_SD 0x03 /* stereo D */ +#define TEA6420_S_SE 0x04 /* stereo E */ +#define TEA6420_S_GMU 0x05 /* general mute */ + +int tea6300_shift10(int val) { return val >> 10; } +int tea6300_shift12(int val) { return val >> 12; } + + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - defines+functions for tda8425 */ + +#define TDA8425_VL 0x00 /* volume left */ +#define TDA8425_VR 0x01 /* volume right */ +#define TDA8425_BA 0x02 /* bass */ +#define TDA8425_TR 0x03 /* treble */ +#define TDA8425_S1 0x08 /* switch functions */ + /* values for those registers: */ +#define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ +#define TDA8425_S1_ON 0xCE /* audio on (mute off) - "linear stereo" mode */ + +int tda8425_shift10(int val) { return val >> 10 | 0xc0; } +int tda8425_shift12(int val) { return val >> 12 | 0xf0; } + + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - defines+functions for pic16c54 (PV951) */ + +/* the registers of 16C54, I2C sub address. */ +#define PIC16C54_REG_KEY_CODE 0x01 /* Not use. */ +#define PIC16C54_REG_MISC 0x02 + +/* bit definition of the RESET register, I2C data. */ +#define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ + /* code of remote controller */ +#define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ +#define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ +#define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ +#define PIC16C54_MISC_SND_MUTE 0x10 /* bit 4, Mute Audio(Line-in and Tuner) */ +#define PIC16C54_MISC_SND_NOTMUTE 0x20 /* bit 5 */ +#define PIC16C54_MISC_SWITCH_TUNER 0x40 /* bit 6 , Switch to Line-in */ +#define PIC16C54_MISC_SWITCH_LINE 0x80 /* bit 7 , Switch to Tuner */ + + +/* ---------------------------------------------------------------------- */ +/* audio chip descriptions - struct CHIPDESC */ + +/* insmod options to enable/disable individual audio chips */ +int tda8425 = 1; +int tda9840 = 1; +int tda9850 = 1; +int tda9855 = 1; +int tda9873 = 1; +int tea6300 = 0; +int tea6420 = 1; +int pic16c54 = 1; +MODULE_PARM(tda8425,"i"); +MODULE_PARM(tda9840,"i"); +MODULE_PARM(tda9850,"i"); +MODULE_PARM(tda9855,"i"); +MODULE_PARM(tda9873,"i"); +MODULE_PARM(tea6300,"i"); +MODULE_PARM(tea6420,"i"); +MODULE_PARM(pic16c54,"i"); + +static struct CHIPDESC chiplist[] = { + { + name: "tda9840", + id: I2C_DRIVERID_TDA9840, + insmodopt: &tda9840, + addr_lo: I2C_TDA9840 >> 1, + addr_hi: I2C_TDA9840 >> 1, + registers: 5, + + getmode: tda9840_getmode, + setmode: tda9840_setmode, + + init: { 2, { TDA9840_SW, 0x2a } } + }, + { + name: "tda9873h", + id: I2C_DRIVERID_TDA9873, + checkit: tda9873_checkit, + insmodopt: &tda9873, + addr_lo: I2C_TDA985x_L >> 1, + addr_hi: I2C_TDA985x_H >> 1, + registers: 3, + + getmode: tda9873_getmode, + setmode: tda9873_setmode, + checkmode: tda9873_checkmode, + + init: { 4, { TDA9873_SW, 0xa0, 0x06, 0x03 } } + }, + { + name: "tda9850", + id: I2C_DRIVERID_TDA9850, + insmodopt: &tda9850, + addr_lo: I2C_TDA985x_L >> 1, + addr_hi: I2C_TDA985x_H >> 1, + registers: 11, + + getmode: tda985x_getmode, + setmode: tda985x_setmode, + + init: { 8, { TDA9850_C4, 0x08, 0x08, TDA985x_STEREO, 0x07, 0x10, 0x10, 0x03 } } + }, + { + name: "tda9855", + id: I2C_DRIVERID_TDA9855, + insmodopt: &tda9855, + addr_lo: I2C_TDA985x_L >> 1, + addr_hi: I2C_TDA985x_H >> 1, + registers: 11, + flags: CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE, + + leftreg: TDA9855_VR, + rightreg: TDA9855_VL, + bassreg: TDA9855_BA, + treblereg: TDA9855_TR, + volfunc: tda9855_volume, + bassfunc: tda9855_bass, + treblefunc: tda9855_treble, + + getmode: tda985x_getmode, + setmode: tda985x_setmode, + + init: { 12, { 0, 0x6f, 0x6f, 0x0e, 0x07<<1, 0x8<<2, + TDA9855_MUTE | TDA9855_AVL | TDA9855_LOUD | TDA9855_INT, + TDA985x_STEREO | TDA9855_LINEAR | TDA9855_TZCM | TDA9855_VZCM, + 0x07, 0x10, 0x10, 0x03 }} + }, + { + name: "tea6300", + id: I2C_DRIVERID_TEA6300, + insmodopt: &tea6300, + addr_lo: I2C_TEA6300 >> 1, + addr_hi: I2C_TEA6300 >> 1, + registers: 6, + flags: CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL, + + leftreg: TEA6300_VR, + rightreg: TEA6300_VL, + bassreg: TEA6300_BA, + treblereg: TEA6300_TR, + volfunc: tea6300_shift10, + bassfunc: tea6300_shift12, + treblefunc: tea6300_shift12, + + inputreg: TEA6300_S, + inputmap: { TEA6300_S_SA, TEA6300_S_SB, TEA6300_S_SC }, + inputmute: TEA6300_S_GMU, + }, + { + name: "tea6420", + id: I2C_DRIVERID_TEA6420, + insmodopt: &tea6420, + addr_lo: I2C_TEA6420 >> 1, + addr_hi: I2C_TEA6420 >> 1, + registers: 1, + flags: CHIP_HAS_INPUTSEL, + + inputreg: -1, + inputmap: { TEA6420_S_SA, TEA6420_S_SB, TEA6420_S_SC }, + inputmute: TEA6300_S_GMU, + }, + { + name: "tda8425", + id: I2C_DRIVERID_TDA8425, + insmodopt: &tda8425, + addr_lo: I2C_TDA8425 >> 1, + addr_hi: I2C_TDA8425 >> 1, + registers: 9, + flags: CHIP_HAS_VOLUME | CHIP_HAS_BASSTREBLE | CHIP_HAS_INPUTSEL, + + leftreg: TDA8425_VR, + rightreg: TDA8425_VL, + bassreg: TDA8425_BA, + treblereg: TDA8425_TR, + volfunc: tda8425_shift10, + bassfunc: tda8425_shift12, + treblefunc: tda8425_shift12, + + inputreg: TDA8425_S1, + inputmap: { TDA8425_S1_ON, TDA8425_S1_ON, TDA8425_S1_ON }, + inputmute: TDA8425_S1_OFF, + }, + { + name: "pic16c54 (PV951)", + id: I2C_DRIVERID_PIC16C54_PV951, + insmodopt: &pic16c54, + addr_lo: I2C_PIC16C54 >> 1, + addr_hi: I2C_PIC16C54>> 1, + registers: 2, + flags: CHIP_HAS_INPUTSEL, + + inputreg: PIC16C54_REG_MISC, + inputmap: {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER, + PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE}, + inputmute: PIC16C54_MISC_SND_MUTE, + }, + { name: NULL } /* EOF */ +}; + + +/* ---------------------------------------------------------------------- */ +/* i2c registration */ + +static int chip_attach(struct i2c_adapter *adap, int addr, + unsigned short flags, int kind) +{ + struct CHIPSTATE *chip; + struct CHIPDESC *desc; + + chip = kmalloc(sizeof(*chip),GFP_KERNEL); + if (!chip) + return -ENOMEM; + memset(chip,0,sizeof(*chip)); + memcpy(&chip->c,&client_template,sizeof(struct i2c_client)); + chip->c.adapter = adap; + chip->c.addr = addr; + chip->c.data = chip; + + /* find description for the chip */ + dprintk("tvaudio: chip @ addr=0x%x\n",addr<<1); + for (desc = chiplist; desc->name != NULL; desc++) { + if (0 == *(desc->insmodopt)) + continue; + if (addr < desc->addr_lo || + addr > desc->addr_hi) + continue; + if (desc->checkit && !desc->checkit(chip)) + continue; + break; + } + if (desc->name == NULL) { + dprintk("tvaudio: no matching chip description found\n"); + return -EIO; + } + dprintk("tvaudio: %s matches:%s%s%s\n",desc->name, + (desc->flags & CHIP_HAS_VOLUME) ? " volume" : "", + (desc->flags & CHIP_HAS_BASSTREBLE) ? " bass/treble" : "", + (desc->flags & CHIP_HAS_INPUTSEL) ? " audiomux" : ""); + + /* fill required data structures */ + strcpy(chip->c.name,desc->name); + chip->type = desc-chiplist; + chip->shadow.count = desc->registers+1; + + /* register */ + MOD_INC_USE_COUNT; + i2c_attach_client(&chip->c); + + /* initialization */ + chip_cmd(chip,"init",&desc->init); + if (desc->flags & CHIP_HAS_VOLUME) { + chip->left = desc->leftinit ? desc->leftinit : 65536; + chip->right = desc->rightinit ? desc->rightinit : 65536; + chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); + chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); + } + if (desc->flags & CHIP_HAS_BASSTREBLE) { + chip->treble = desc->trebleinit ? desc->trebleinit : 32768; + chip->bass = desc->bassinit ? desc->bassinit : 32768; + chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); + chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); + } + + if (desc->checkmode) { + /* start async thread */ + DECLARE_MUTEX_LOCKED(sem); + chip->notify = &sem; + init_waitqueue_head(&chip->wq); + kernel_thread(chip_thread,(void *)chip,0); + down(&sem); + chip->notify = NULL; + chip->wake++; + wake_up_interruptible(&chip->wq); + } + return 0; +} + +static int chip_probe(struct i2c_adapter *adap) +{ + if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848)) + return i2c_probe(adap, &addr_data, chip_attach); + return 0; +} + +static int chip_detach(struct i2c_client *client) +{ + struct CHIPSTATE *chip = client->data; + + if (NULL != chip->thread) { + /* shutdown async thread */ + DECLARE_MUTEX_LOCKED(sem); + chip->notify = &sem; + chip->done = 1; + wake_up_interruptible(&chip->wq); + down(&sem); + chip->notify = NULL; + } + + i2c_detach_client(&chip->c); + kfree(chip); + MOD_DEC_USE_COUNT; + return 0; +} + +/* ---------------------------------------------------------------------- */ +/* video4linux interface */ + +static int chip_command(struct i2c_client *client, + unsigned int cmd, void *arg) +{ + __u16 *sarg = arg; + struct CHIPSTATE *chip = client->data; + struct CHIPDESC *desc = chiplist + chip->type; + + dprintk("%s: chip_command 0x%x\n",chip->c.name,cmd); + + switch (cmd) { + case AUDC_SET_INPUT: + if (desc->flags & CHIP_HAS_INPUTSEL) { + if (*sarg & 0x80) + chip_write(chip,desc->inputreg,desc->inputmute); + else + chip_write(chip,desc->inputreg,desc->inputmap[*sarg]); + } + break; + /* --- v4l ioctls --- */ + /* take care: bttv does userspace copying, we'll get a + kernel pointer here... */ + case VIDIOCGAUDIO: + { + struct video_audio *va = arg; + + if (desc->flags & CHIP_HAS_VOLUME) { + va->flags |= VIDEO_AUDIO_VOLUME; + va->volume = MAX(chip->left,chip->right); + va->balance = (32768*MIN(chip->left,chip->right))/ + (va->volume ? va->volume : 1); + } + if (desc->flags & CHIP_HAS_BASSTREBLE) { + va->flags |= VIDEO_AUDIO_BASS | VIDEO_AUDIO_TREBLE; + va->bass = chip->bass; + va->treble = chip->treble; + } + if (desc->getmode) + va->mode = desc->getmode(chip); + else + va->mode = VIDEO_SOUND_MONO; + break; + } + + case VIDIOCSAUDIO: + { + struct video_audio *va = arg; + + if (desc->flags & CHIP_HAS_VOLUME) { + chip->left = (MIN(65536 - va->balance,32768) * + va->volume) / 32768; + chip->right = (MIN(va->balance,32768) * + va->volume) / 32768; + chip_write(chip,desc->leftreg,desc->volfunc(chip->left)); + chip_write(chip,desc->rightreg,desc->volfunc(chip->right)); + } + if (desc->flags & CHIP_HAS_BASSTREBLE) { + chip->bass = va->bass; + chip->treble = va->treble; + chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass)); + chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble)); + } + if (desc->setmode && va->mode) + desc->setmode(chip,va->mode); + break; + } + case VIDIOCSFREQ: + { + if (desc->checkmode) { + desc->setmode(chip,VIDEO_SOUND_MONO); + chip->wake++; + wake_up_interruptible(&chip->wq); + /* the thread will call checkmode() a second later */ + } + } + } + return 0; +} + + +static struct i2c_driver driver = { + name: "generic i2c audio driver", + id: I2C_DRIVERID_TVAUDIO, /* FIXME */ + flags: I2C_DF_NOTIFY, + attach_adapter: chip_probe, + detach_client: chip_detach, + command: chip_command, +}; + +static struct i2c_client client_template = +{ + name: "(unset)", + driver: &driver, +}; + +int audiochip_init_module(void) +{ + struct CHIPDESC *desc; + printk(KERN_INFO "tvaudio: TV audio decoder + audio/video mux driver\n"); + printk(KERN_INFO "tvaudio: known chips: "); + for (desc = chiplist; desc->name != NULL; desc++) + printk("%s%s", (desc == chiplist) ? "" : ",",desc->name); + printk("\n"); + i2c_add_driver(&driver); + return 0; +} + +void audiochip_cleanup_module(void) +{ + i2c_del_driver(&driver); +} + +module_init(audiochip_init_module); +module_exit(audiochip_cleanup_module); + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tvaudio.h linux/drivers/media/video/tvaudio.h --- v2.4.0-test10/linux/drivers/media/video/tvaudio.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/media/video/tvaudio.h Sun Nov 12 20:47:19 2000 @@ -0,0 +1,13 @@ +/* + * i2c bus addresses for the chips supported by tvaudio.c + */ + +#define I2C_TDA8425 0x82 +#define I2C_TDA9840 0x84 +#define I2C_TDA985x_L 0xb4 /* also used by 9873 */ +#define I2C_TDA985x_H 0xb6 + +#define I2C_TEA6300 0x80 +#define I2C_TEA6420 0x98 + +#define I2C_PIC16C54 0x96 /* PV951 */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/tvmixer.c linux/drivers/media/video/tvmixer.c --- v2.4.0-test10/linux/drivers/media/video/tvmixer.c Tue Jul 18 22:35:33 2000 +++ linux/drivers/media/video/tvmixer.c Sun Nov 12 20:47:19 2000 @@ -16,6 +16,7 @@ #include #include "audiochip.h" +#include "id.h" #define DEV_MAX 4 @@ -45,11 +46,11 @@ static struct i2c_driver driver = { - "tv card mixer driver", - 42 /* I2C_DRIVERID_FIXME */, - I2C_DF_DUMMY, - tvmixer_adapters, - tvmixer_clients, + name: "tv card mixer driver", + id: I2C_DRIVERID_TVMIXER, + flags: I2C_DF_DUMMY, + attach_adapter: tvmixer_adapters, + detach_client: tvmixer_clients, }; static struct file_operations tvmixer_fops = { @@ -241,6 +242,15 @@ static int tvmixer_adapters(struct i2c_adapter *adap) { + int i; + + if (debug) + printk("tvmixer: adapter %s\n",adap->name); + for (i=0; iclients[i]) + continue; + tvmixer_clients(adap->clients[i]); + } return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/vino.c linux/drivers/media/video/vino.c --- v2.4.0-test10/linux/drivers/media/video/vino.c Fri Feb 25 10:26:42 2000 +++ linux/drivers/media/video/vino.c Fri Nov 17 17:56:51 2000 @@ -224,20 +224,13 @@ } static struct video_device vino_dev = { - "Vino IndyCam/TV", - VID_TYPE_CAPTURE, - VID_HARDWARE_VINO, - vino_open, - vino_close, - NULL, /* vino_read */ - NULL, /* vino_write */ - NULL, /* vino_poll */ - vino_ioctl, - vino_mmap, - NULL, /* vino_init */ - NULL, - 0, - 0 + name: "Vino IndyCam/TV", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_VINO, + open: vino_open, + close: vino_close, + ioctl: vino_ioctl, + mmap: vino_mmap, }; int __init init_vino(struct video_device *dev) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c --- v2.4.0-test10/linux/drivers/media/video/zr36120.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/media/video/zr36120.c Fri Nov 17 17:56:52 2000 @@ -1482,23 +1482,17 @@ static struct video_device zr36120_template= { - "UNSET", - VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, - VID_HARDWARE_ZR36120, - - zoran_open, - zoran_close, - zoran_read, - zoran_write, -#if LINUX_VERSION_CODE >= 0x020100 - zoran_poll, /* poll */ -#endif - zoran_ioctl, - zoran_mmap, - NULL, /* initialize */ - NULL, - 0, - -1 + name: "UNSET", + type: VID_TYPE_TUNER|VID_TYPE_CAPTURE|VID_TYPE_OVERLAY, + hardware: VID_HARDWARE_ZR36120, + open: zoran_open, + close: zoran_close, + read: zoran_read, + write: zoran_write, + poll: zoran_poll, + ioctl: zoran_ioctl, + mmap: zoran_mmap, + minor: -1, }; static @@ -1825,23 +1819,16 @@ static struct video_device vbi_template= { - "UNSET", - VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, - VID_HARDWARE_ZR36120, - - vbi_open, - vbi_close, - vbi_read, - zoran_write, -#if LINUX_VERSION_CODE >= 0x020100 - vbi_poll, /* poll */ -#endif - vbi_ioctl, - NULL, /* no mmap */ - NULL, /* no initialize */ - NULL, /* priv */ - 0, /* busy */ - -1 /* minor */ + name: "UNSET", + type: VID_TYPE_CAPTURE|VID_TYPE_TELETEXT, + hardware: VID_HARDWARE_ZR36120, + open: vbi_open, + close: vbi_close, + read: vbi_read, + write: zoran_write, + poll: vbi_poll, + ioctl: vbi_ioctl, + minor: -1, }; /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/Makefile linux/drivers/mtd/Makefile --- v2.4.0-test10/linux/drivers/mtd/Makefile Sun Aug 6 11:23:40 2000 +++ linux/drivers/mtd/Makefile Tue Nov 7 10:46:04 2000 @@ -44,7 +44,7 @@ ALL_SUB_DIRS := MOD_SUB_DIRS := -export-objs := mtdcore.o doc2000.o doc2001.o cfi_probe.o cfi_cmdset_0001.o cfi_cmdset_0002.o +export-objs := mtdcore.o list-multi := # MTD devices diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/cfi_cmdset_0001.c linux/drivers/mtd/cfi_cmdset_0001.c --- v2.4.0-test10/linux/drivers/mtd/cfi_cmdset_0001.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/cfi_cmdset_0001.c Wed Nov 15 00:41:03 2000 @@ -32,12 +32,20 @@ static void cfi_intelext_destroy(struct mtd_info *); -void cfi_cmdset_0001(struct map_info *, int, unsigned long); -EXPORT_SYMBOL(cfi_cmdset_0001); +static void cfi_cmdset_0001(struct map_info *, int, unsigned long); -struct mtd_info *cfi_intelext_setup (struct map_info *); +static struct mtd_info *cfi_intelext_setup (struct map_info *); -void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) +static const char im_name[] = "cfi_cmdset_0001"; + +/* 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 cfi 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. + */ +static void cfi_cmdset_0001(struct map_info *map, int primary, unsigned long base) { struct cfi_private *cfi = map->fldrv_priv; int i; @@ -144,7 +152,7 @@ /* If there was an old setup function, decrease its use count */ if (cfi->cmdset_setup) - put_module_symbol((unsigned long)cfi->cmdset_setup); + inter_module_put(cfi->im_name); if (cfi->cmdset_priv) kfree(cfi->cmdset_priv); @@ -156,14 +164,13 @@ cfi->cmdset_setup = cfi_intelext_setup; + cfi->im_name = im_name; cfi->cmdset_priv = extp; - MOD_INC_USE_COUNT; /* So the setup function is still there - * by the time it's called */ return; } -struct mtd_info *cfi_intelext_setup(struct map_info *map) +static struct mtd_info *cfi_intelext_setup(struct map_info *map) { struct cfi_private *cfi = map->fldrv_priv; struct mtd_info *mtd; @@ -763,6 +770,8 @@ spin_unlock_bh(chip->mutex); schedule(); + remove_wait_queue(&chip->wq, &wait); + goto retry; } } @@ -862,6 +871,21 @@ struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; kfree(cfi->cmdset_priv); + inter_module_put(cfi->im_name); kfree(cfi); } + +static int __init cfi_intelext_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0001); + return 0; +} + +static void __exit cfi_intelext_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_intelext_init); +module_exit(cfi_intelext_exit); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/cfi_cmdset_0002.c linux/drivers/mtd/cfi_cmdset_0002.c --- v2.4.0-test10/linux/drivers/mtd/cfi_cmdset_0002.c Sun Oct 8 10:50:18 2000 +++ linux/drivers/mtd/cfi_cmdset_0002.c Wed Nov 15 00:41:03 2000 @@ -36,12 +36,13 @@ static void cfi_amdext_destroy(struct mtd_info *); -void cfi_cmdset_0002(struct map_info *, int, unsigned long); -EXPORT_SYMBOL(cfi_cmdset_0002); +static void cfi_cmdset_0002(struct map_info *, int, unsigned long); -struct mtd_info *cfi_amdext_setup (struct map_info *); +static struct mtd_info *cfi_amdext_setup (struct map_info *); -void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) +static const char im_name[] = "cfi_cmdset_0002"; + +static void cfi_cmdset_0002(struct map_info *map, int primary, unsigned long base) { struct cfi_private *cfi = map->fldrv_priv; int i; @@ -54,7 +55,7 @@ /* If there was an old setup function, decrease its use count */ if (cfi->cmdset_setup) - put_module_symbol((unsigned long)cfi->cmdset_setup); + inter_module_put(cfi->im_name); if (cfi->cmdset_priv) kfree(cfi->cmdset_priv); @@ -66,14 +67,13 @@ cfi->cmdset_setup = cfi_amdext_setup; + cfi->im_name = im_name; // cfi->cmdset_priv = extp; - MOD_INC_USE_COUNT; /* So the setup function is still there - * by the time it's called */ return; } -struct mtd_info *cfi_amdext_setup(struct map_info *map) +static struct mtd_info *cfi_amdext_setup(struct map_info *map) { struct cfi_private *cfi = map->fldrv_priv; struct mtd_info *mtd; @@ -501,8 +501,11 @@ add_wait_queue(&chip->wq, &wait); spin_unlock_bh(chip->mutex); + schedule(); + remove_wait_queue(&chip->wq, &wait); + goto retry; } } @@ -605,6 +608,21 @@ struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; kfree(cfi->cmdset_priv); + inter_module_put(cfi->im_name); kfree(cfi); } + +static int __init cfi_amdext_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0002); + return 0; +} + +static void __exit cfi_amdext_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_amdext_init); +module_exit(cfi_amdext_exit); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/cfi_probe.c linux/drivers/mtd/cfi_probe.c --- v2.4.0-test10/linux/drivers/mtd/cfi_probe.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/cfi_probe.c Tue Nov 7 10:46:04 2000 @@ -17,14 +17,22 @@ #include -struct mtd_info *cfi_probe(struct map_info *); -EXPORT_SYMBOL(cfi_probe); +static struct mtd_info *cfi_probe(struct map_info *); static void print_cfi_ident(struct cfi_ident *); static void check_cmd_set(struct map_info *, int, unsigned long); static struct cfi_private *cfi_cfi_probe(struct map_info *); -struct mtd_info *cfi_probe(struct map_info *map) +static const char im_name[] = "cfi_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. + */ +static struct mtd_info *cfi_probe(struct map_info *map) { struct mtd_info *mtd = NULL; struct cfi_private *cfi; @@ -35,13 +43,14 @@ return NULL; map->fldrv_priv = cfi; + map->im_name = im_name; /* OK we liked it. Now find a driver for the command set it talks */ check_cmd_set(map, 1, cfi->chips[0].start); /* First the primary cmdset */ check_cmd_set(map, 0, cfi->chips[0].start); /* Then the secondary */ - /* check_cmd_set() will have used get_module_symbol to increase + /* check_cmd_set() will have used inter_module_get to increase the use count of the module which provides the command set driver. If we're quitting, we have to decrease it again. */ @@ -51,7 +60,7 @@ if (mtd) return mtd; - put_module_symbol((unsigned long)cfi->cmdset_setup); + inter_module_put(cfi->im_name); } printk("No supported Vendor Command Set found\n"); @@ -239,7 +248,7 @@ } } default: - printk(KERN_WARNING "cfi_cfi_probe called with strange buswidth %d\n", map->buswidth); + printk(KERN_WARNING "cfi_probe called with strange buswidth %d\n", map->buswidth); return 0; } } @@ -465,16 +474,9 @@ sprintf(probename, "cfi_cmdset_%4.4X", type); - probe_function = (void *)get_module_symbol(NULL, probename); - if (!probe_function) { - request_module(probename); - - probe_function = (void *)get_module_symbol(NULL, probename); - } - + probe_function = inter_module_get_request(probename, probename); if (probe_function) { (*probe_function)(map, primary, base); - put_module_symbol((unsigned long)probe_function); return; } @@ -499,3 +501,17 @@ map->read8(map,base+((adr+4)*map->buswidth))); } } + +static int __init cfi_probe_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &cfi_probe); + return 0; +} + +static void __exit cfi_probe_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(cfi_probe_init); +module_exit(cfi_probe_exit); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/doc2000.c linux/drivers/mtd/doc2000.c --- v2.4.0-test10/linux/drivers/mtd/doc2000.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/doc2000.c Tue Nov 7 10:46:04 2000 @@ -392,7 +392,16 @@ } -void DoC2k_init(struct mtd_info *mtd) +static const char im_name[] = "DoC2k_init"; + +/* 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. + */ +static void DoC2k_init(struct mtd_info *mtd) { struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; struct DiskOnChip *old = NULL; @@ -460,8 +469,6 @@ } -EXPORT_SYMBOL(DoC2k_init); - 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 */ @@ -805,6 +812,12 @@ * ****************************************************************************/ +static int __init init_doc2000(void) +{ + inter_module_register(im_name, THIS_MODULE, &DoC2k_init); + return 0; +} + #if LINUX_VERSION_CODE < 0x20300 #ifdef MODULE #define cleanup_doc2000 cleanup_module @@ -828,10 +841,12 @@ kfree(this->chips); kfree(mtd); } + inter_module_unregister(im_name); } +module_init(init_doc2000); + #if LINUX_VERSION_CODE > 0x20300 module_exit(cleanup_doc2000); #endif - diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/doc2001.c linux/drivers/mtd/doc2001.c --- v2.4.0-test10/linux/drivers/mtd/doc2001.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/doc2001.c Tue Nov 7 10:46:04 2000 @@ -321,6 +321,15 @@ return retval; } +static const char im_name[] = "DoCMil_init"; + +/* 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. + */ void DoCMil_init(struct mtd_info *mtd) { struct DiskOnChip *this = (struct DiskOnChip *)mtd->priv; @@ -386,8 +395,6 @@ } } -EXPORT_SYMBOL(DoCMil_init); - static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf) { @@ -780,6 +787,12 @@ * ****************************************************************************/ +static 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 @@ -803,10 +816,12 @@ kfree(this->chips); kfree(mtd); } + inter_module_unregister(im_name); } +module_init(init_doc2001); + #if LINUX_VERSION_CODE > 0x20300 module_exit(cleanup_doc2001); #endif - diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/docprobe.c linux/drivers/mtd/docprobe.c --- v2.4.0-test10/linux/drivers/mtd/docprobe.c Thu Jul 13 10:19:55 2000 +++ linux/drivers/mtd/docprobe.c Sun Nov 12 20:40:42 2000 @@ -26,11 +26,8 @@ #define DOC_PASSIVE_PROBE */ - -#include #include #include -#include #include #include #include @@ -62,12 +59,6 @@ #warning Unknown architecture for DiskOnChip. No default probe locations defined #endif -#ifdef CONFIG_MTD_DOC2000 -extern void DoC2k_init(struct mtd_info *); -#endif -#ifdef CONFIG_MTD_DOC2001 -extern void DoCMil_init(struct mtd_info *); -#endif /* doccheck: Probe a given memory window to see if there's a DiskOnChip present */ @@ -157,8 +148,9 @@ int ChipID; char namebuf[15]; char *name = namebuf; + char *im_funcname = NULL; + char *im_modname = NULL; void (*initroutine)(struct mtd_info *) = NULL; - int initroutinedynamic = 0; docptr = (unsigned long)ioremap(physadr, 0x2000); @@ -189,42 +181,21 @@ switch(ChipID) { case DOC_ChipID_Doc2k: name="2000"; -#ifdef CONFIG_MTD_DOC2000 - initroutine = &DoC2k_init; -#elif CONFIG_MODULES - initroutinedynamic=1; - initroutine = (void *)get_module_symbol(NULL, "DoC2k_init"); -#ifdef CONFIG_KMOD - if (!initroutine) { - request_module("doc2000"); - initroutine = (void *)get_module_symbol("doc2000", "DoC2k_init"); - } -#endif /* CONFIG_KMOD */ -#endif + im_funcname = "DoC2k_init"; + im_modname = "doc2000"; break; case DOC_ChipID_DocMil: name="Millennium"; -#ifdef CONFIG_MTD_DOC2001 - initroutine = &DoCMil_init; -#elif CONFIG_MODULES - initroutinedynamic=1; - initroutine = (void *)get_module_symbol(NULL, "DoCMil_init"); -#ifdef CONFIG_KMOD - if (!initroutine) { - request_module("doc2001"); - initroutine = (void *)get_module_symbol("doc2001", "DoCMil_init"); - } -#endif /* CONFIG_KMOD */ -#endif + im_funcname = "DoCMil_init"; + im_modname = "doc2001"; break; } + if (im_funcname) + initroutine = inter_module_get_request(im_funcname, im_modname); if (initroutine) { (*initroutine)(mtd); -#if defined(CONFIG_MODULES) && LINUX_VERSION_CODE >= 0x20400 - if (initroutinedynamic) - put_module_symbol(initroutine); -#endif + inter_module_put(im_funcname); return; } printk("Cannot find driver for DiskOnChip %s at 0x%X\n", name, physadr); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/mtd/map_ram.c linux/drivers/mtd/map_ram.c --- v2.4.0-test10/linux/drivers/mtd/map_ram.c Tue Jul 4 10:10:05 2000 +++ linux/drivers/mtd/map_ram.c Tue Nov 7 10:46:04 2000 @@ -20,10 +20,16 @@ static int mapram_erase (struct mtd_info *, struct erase_info *); static void mapram_nop (struct mtd_info *); -struct mtd_info *map_ram_probe(struct map_info *); -EXPORT_SYMBOL(map_ram_probe); +static const char im_name[] = "map_ram_probe"; -struct mtd_info *map_ram_probe(struct map_info *map) +/* 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. + */ +static struct mtd_info *map_ram_probe(struct map_info *map) { struct mtd_info *mtd; @@ -63,9 +69,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; - MOD_INC_USE_COUNT; return mtd; } @@ -108,3 +114,17 @@ { /* Nothing to see here */ } + +static int __init map_ram_init(void) +{ + inter_module_register(im_name, THIS_MODULE, &map_ram_probe); + return 0; +} + +static void __exit map_ram_exit(void) +{ + inter_module_unregister(im_name); +} + +module_init(map_ram_init); +module_exit(map_ram_exit); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c501.c linux/drivers/net/3c501.c --- v2.4.0-test10/linux/drivers/net/3c501.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c501.c Tue Nov 14 13:16:37 2000 @@ -234,7 +234,9 @@ int __init el1_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 el1_probe1(dev, base_addr); @@ -398,19 +400,16 @@ static int el_open(struct net_device *dev) { + int retval; int ioaddr = dev->base_addr; struct net_local *lp = (struct net_local *)dev->priv; unsigned long flags; - MOD_INC_USE_COUNT; - if (el_debug > 2) printk("%s: Doing el_open()...", dev->name); - if (request_irq(dev->irq, &el_interrupt, 0, "3c501", dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + if ((retval = request_irq(dev->irq, &el_interrupt, 0, dev->name, dev))) + return retval; spin_lock_irqsave(&lp->lock, flags); el_reset(dev); @@ -862,7 +861,6 @@ free_irq(dev->irq, dev); outb(AX_RESET, AX_CMD); /* Reset the chip */ - MOD_DEC_USE_COUNT; return 0; } @@ -916,12 +914,10 @@ #ifdef MODULE -static struct net_device dev_3c501 = -{ - "", /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0x280, 5, - 0, 0, 0, NULL, el1_probe +static struct net_device dev_3c501 = { + init: el1_probe, + base_addr: 0x280, + irq: 5, }; static int io=0x280; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c503.c linux/drivers/net/3c503.c --- v2.4.0-test10/linux/drivers/net/3c503.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c503.c Tue Nov 14 13:16:37 2000 @@ -87,6 +87,8 @@ int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0}; 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. */ @@ -101,8 +103,6 @@ break; if (base_bits != 1) continue; - if (check_region(netcard_portlist[i], EL2_IO_EXTENT)) - continue; if (el2_probe1(dev, netcard_portlist[i]) == 0) return 0; } @@ -126,13 +126,9 @@ else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; netcard_portlist[i]; i++) { - int ioaddr = netcard_portlist[i]; - if (check_region(ioaddr, EL2_IO_EXTENT)) - continue; - if (el2_probe1(dev, ioaddr) == 0) + for (i = 0; netcard_portlist[i]; i++) + if (el2_probe1(dev, netcard_portlist[i]) == 0) return 0; - } return -ENODEV; } @@ -143,14 +139,18 @@ int __init el2_probe1(struct net_device *dev, int ioaddr) { - int i, iobase_reg, membase_reg, saved_406, wordlength; - static unsigned version_printed = 0; + int i, iobase_reg, membase_reg, saved_406, wordlength, retval; + static unsigned version_printed; unsigned long vendor_id; + if (!request_region(ioaddr, EL2_IO_EXTENT, dev->name)) + return -EBUSY; + /* Reset and/or avoid any lurking NE2000 */ if (inb(ioaddr + 0x408) == 0xff) { mdelay(1); - return -ENODEV; + retval = -ENODEV; + goto out; } /* We verify that it's a 3C503 board by checking the first three octets @@ -160,7 +160,8 @@ /* ASIC location registers should be 0 or have only a single bit set. */ if ( (iobase_reg & (iobase_reg - 1)) || (membase_reg & (membase_reg - 1))) { - return -ENODEV; + retval = -ENODEV; + goto out; } saved_406 = inb_p(ioaddr + 0x406); outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ @@ -172,7 +173,8 @@ if ((vendor_id != OLD_3COM_ID) && (vendor_id != NEW_3COM_ID)) { /* Restore the register we frobbed. */ outb(saved_406, ioaddr + 0x406); - return -ENODEV; + retval = -ENODEV; + goto out; } if (ei_debug && version_printed++ == 0) @@ -182,8 +184,9 @@ /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk ("3c503: unable to allocate memory for dev->priv.\n"); - return -ENOMEM; - } + retval = -ENOMEM; + goto out; + } printk("%s: 3c503 at i/o base %#3x, node ", dev->name, ioaddr); @@ -282,8 +285,6 @@ ei_status.block_input = &el2_block_input; ei_status.block_output = &el2_block_output; - request_region(ioaddr, EL2_IO_EXTENT, ei_status.name); - if (dev->irq == 2) dev->irq = 9; else if (dev->irq > 5 && dev->irq != 9) { @@ -310,6 +311,9 @@ dev->name, ei_status.name, (wordlength+1)<<3); } return 0; +out: + release_region(ioaddr, EL2_IO_EXTENT); + return retval; } static int @@ -324,10 +328,10 @@ do { if (request_irq (*irqp, NULL, 0, "bogus", dev) != -EBUSY) { /* Twinkle the interrupt, and check if it's seen. */ - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR); outb_p(0x00, E33G_IDCFR); - if (*irqp == autoirq_report(0) /* It's a good IRQ line! */ + 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) break; } @@ -344,7 +348,6 @@ el2_init_card(dev); ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -356,7 +359,6 @@ outb(EGACFR_IRQOFF, E33G_GACFR); /* disable interrupts. */ ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } @@ -602,18 +604,10 @@ #ifdef MODULE #define MAX_EL2_CARDS 4 /* Max number of EL2 cards per module */ -static struct net_device dev_el2[MAX_EL2_CARDS] = { - { - "", - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, NULL - }, -}; - -static int io[MAX_EL2_CARDS] = { 0, }; -static int irq[MAX_EL2_CARDS] = { 0, }; -static int xcvr[MAX_EL2_CARDS] = { 0, }; /* choose int. or ext. xcvr */ +static struct net_device dev_el2[MAX_EL2_CARDS]; +static int io[MAX_EL2_CARDS]; +static int irq[MAX_EL2_CARDS]; +static int xcvr[MAX_EL2_CARDS]; /* choose int. or ext. xcvr */ MODULE_PARM(io, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i"); MODULE_PARM(xcvr, "1-" __MODULE_STRING(MAX_EL2_CARDS) "i"); @@ -625,9 +619,6 @@ { int this_dev, found = 0; - if (load_8390_module("3c503.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_EL2_CARDS; this_dev++) { struct net_device *dev = &dev_el2[this_dev]; dev->irq = irq[this_dev]; @@ -643,7 +634,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -666,7 +656,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c505.c linux/drivers/net/3c505.c --- v2.4.0-test10/linux/drivers/net/3c505.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c505.c Tue Nov 14 13:16:37 2000 @@ -854,6 +854,7 @@ static int elp_open(struct net_device *dev) { elp_device *adapter; + int retval; adapter = dev->priv; @@ -893,16 +894,21 @@ /* * install our interrupt service routine */ - if (request_irq(dev->irq, &elp_interrupt, 0, "3c505", dev)) { - return -EAGAIN; - } - if (request_dma(dev->dma, "3c505")) { - printk("%s: could not allocate DMA channel\n", dev->name); - return -EAGAIN; + if ((retval = request_irq(dev->irq, &elp_interrupt, 0, dev->name, dev))) { + printk(KERN_ERR "%s: could not allocate IRQ%d\n", dev->name, dev->irq); + return retval; + } + if ((retval = request_dma(dev->dma, dev->name))) { + free_irq(dev->irq, dev); + printk(KERN_ERR "%s: could not allocate DMA%d channel\n", dev->name, dev->dma); + return retval; } adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE); if (!adapter->dma_buffer) { - printk("Could not allocate DMA buffer\n"); + printk(KERN_ERR "%s: could not allocate DMA buffer\n", dev->name); + free_dma(dev->dma); + free_irq(dev->irq, dev); + return -ENOMEM; } adapter->dmaing = 0; @@ -915,7 +921,7 @@ * configure adapter memory: we need 10 multicast addresses, default==0 */ if (elp_debug >= 3) - printk("%s: sending 3c505 memory configuration command\n", dev->name); + printk(KERN_DEBUG "%s: sending 3c505 memory configuration command\n", dev->name); adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY; adapter->tx_pcb.data.memconf.cmd_q = 10; adapter->tx_pcb.data.memconf.rcv_q = 20; @@ -967,10 +973,8 @@ * device is now officially open! */ - netif_wake_queue(dev); - MOD_INC_USE_COUNT; - - return 0; /* Always succeed */ + netif_start_queue(dev); + return 0; } @@ -1178,8 +1182,6 @@ free_dma(dev->dma); free_pages((unsigned long) adapter->dma_buffer, get_order(DMA_BUFFER_SIZE)); - MOD_DEC_USE_COUNT; - return 0; } @@ -1412,6 +1414,9 @@ { elp_device *adapter; int i, tries, tries1, timeout, okay; + unsigned long cookie = 0; + + SET_MODULE_OWNER(dev); /* * setup adapter structure @@ -1479,21 +1484,21 @@ */ adapter->tx_pcb.command = CMD_STATION_ADDRESS; adapter->tx_pcb.length = 0; - autoirq_setup(0); + cookie = probe_irq_on(); if (!send_pcb(dev, &adapter->tx_pcb)) { printk("%s: could not send first PCB\n", dev->name); - autoirq_report(0); + probe_irq_off(cookie); continue; } if (!receive_pcb(dev, &adapter->rx_pcb)) { printk("%s: could not read first PCB\n", dev->name); - autoirq_report(0); + probe_irq_off(cookie); continue; } if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) || (adapter->rx_pcb.length != 6)) { printk("%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length); - autoirq_report(0); + probe_irq_off(cookie); continue; } goto okay; @@ -1511,13 +1516,13 @@ okay: if (dev->irq) { /* Is there a preset IRQ? */ - int rpt = autoirq_report(0); + int rpt = probe_irq_off(cookie); if (dev->irq != rpt) { printk("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt); } - /* if dev->irq == autoirq_report(0), all is well */ + /* if dev->irq == probe_irq_off(cookie), all is well */ } else /* No preset IRQ; just use what we can detect */ - dev->irq = autoirq_report(0); + dev->irq = probe_irq_off(cookie); switch (dev->irq) { /* Legal, sane? */ case 0: printk("%s: IRQ probe failed: check 3c505 jumpers.\n", @@ -1527,7 +1532,7 @@ case 6: case 8: case 13: - printk("%s: Impossible IRQ %d reported by autoirq_report().\n", + printk("%s: Impossible IRQ %d reported by probe_irq_off().\n", dev->name, dev->irq); return -ENODEV; } @@ -1607,17 +1612,10 @@ } #ifdef MODULE -static struct net_device dev_3c505[ELP_MAX_CARDS] = -{ - { "", /* device name is inserted by net_init.c */ - 0, 0, 0, 0, - 0, 0, - 0, 0, 0, NULL, elplus_probe}, -}; - -static int io[ELP_MAX_CARDS] = { 0, }; -static int irq[ELP_MAX_CARDS] = { 0, }; -static int dma[ELP_MAX_CARDS] = { 0, }; +static struct net_device dev_3c505[ELP_MAX_CARDS]; +static int io[ELP_MAX_CARDS]; +static int irq[ELP_MAX_CARDS]; +static int dma[ELP_MAX_CARDS]; MODULE_PARM(io, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i"); MODULE_PARM(irq, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i"); MODULE_PARM(dma, "1-" __MODULE_STRING(ELP_MAX_CARDS) "i"); @@ -1630,6 +1628,7 @@ struct net_device *dev = &dev_3c505[this_dev]; dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; + dev->init = elplus_probe; if (dma[this_dev]) { dev->dma = dma[this_dev]; } else { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c507.c linux/drivers/net/3c507.c --- v2.4.0-test10/linux/drivers/net/3c507.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c507.c Tue Nov 14 13:16:37 2000 @@ -304,9 +304,11 @@ int __init el16_probe(struct net_device *dev) { - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; int i; + SET_MODULE_OWNER(dev); + if (base_addr > 0x1ff) /* Check a single specified location. */ return el16_probe1(dev, base_addr); else if (base_addr != 0) @@ -339,7 +341,7 @@ init_ID_done = 1; } - if (!request_region(ioaddr, EL16_IO_EXTENT, "3c507")) + if (!request_region(ioaddr, EL16_IO_EXTENT, dev->name)) return -ENODEV; if ((inb(ioaddr) != '*') || (inb(ioaddr + 1) != '3') || @@ -358,7 +360,7 @@ irq = inb(ioaddr + IRQ_CONFIG) & 0x0f; - irqval = request_irq(irq, &el16_interrupt, 0, "3c507", dev); + irqval = request_irq(irq, &el16_interrupt, 0, dev->name, dev); if (irqval) { printk ("unable to get IRQ %d (irqval=%d).\n", irq, irqval); retval = -EAGAIN; @@ -439,9 +441,6 @@ init_82586_mem(dev); netif_start_queue(dev); - - MOD_INC_USE_COUNT; - return 0; } @@ -624,8 +623,6 @@ /* Update the statistics here. */ - MOD_DEC_USE_COUNT; - return 0; } @@ -857,8 +854,7 @@ lp->rx_tail = rx_tail; } #ifdef MODULE -static struct net_device dev_3c507 = { init: el16_probe }; - +static struct net_device dev_3c507; static int io = 0x300; static int irq = 0; MODULE_PARM(io, "i"); @@ -870,6 +866,7 @@ printk("3c507: You should not use auto-probing with insmod!\n"); dev_3c507.base_addr = io; dev_3c507.irq = irq; + dev_3c507.init = el16_probe; if (register_netdev(&dev_3c507) != 0) { printk("3c507: register_netdev() returned non-zero.\n"); return -EIO; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c509.c linux/drivers/net/3c509.c --- v2.4.0-test10/linux/drivers/net/3c509.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c509.c Tue Nov 14 13:16:37 2000 @@ -200,6 +200,8 @@ static int pnp_cards = 0; #endif /* __ISAPNP__ */ + if (dev) SET_MODULE_OWNER(dev); + /* First check all slots of the EISA bus. The next slot address to probe is kept in 'eisa_addr' to support multiple probe() calls. */ if (EISA_bus) { @@ -434,6 +436,14 @@ /* Free the interrupt so that some other card can use it. */ outw(0x0f00, ioaddr + WN0_IRQ); found: + if (dev == NULL) { + dev = init_etherdev(dev, sizeof(struct el3_private)); + if (dev == NULL) { + release_region(ioaddr, EL3_IO_EXTENT); + return -ENOMEM; + } + SET_MODULE_OWNER(dev); + } memcpy(dev->dev_addr, phys_addr, sizeof(phys_addr)); dev->base_addr = ioaddr; dev->irq = irq; @@ -523,9 +533,8 @@ outw(RxReset, ioaddr + EL3_CMD); outw(SetStatusEnb | 0x00, ioaddr + EL3_CMD); - if (request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev)) { - return -EAGAIN; - } + i = request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev); + if (i) return i; EL3WINDOW(0); if (el3_debug > 3) @@ -584,8 +593,7 @@ printk("%s: Opened 3c509 IRQ %d status %4.4x.\n", dev->name, dev->irq, inw(ioaddr + EL3_STATUS)); - MOD_INC_USE_COUNT; - return 0; /* Always succeed */ + return 0; } static void @@ -962,7 +970,6 @@ outw(0x0f00, ioaddr + WN0_IRQ); update_stats(dev); - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c515.c linux/drivers/net/3c515.c --- v2.4.0-test10/linux/drivers/net/3c515.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c515.c Tue Nov 14 13:16:37 2000 @@ -428,6 +428,8 @@ { int cards_found = 0; + SET_MODULE_OWNER(dev); + cards_found = corkscrew_scan(dev); if (corkscrew_debug > 0 && cards_found) @@ -561,6 +563,8 @@ sizeof(struct corkscrew_private) + 15; /* Pad for alignment */ dev = (struct net_device *) kmalloc(dev_size, GFP_KERNEL); + if (!dev) + return NULL; memset(dev, 0, dev_size); /* Align the Rx and Tx ring entries. */ dev->priv = @@ -586,15 +590,16 @@ ether_setup(dev); vp->next_module = root_corkscrew_dev; root_corkscrew_dev = dev; - if (register_netdev(dev) != 0) - return 0; -#else /* not a MODULE */ - if (dev) { - /* Caution: quad-word alignment required for rings! */ - dev->priv = - kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL); - memset(dev->priv, 0, sizeof(struct corkscrew_private)); + if (register_netdev(dev) != 0) { + kfree(dev); + return NULL; } + SET_MODULE_OWNER(dev); +#else /* not a MODULE */ + /* Caution: quad-word alignment required for rings! */ + dev->priv = + kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL); + memset(dev->priv, 0, sizeof(struct corkscrew_private)); dev = init_etherdev(dev, sizeof(struct corkscrew_private)); dev->base_addr = ioaddr; dev->irq = irq; @@ -874,8 +879,6 @@ | (vp->bus_master ? DMADone : 0) | UpComplete | DownComplete, ioaddr + EL3_CMD); - MOD_INC_USE_COUNT; - return 0; } @@ -1499,8 +1502,6 @@ vp->tx_skbuff[i] = 0; } } - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c523.c linux/drivers/net/3c523.c --- v2.4.0-test10/linux/drivers/net/3c523.c Tue Jul 18 16:09:27 2000 +++ linux/drivers/net/3c523.c Tue Nov 14 13:16:37 2000 @@ -271,7 +271,6 @@ netif_stop_queue(dev); elmc_id_reset586(); /* the hard way to stop the receiver */ free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; return 0; } @@ -281,21 +280,21 @@ static int elmc_open(struct net_device *dev) { + int ret; elmc_id_attn586(); /* disable interrupts */ - if (request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, - "3c523", dev) - ) { + ret = request_irq(dev->irq, &elmc_interrupt, SA_SHIRQ | SA_SAMPLE_RANDOM, + dev->name, dev); + if (ret) { printk(KERN_ERR "%s: couldn't get irq %d\n", dev->name, dev->irq); elmc_id_reset586(); - return -EAGAIN; + return ret; } alloc586(dev); init586(dev); startrecv586(dev); netif_start_queue(dev); - MOD_INC_USE_COUNT; return 0; /* most done by init */ } @@ -409,13 +408,14 @@ int __init elmc_probe(struct net_device *dev) { static int slot = 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; u_char status = 0; u_char revision = 0; int i = 0; unsigned int size = 0; + SET_MODULE_OWNER(dev); if (MCA_bus == 0) { return -ENODEV; } @@ -1208,15 +1208,9 @@ /* Increase if needed ;) */ #define MAX_3C523_CARDS 4 -static struct net_device dev_elmc[MAX_3C523_CARDS] = -{ - { - "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL - }, -}; - -static int irq[MAX_3C523_CARDS] = {0,}; -static int io[MAX_3C523_CARDS] = {0,}; +static struct net_device dev_elmc[MAX_3C523_CARDS]; +static int irq[MAX_3C523_CARDS]; +static int io[MAX_3C523_CARDS]; MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); MODULE_PARM(io, "1-" __MODULE_STRING(MAX_3C523_CARDS) "i"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c527.c linux/drivers/net/3c527.c --- v2.4.0-test10/linux/drivers/net/3c527.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c527.c Tue Nov 14 13:16:37 2000 @@ -184,6 +184,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 :) */ @@ -347,25 +349,22 @@ * Grab the IRQ */ - if(request_irq(dev->irq, &mc32_interrupt, 0, cardname, dev)) - { - printk("%s: unable to get IRQ %d.\n", - dev->name, dev->irq); - return -EAGAIN; + i = request_irq(dev->irq, &mc32_interrupt, 0, dev->name, dev); + if (i) { + printk("%s: unable to get IRQ %d.\n", dev->name, dev->irq); + return i; } /* Initialize the device structure. */ - if (dev->priv == NULL) { - dev->priv = kmalloc(sizeof(struct mc32_local), GFP_KERNEL); - if (dev->priv == NULL) - { - free_irq(dev->irq, dev); - return -ENOMEM; - } + dev->priv = kmalloc(sizeof(struct mc32_local), GFP_KERNEL); + if (dev->priv == NULL) + { + free_irq(dev->irq, dev); + return -ENOMEM; } memset(dev->priv, 0, sizeof(struct mc32_local)); - lp = (struct mc32_local *)dev->priv; + lp = dev->priv; lp->slot = slot; i=0; @@ -897,8 +896,6 @@ mc32_tx_begin(dev); netif_start_queue(dev); - MOD_INC_USE_COUNT; - return 0; } @@ -1318,8 +1315,6 @@ /* Update the statistics here. */ - MOD_DEC_USE_COUNT; - return 0; } @@ -1444,7 +1439,7 @@ #ifdef MODULE -static struct net_device this_device = { init: mc32_probe }; +static struct net_device this_device; /** @@ -1459,6 +1454,7 @@ { int result; + this_device.init = mc32_probe; if ((result = register_netdev(&this_device)) != 0) return result; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c --- v2.4.0-test10/linux/drivers/net/3c59x.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/3c59x.c Tue Nov 14 11:34:25 2000 @@ -98,7 +98,7 @@ - Added INVERT_LED_PWR, used it. - Backed out the extra_reset stuff - LK1.1.9 2 Sep 2000 andrewm + LK1.1.9 12 Sep 2000 andrewm - Backed out the tx_reset_resume flags. It was a no-op. - In vortex_error, don't reset the Tx on txReclaim errors - In vortex_error, don't reset the Tx on maxCollisions errors. @@ -110,6 +110,14 @@ is downed, it remains set when the interface is upped. Bad things happen. + LK1.1.10 17 Sep 2000 andrewm + - Added EEPROM_8BIT for 3c555 (Fred Maciel) + - Added experimental support for the 3c556B Laptop Hurricane (Louis Gerbarg) + - Add HAS_NWAY to "3c900 Cyclone 10Mbps TPO" + + LK1.1.11 13 Nov 2000 andrewm + - Dump MOD_INC/DEC_USE_COUNT, use SET_MODULE_OWNER + - See http://www.uow.edu.au/~andrewm/linux/#3c59x-2.3 for more details. - Also see Documentation/networking/vortex.txt */ @@ -195,7 +203,7 @@ #include static char version[] __devinitdata = -"3c59x.c:LK1.1.9 2 Sep 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.38 $\n"; +"3c59x.c:LK1.1.11 13 Nov 2000 Donald Becker and others. http://www.scyld.com/network/vortex.html " "$Revision: 1.102.2.46 $\n"; MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("3Com 3c59x/3c90x/3c575 series Vortex/Boomerang/Cyclone driver"); @@ -315,8 +323,8 @@ enum { IS_VORTEX=1, IS_BOOMERANG=2, IS_CYCLONE=4, IS_TORNADO=8, EEPROM_8BIT=0x10, /* AKPM: Uses 0x230 as the base bitmaps for EEPROM reads */ HAS_PWR_CTRL=0x20, HAS_MII=0x40, HAS_NWAY=0x80, HAS_CB_FNS=0x100, - INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800 }; - + INVERT_MII_PWR=0x200, INVERT_LED_PWR=0x400, MAX_COLLISION_RESET=0x800, + EEPROM_OFFSET=0x1000 }; enum vortex_chips { CH_3C590 = 0, @@ -346,15 +354,16 @@ CH_3CSOHO100_TX, CH_3C555, CH_3C556, + CH_3C556B, CH_3C575, - CH_3C575_1, + CH_3C575_1, CH_3CCFE575, CH_3CCFE575CT, CH_3CCFE656, CH_3CCFEM656, - CH_3CCFEM656_1, + CH_3CCFEM656_1, CH_3C450, }; @@ -388,7 +397,7 @@ {"3c900 Boomerang 10Mbps Combo", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG, 64, }, {"3c900 Cyclone 10Mbps TPO", /* AKPM: from Don's 0.99M */ - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY, 128, }, {"3c900 Cyclone 10Mbps Combo", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, @@ -417,14 +426,16 @@ {"3cSOHO100-TX Hurricane", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, {"3c555 Laptop Hurricane", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE, 128, }, - {"3c556 10/100 Mini PCI Adapter", - PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR, 128, }, + PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|EEPROM_8BIT, 128, }, + {"3c556 Laptop Tornado", + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_8BIT|HAS_CB_FNS|INVERT_MII_PWR, 128, }, + {"3c556B Laptop Hurricane", + PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|EEPROM_OFFSET|HAS_CB_FNS|INVERT_MII_PWR, 128, }, {"3c575 [Megahertz] 10/100 LAN CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, + {"3c575 Boomerang CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_BOOMERANG|HAS_MII|EEPROM_8BIT, 128, }, - {"3CCFE575BT Cyclone CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_LED_PWR, 128, }, {"3CCFE575CT Tornado CardBus", @@ -433,9 +444,9 @@ PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|INVERT_LED_PWR, 128, }, {"3CCFEM656B Cyclone+Winmodem CardBus", PCI_USES_IO|PCI_USES_MASTER, IS_CYCLONE|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|INVERT_LED_PWR, 128, }, + {"3CXFEM656C Tornado+Winmodem CardBus", /* From pcmcia-cs-3.1.5 */ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY|HAS_CB_FNS|EEPROM_8BIT|INVERT_MII_PWR|MAX_COLLISION_RESET, 128, }, - {"3c450 HomePNA Tornado", /* AKPM: from Don's 0.99Q */ PCI_USES_IO|PCI_USES_MASTER, IS_TORNADO|HAS_NWAY, 128, }, {0,}, /* 0 terminated list. */ @@ -470,15 +481,16 @@ { 0x10B7, 0x7646, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CSOHO100_TX }, { 0x10B7, 0x5055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C555 }, { 0x10B7, 0x6055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556 }, + { 0x10B7, 0x6056, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C556B }, { 0x10B7, 0x5b57, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575 }, - { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 }, + { 0x10B7, 0x5057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C575_1 }, { 0x10B7, 0x5157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575 }, { 0x10B7, 0x5257, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE575CT }, { 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 }, { 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 }, - { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 }, + { 0x10B7, 0x6564, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656_1 }, { 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 }, {0,} /* 0 terminated list. */ }; @@ -869,7 +881,8 @@ retval = -ENOMEM; goto out; } - + SET_MODULE_OWNER(dev); + printk(KERN_INFO "%s: 3Com %s %s at 0x%lx, ", dev->name, pdev ? "PCI" : "EISA", @@ -963,7 +976,15 @@ /* Read the station address from the EEPROM. */ EL3WINDOW(0); { - int base = (vci->drv_flags & EEPROM_8BIT) ? 0x230 : EEPROM_Read; + int base; + + if (vci->drv_flags & EEPROM_8BIT) + base = 0x230; + else if (vci->drv_flags & EEPROM_OFFSET) + base = EEPROM_Read + 0x30; + else + base = EEPROM_Read; + for (i = 0; i < 0x40; i++) { int timer; outw(base + i, ioaddr + Wn0EepromCmd); @@ -1338,8 +1359,6 @@ int i; int retval; - MOD_INC_USE_COUNT; - /* Use the now-standard shared IRQ implementation. */ if ((retval = request_irq(dev->irq, vp->full_bus_master_rx ? &boomerang_interrupt : &vortex_interrupt, SA_SHIRQ, dev->name, dev))) { @@ -1388,7 +1407,6 @@ out: if (vortex_debug > 1) printk(KERN_ERR "%s: vortex_open() fails: returning %d\n", dev->name, retval); - MOD_DEC_USE_COUNT; return retval; } @@ -2265,7 +2283,6 @@ } } - MOD_DEC_USE_COUNT; vp->open = 0; return 0; } @@ -2550,7 +2567,6 @@ vp = (void *)(dev->priv); - /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ /* AKPM: FIXME: we should have * if (vp->cb_fn_base) iounmap(vp->cb_fn_base); * here diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/8139too.c linux/drivers/net/8139too.c --- v2.4.0-test10/linux/drivers/net/8139too.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/8139too.c Wed Nov 8 19:12:24 2000 @@ -72,7 +72,7 @@ Jean-Jacques Michel - bug fix - Tobias - Rx interrupt status checking suggestion + Tobias Ringström - Rx interrupt status checking suggestion Submitting bug reports: diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/82596.c linux/drivers/net/82596.c --- v2.4.0-test10/linux/drivers/net/82596.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/82596.c Tue Nov 14 11:24:14 2000 @@ -1092,7 +1092,7 @@ { int i; struct i596_private *lp; - char eth_addr[6]; + char eth_addr[8]; static int probed = 0; if (probed) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/Config.in linux/drivers/net/Config.in --- v2.4.0-test10/linux/drivers/net/Config.in Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/Config.in Thu Nov 16 12:51:28 2000 @@ -60,23 +60,23 @@ fi bool ' 3COM cards' CONFIG_NET_VENDOR_3COM if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then - tristate ' 3c501 "EtherLink" support' CONFIG_EL1 - tristate ' 3c503 "EtherLink II" support' CONFIG_EL2 - tristate ' 3c505 "EtherLink Plus" support' CONFIG_ELPLUS - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' 3c507 "EtherLink 16" support (EXPERIMENTAL)' CONFIG_EL16 + dep_tristate ' 3c501 "EtherLink" support' CONFIG_EL1 $CONFIG_ISA + dep_tristate ' 3c503 "EtherLink II" support' CONFIG_EL2 $CONFIG_ISA + dep_tristate ' 3c505 "EtherLink Plus" support' CONFIG_ELPLUS $CONFIG_ISA + dep_tristate ' 3c507 "EtherLink 16" support (EXPERIMENTAL)' CONFIG_EL16 $CONFIG_ISA $CONFIG_EXPERIMENTAL + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_MCA" = "y" ]; then + tristate ' 3c509/3c529 (MCA)/3c579 "EtherLink III" support' CONFIG_EL3 + fi + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" ]; then + tristate ' 3c515 ISA "Fast EtherLink"' CONFIG_3C515 + fi + dep_tristate ' 3c523 "EtherLink/MC" support' CONFIG_ELMC $CONFIG_MCA + dep_tristate ' 3c527 "EtherLink/MC 32" support (EXPERIMENTAL)' CONFIG_ELMC_II $CONFIG_MCA $CONFIG_EXPERIMENTAL + if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then + tristate ' 3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX fi - tristate ' 3c509/3c529 (MCA)/3c579 "EtherLink III" support' CONFIG_EL3 - tristate ' 3c515 ISA "Fast EtherLink"' CONFIG_3C515 - if [ "$CONFIG_MCA" = "y" ]; then - tristate ' 3c523 "EtherLink/MC" support' CONFIG_ELMC - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' 3c527 "EtherLink/MC 32" support (EXPERIMENTAL)' CONFIG_ELMC_II - fi - fi - tristate ' 3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX fi - tristate ' AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE + dep_tristate ' AMD LANCE and PCnet (AT1500 and NE2100) support' CONFIG_LANCE $CONFIG_ISA bool ' Western Digital/SMC cards' CONFIG_NET_VENDOR_SMC if [ "$CONFIG_NET_VENDOR_SMC" = "y" ]; then tristate ' WD80*3 support' CONFIG_WD80x3 @@ -84,23 +84,23 @@ tristate ' SMC Ultra MCA support' CONFIG_ULTRAMCA fi tristate ' SMC Ultra support' CONFIG_ULTRA - tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 + dep_tristate ' SMC Ultra32 EISA support' CONFIG_ULTRA32 $CONFIG_EISA tristate ' SMC 9194 support' CONFIG_SMC9194 - fi - bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL - if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' NI5010 support (EXPERIMENTAL)' CONFIG_NI5010 - fi - tristate ' NI5210 support' CONFIG_NI52 - tristate ' NI6510 support' CONFIG_NI65 - fi + fi + bool ' Racal-Interlan (Micom) NI cards' CONFIG_NET_VENDOR_RACAL + if [ "$CONFIG_NET_VENDOR_RACAL" = "y" ]; then + dep_tristate ' NI5010 support (EXPERIMENTAL)' CONFIG_NI5010 $CONFIG_EXPERIMENTAL + tristate ' NI5210 support' CONFIG_NI52 + tristate ' NI6510 support' CONFIG_NI65 + fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then tristate ' AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700 fi tristate ' DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA - tristate ' HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100 - bool ' Other ISA cards' CONFIG_NET_ISA + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" -o "$CONFIG_PCI" = "y" ]; then + tristate ' HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100 + fi + dep_bool ' Other ISA cards' CONFIG_NET_ISA $CONFIG_ISA if [ "$CONFIG_NET_ISA" = "y" ]; then tristate ' Cabletron E21xx support' CONFIG_E2100 if [ "$CONFIG_OBSOLETE" = "y" ]; then @@ -127,52 +127,45 @@ fi bool ' EISA, VLB, PCI and on board controllers' CONFIG_NET_PCI if [ "$CONFIG_NET_PCI" = "y" ]; then - tristate ' AMD PCnet32 (VLB and PCI) support' CONFIG_PCNET32 + dep_tristate ' AMD PCnet32 PCI support' CONFIG_PCNET32 $CONFIG_PCI dep_tristate ' Adaptec Starfire support (EXPERIMENTAL)' CONFIG_ADAPTEC_STARFIRE $CONFIG_PCI $CONFIG_EXPERIMENTAL - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 + if [ "$CONFIG_ISA" = "y" -o "$CONFIG_EISA" = "y" ]; then + dep_tristate ' Ansel Communications EISA 3200 support (EXPERIMENTAL)' CONFIG_AC3200 $CONFIG_EXPERIMENTAL fi tristate ' Apricot Xen-II on board Ethernet' CONFIG_APRICOT - tristate ' CS89x0 support' CONFIG_CS89x0 - tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 + dep_tristate ' CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA dep_tristate ' DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI - tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102 + if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then + tristate ' Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5 + tristate ' Digi Intl. RightSwitch SE-X support' CONFIG_DGRS fi + dep_tristate ' DM9102 PCI Fast Ethernet Adapter support (EXPERIMENTAL)' CONFIG_DM9102 $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' EtherExpressPro/100 support' CONFIG_EEPRO100 $CONFIG_PCI - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - if [ "$CONFIG_EEPRO100" = "y" -o "$CONFIG_EEPRO100" = "m" ]; then - bool ' Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM - fi - tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 - fi + dep_mbool ' Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM $CONFIG_EEPRO100 $CONFIG_EXPERIMENTAL + dep_tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL dep_tristate ' National Semiconductor DP83810 series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI dep_tristate ' PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 - fi - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate ' Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 - dep_tristate ' RealTek 8129 (not 8019/8029/8139!) support (EXPERIMENTAL)' CONFIG_RTL8129 $CONFIG_PCI - fi + dep_tristate ' Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL + dep_tristate ' Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL dep_tristate ' RealTek RTL-8139 PCI Fast Ethernet Adapter support' CONFIG_8139TOO $CONFIG_PCI + dep_tristate ' RealTek 8129 (not 8019/8029/8139!) support (EXPERIMENTAL)' CONFIG_RTL8129 $CONFIG_PCI $CONFIG_EXPERIMENTAL dep_tristate ' SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI dep_tristate ' SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI dep_tristate ' Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI - tristate ' TI ThunderLAN support' CONFIG_TLAN + if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then + tristate ' TI ThunderLAN support' CONFIG_TLAN + fi dep_tristate ' VIA Rhine support' CONFIG_VIA_RHINE $CONFIG_PCI dep_tristate ' Winbond W89c840 Ethernet support' CONFIG_WINBOND_840 $CONFIG_PCI + dep_tristate ' Sun Happy Meal 10/100baseT PCI support' CONFIG_HAPPYMEAL $CONFIG_PCI if [ "$CONFIG_OBSOLETE" = "y" ]; then bool ' Zenith Z-Note support (EXPERIMENTAL)' CONFIG_ZNET fi fi bool ' Pocket and portable adapters' CONFIG_NET_POCKET if [ "$CONFIG_NET_POCKET" = "y" ]; then - if [ "$CONFIG_X86" = "y" ]; then - tristate ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP - fi + dep_tristate ' AT-LAN-TEC/RealTek pocket adapter support' CONFIG_ATP $CONFIG_ISA tristate ' D-Link DE600 pocket adapter support' CONFIG_DE600 tristate ' D-Link DE620 pocket adapter support' CONFIG_DE620 fi diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/Space.c linux/drivers/net/Space.c --- v2.4.0-test10/linux/drivers/net/Space.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/Space.c Thu Nov 16 12:51:28 2000 @@ -459,14 +459,6 @@ #endif -/* 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" -#define __PAD5 __PAD6 "\0" -#define __PAD4 __PAD5 "\0" -#define __PAD3 __PAD4 "\0" -#define __PAD2 __PAD3 "\0" - - #ifdef CONFIG_NET_FC static int fcif_probe(struct net_device *dev) { @@ -486,14 +478,14 @@ #ifdef CONFIG_ETHERTAP - static struct net_device tap0_dev = { "tap0" __PAD4, 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, }; + static struct net_device tap0_dev = { "tap0", 0, 0, 0, 0, NETLINK_TAPBASE, 0, 0, 0, 0, NEXT_DEV, ethertap_probe, }; # undef NEXT_DEV # define NEXT_DEV (&tap0_dev) #endif #ifdef CONFIG_SDLA extern int sdla_init(struct net_device *); - static struct net_device sdla0_dev = { "sdla0" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, sdla_init, }; + static struct net_device sdla0_dev = { "sdla0", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, sdla_init, }; # undef NEXT_DEV # define NEXT_DEV (&sdla0_dev) @@ -502,7 +494,7 @@ #if defined(CONFIG_LTPC) extern int ltpc_probe(struct net_device *); static struct net_device dev_ltpc = { - "lt0" __PAD3, + "lt0", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NEXT_DEV, ltpc_probe }; @@ -512,9 +504,9 @@ #if defined(CONFIG_COPS) extern int cops_probe(struct net_device *); - static struct net_device cops2_dev = { "lt2" __PAD3, 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NEXT_DEV, cops_probe }; - static struct net_device cops1_dev = { "lt1" __PAD3, 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops2_dev, cops_probe }; - static struct net_device cops0_dev = { "lt0" __PAD3, 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops1_dev, cops_probe }; + static struct net_device cops2_dev = { "lt2", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, NEXT_DEV, cops_probe }; + static struct net_device cops1_dev = { "lt1", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops2_dev, cops_probe }; + static struct net_device cops0_dev = { "lt0", 0, 0, 0, 0, 0x0, 0, 0, 0, 0, &cops1_dev, cops_probe }; # undef NEXT_DEV # define NEXT_DEV (&cops0_dev) #endif /* COPS */ @@ -535,22 +527,22 @@ #define ETH_NOPROBE_ADDR 0xffe0 static struct net_device eth7_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, NEXT_DEV, ethif_probe }; static struct net_device eth6_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð7_dev, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð7_dev, ethif_probe }; static struct net_device eth5_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð6_dev, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð6_dev, ethif_probe }; static struct net_device eth4_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð5_dev, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð5_dev, ethif_probe }; static struct net_device eth3_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð4_dev, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð4_dev, ethif_probe }; static struct net_device eth2_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð3_dev, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð3_dev, ethif_probe }; static struct net_device eth1_dev = { - "eth%d" __PAD5, 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð2_dev, ethif_probe }; + "eth%d", 0,0,0,0,ETH_NOPROBE_ADDR /* I/O base*/, 0,0,0,0, ð2_dev, ethif_probe }; static struct net_device eth0_dev = { - "eth%d" __PAD5, 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, ð1_dev, ethif_probe }; + "eth%d", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, ð1_dev, ethif_probe }; # undef NEXT_DEV # define NEXT_DEV (ð0_dev) @@ -582,21 +574,21 @@ return 0; } static struct net_device tr7_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, NEXT_DEV, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, NEXT_DEV, trif_probe }; static struct net_device tr6_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr7_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr7_dev, trif_probe }; static struct net_device tr5_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr6_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr6_dev, trif_probe }; static struct net_device tr4_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr5_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr5_dev, trif_probe }; static struct net_device tr3_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr4_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr4_dev, trif_probe }; static struct net_device tr2_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr3_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr3_dev, trif_probe }; static struct net_device tr1_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr2_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr2_dev, trif_probe }; static struct net_device tr0_dev = { - "tr%d" __PAD3,0,0,0,0,0,0,0,0,0, &tr1_dev, trif_probe }; + "tr%d",0,0,0,0,0,0,0,0,0, &tr1_dev, trif_probe }; # undef NEXT_DEV # define NEXT_DEV (&tr0_dev) @@ -604,21 +596,21 @@ #ifdef CONFIG_FDDI static struct net_device fddi7_dev = - {"fddi7" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, fddiif_probe}; + {"fddi7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, fddiif_probe}; static struct net_device fddi6_dev = - {"fddi6" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi7_dev, fddiif_probe}; + {"fddi6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi7_dev, fddiif_probe}; static struct net_device fddi5_dev = - {"fddi5" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi6_dev, fddiif_probe}; + {"fddi5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi6_dev, fddiif_probe}; static struct net_device fddi4_dev = - {"fddi4" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi5_dev, fddiif_probe}; + {"fddi4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi5_dev, fddiif_probe}; static struct net_device fddi3_dev = - {"fddi3" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi4_dev, fddiif_probe}; + {"fddi3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi4_dev, fddiif_probe}; static struct net_device fddi2_dev = - {"fddi2" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi3_dev, fddiif_probe}; + {"fddi2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi3_dev, fddiif_probe}; static struct net_device fddi1_dev = - {"fddi1" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi2_dev, fddiif_probe}; + {"fddi1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi2_dev, fddiif_probe}; static struct net_device fddi0_dev = - {"fddi0" __PAD5, 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi1_dev, fddiif_probe}; + {"fddi0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &fddi1_dev, fddiif_probe}; #undef NEXT_DEV #define NEXT_DEV (&fddi0_dev) #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/a2065.c linux/drivers/net/a2065.c --- v2.4.0-test10/linux/drivers/net/a2065.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/a2065.c Thu Nov 16 12:51:28 2000 @@ -261,7 +261,7 @@ barrier(); if ((i == 100) || (ll->rdp & LE_C0_ERR)) { printk ("LANCE unopened after %d ticks, csr0=%4.4x.\n", i, ll->rdp); - return -1; + return -EIO; } /* Clear IDON by writing a "1", enable interrupts and start lance */ @@ -488,14 +488,14 @@ { struct lance_private *lp = (struct lance_private *)dev->priv; volatile struct lance_regs *ll = lp->ll; - int status = 0; + int ret; last_dev = dev; /* Install the Interrupt handler */ - if (request_irq(IRQ_AMIGA_PORTS, lance_interrupt, SA_SHIRQ, - "a2065 Ethernet", dev)) - return -EAGAIN; + ret = request_irq(IRQ_AMIGA_PORTS, lance_interrupt, SA_SHIRQ, + dev->name, dev); + if (ret) return ret; /* Stop the Lance */ ll->rap = LE_CSR0; @@ -506,11 +506,7 @@ netif_start_queue(dev); - status = init_restart_lance (lp); - - MOD_INC_USE_COUNT; - - return status; + return init_restart_lance (lp); } static int lance_close (struct net_device *dev) @@ -526,9 +522,6 @@ ll->rdp = LE_C0_STOP; free_irq(IRQ_AMIGA_PORTS, dev); - - MOD_DEC_USE_COUNT; - return 0; } @@ -727,6 +720,7 @@ while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { unsigned long board, base_addr, mem_start; + struct resource *r1, *r2; int is_cbm; if (z->id == ZORRO_PROD_CBM_A2065_1 || @@ -741,25 +735,27 @@ base_addr = board+A2065_LANCE; mem_start = board+A2065_RAM; - if (!request_mem_region(base_addr, sizeof(struct lance_regs), - "Am7990")) - continue; - if (!request_mem_region(mem_start, A2065_RAM_SIZE, "RAM")) { - release_mem_region(base_addr, - sizeof(struct lance_regs)); + r1 = request_mem_region(base_addr, sizeof(struct lance_regs), + "Am7990"); + if (!r1) continue; + r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM"); + if (!r2) { + release_resource(r1); continue; } dev = init_etherdev(NULL, sizeof(struct lance_private)); if (dev == NULL) { - release_mem_region(base_addr, - sizeof(struct lance_regs)); - release_mem_region(mem_start, A2065_RAM_SIZE); + release_resource(r1); + release_resource(r2); return -ENOMEM; } - priv = (struct lance_private *)dev->priv; - memset(priv, 0, sizeof(struct lance_private)); + SET_MODULE_OWNER(dev); + priv = dev->priv; + + r1->name = dev->name; + r2->name = dev->name; priv->dev = dev; dev->dev_addr[0] = 0x00; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c --- v2.4.0-test10/linux/drivers/net/ac3200.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/ac3200.c Tue Nov 14 13:16:37 2000 @@ -99,6 +99,8 @@ { unsigned short ioaddr = dev->base_addr; + SET_MODULE_OWNER(dev); + if (ioaddr > 0x1ff) /* Check a single specified location. */ return ac_probe1(ioaddr, dev); else if (ioaddr > 0) /* Don't probe at all. */ @@ -107,12 +109,9 @@ if ( ! EISA_bus) return -ENXIO; - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (check_region(ioaddr, AC_IO_EXTENT)) - continue; + for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) if (ac_probe1(ioaddr, dev) == 0) return 0; - } return -ENODEV; } @@ -121,8 +120,8 @@ { int i, retval; - if (!request_region(ioaddr, AC_IO_EXTENT, "ac3200")) - return -ENODEV; + if (!request_region(ioaddr, AC_IO_EXTENT, dev->name)) + return -EBUSY; if (inb_p(ioaddr + AC_ID_PORT) == 0xff) { retval = -ENODEV; @@ -172,9 +171,9 @@ printk(", assigning"); } - if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", dev)) { + retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (retval) { printk (" nothing! Unable to get IRQ %d.\n", dev->irq); - retval = -EAGAIN; goto out1; } @@ -262,15 +261,9 @@ #ifdef notyet /* Someday we may enable the IRQ and shared memory here. */ int ioaddr = dev->base_addr; - - if (request_irq(dev->irq, ei_interrupt, 0, "ac3200", dev)) - return -EAGAIN; #endif ei_open(dev); - - MOD_INC_USE_COUNT; - return 0; } @@ -339,9 +332,6 @@ #endif ei_close(dev); - - MOD_DEC_USE_COUNT; - return 0; } @@ -360,9 +350,6 @@ { int this_dev, found = 0; - if (load_8390_module("ac3200.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { struct net_device *dev = &dev_ac32[this_dev]; dev->irq = irq[this_dev]; @@ -376,7 +363,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -392,17 +378,16 @@ for (this_dev = 0; this_dev < MAX_AC32_CARDS; this_dev++) { struct net_device *dev = &dev_ac32[this_dev]; if (dev->priv != NULL) { - void *priv = dev->priv; /* Someday free_irq may be in ac_close_card() */ free_irq(dev->irq, dev); release_region(dev->base_addr, AC_IO_EXTENT); if (ei_status.reg0) iounmap((void *)dev->mem_start); unregister_netdev(dev); - kfree(priv); + kfree(dev->priv); + dev->priv = NULL; } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/acenic.c linux/drivers/net/acenic.c --- v2.4.0-test10/linux/drivers/net/acenic.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/acenic.c Sat Nov 11 19:02:39 2000 @@ -56,12 +56,9 @@ #include #include -#undef ETHTOOL #undef INDEX_DEBUG -#ifdef ETHTOOL #include -#endif #include #include @@ -1145,10 +1142,10 @@ goto init_error; } - if (request_irq(dev->irq, ace_interrupt, SA_SHIRQ, ap->name, dev)) { + ecode = request_irq(dev->irq, ace_interrupt, SA_SHIRQ, dev->name, dev); + if (ecode) { printk(KERN_WARNING "%s: Requested IRQ %d is busy\n", dev->name, dev->irq); - ecode = -EAGAIN; goto init_error; } @@ -2427,7 +2424,6 @@ static int ace_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { -#ifdef ETHTOOL struct ace_private *ap = dev->priv; struct ace_regs *regs = ap->regs; struct ethtool_cmd ecmd; @@ -2453,7 +2449,7 @@ if (copy_from_user(&ecmd, ifr->ifr_data, sizeof(ecmd))) return -EFAULT; - if (ecmd.cmd == ETH_GSET) { + if (ecmd.cmd == ETHTOOL_GSET) { ecmd.supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | @@ -2486,17 +2482,18 @@ else ecmd.autoneg = AUTONEG_DISABLE; +#if 0 ecmd.trace = readl(®s->TuneTrace); - ecmd.txcoal = readl(®s->TuneTxCoalTicks); ecmd.rxcoal = readl(®s->TuneRxCoalTicks); +#endif ecmd.maxtxpkt = readl(®s->TuneMaxTxDesc); ecmd.maxrxpkt = readl(®s->TuneMaxRxDesc); if(copy_to_user(ifr->ifr_data, &ecmd, sizeof(ecmd))) return -EFAULT; return 0; - } else if (ecmd.cmd == ETH_SSET) { + } else if (ecmd.cmd == ETHTOOL_SSET) { if(!capable(CAP_NET_ADMIN)) return -EPERM; @@ -2554,7 +2551,6 @@ } return 0; } -#endif return -EOPNOTSUPP; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/aironet4500_card.c linux/drivers/net/aironet4500_card.c --- v2.4.0-test10/linux/drivers/net/aironet4500_card.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/aironet4500_card.c Tue Nov 7 11:02:24 2000 @@ -164,16 +164,23 @@ static int awc_pci_init(struct net_device * dev, struct pci_dev *pdev, int ioaddr, int cis_addr, int mem_addr, u8 pci_irq_line) { - int i; + int i, allocd_dev = 0; if (!dev) { - dev = init_etherdev(dev, 0 ); + dev = init_etherdev(NULL, 0); + if (!dev) + return -ENOMEM; + allocd_dev = 1; } dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); memset(dev->priv,0,sizeof(struct awc_private)); if (!dev->priv) { printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); - return -1; + if (allocd_dev) { + unregister_netdev(dev); + kfree(dev); + } + return -ENOMEM; }; // ether_setup(dev); @@ -194,7 +201,16 @@ dev->watchdog_timeo = AWC_TX_TIMEOUT; - request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev); + i = request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT, dev->name, dev); + if (i) { + kfree(dev->priv); + dev->priv = NULL; + if (allocd_dev) { + unregister_netdev(dev); + kfree(dev); + } + return i; + } awc_private_init( dev); awc_init(dev); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c --- v2.4.0-test10/linux/drivers/net/aironet4500_core.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/aironet4500_core.c Thu Nov 16 12:51:28 2000 @@ -2574,7 +2574,7 @@ MODULE_PARM(max_mtu,"i"); MODULE_PARM(large_buff_mem,"i"); MODULE_PARM(small_buff_no,"i"); -MODULE_PARM(SSID,"1-4c31"); +MODULE_PARM(SSID,"c33"); #endif /*EXPORT_SYMBOL(tx_queue_len); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c --- v2.4.0-test10/linux/drivers/net/am79c961a.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/am79c961a.c Thu Nov 16 12:51:28 2000 @@ -285,15 +285,13 @@ am79c961_open(struct net_device *dev) { struct dev_priv *priv = (struct dev_priv *)dev->priv; - - MOD_INC_USE_COUNT; + int ret; memset (&priv->stats, 0, sizeof (priv->stats)); - if (request_irq(dev->irq, am79c961_interrupt, 0, "am79c961", dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + ret = request_irq(dev->irq, am79c961_interrupt, 0, dev->name, dev); + if (ret) + return ret; am79c961_init_for_open(dev); @@ -320,7 +318,6 @@ free_irq (dev->irq, dev); - MOD_DEC_USE_COUNT; return 0; } @@ -657,7 +654,8 @@ if (!dev) goto out; - priv = (struct dev_priv *) dev->priv; + SET_MODULE_OWNER(dev); + priv = dev->priv; /* * Fixed address and IRQ lines here. diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/apne.c linux/drivers/net/apne.c --- v2.4.0-test10/linux/drivers/net/apne.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/apne.c Thu Nov 16 12:51:28 2000 @@ -129,7 +129,9 @@ if (apne_owned) return -ENODEV; - + + SET_MODULE_OWNER(dev); + if ( !(AMIGAHW_PRESENT(PCMCIA)) ) return (-ENODEV); @@ -285,10 +287,8 @@ dev->base_addr = ioaddr; /* Install the Interrupt handler */ - if (request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, - "apne Ethernet", dev)) - return -EAGAIN; - + i = request_irq(IRQ_AMIGA_PORTS, apne_interrupt, SA_SHIRQ, dev->name, dev); + if (i) return i; /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { @@ -301,8 +301,7 @@ dev->dev_addr[i] = SA_prom[i]; } - printk("\n%s: %s found.\n", - dev->name, name); + printk("\n%s: %s found.\n", dev->name, name); ei_status.name = name; ei_status.tx_start_page = start_page; @@ -332,7 +331,6 @@ apne_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -342,7 +340,6 @@ if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } @@ -550,19 +547,16 @@ } #ifdef MODULE -static struct net_device apne_dev = { init: apne_probe }; +static struct net_device apne_dev; int init_module(void) { int err; - if (load_8390_module("apne.c")) - return -ENOSYS; - + apne_dev.init = apne_probe; if ((err = register_netdev(&apne_dev))) { if (err == -EIO) printk("No PCMCIA NEx000 ethernet card found.\n"); - unload_8390_module(); return (err); } return (0); @@ -577,8 +571,6 @@ free_irq(IRQ_AMIGA_PORTS, &apne_dev); pcmcia_reset(); - - unload_8390_module(); apne_owned = 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c --- v2.4.0-test10/linux/drivers/net/appletalk/cops.c Sun Aug 6 22:20:09 2000 +++ linux/drivers/net/appletalk/cops.c Tue Nov 7 11:06:09 2000 @@ -100,7 +100,6 @@ static int irq = 5; /* Default IRQ */ #else static int io = 0; /* Default IO for Dayna */ -static int irq = 0; /* Default IRQ */ #endif /* @@ -1009,15 +1008,7 @@ } #ifdef MODULE -static struct net_device cops0_dev = -{ - "", /* device name */ - 0, 0, 0, 0, - 0x0, 0, /* I/O address, IRQ */ - 0, 0, 0, NULL, cops_probe -}; - - +static struct net_device cops0_dev = { init: cops_probe }; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(board_type, "i"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c --- v2.4.0-test10/linux/drivers/net/ariadne2.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/ariadne2.c Thu Nov 16 12:51:28 2000 @@ -86,10 +86,12 @@ unsigned long board, ioaddr; int err; + SET_MODULE_OWNER(dev); + while ((z = zorro_find_device(ZORRO_PROD_VILLAGE_TRONIC_ARIADNE2, z))) { board = z->resource.start; ioaddr = board+ARIADNE2_BASE*2; - if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, "RTL8019AS")) + if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, dev->name)) continue; if ((err = ariadne2_init(dev, ZTWO_VADDR(board)))) { release_mem_region(ioaddr, NE_IO_EXTENT*2); @@ -170,9 +172,8 @@ dev->irq = IRQ_AMIGA_PORTS; /* Install the Interrupt handler */ - if (request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, - "AriadNE2 Ethernet", dev)) - return -EAGAIN; + i = request_irq(IRQ_AMIGA_PORTS, ei_interrupt, SA_SHIRQ, dev->name, dev); + if (i) return i; /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { @@ -213,7 +214,6 @@ static int ariadne2_open(struct net_device *dev) { ei_open(dev); - MOD_INC_USE_COUNT; return 0; } @@ -222,7 +222,6 @@ if (ei_debug > 1) printk("%s: Shutting down ethercard.\n", dev->name); ei_close(dev); - MOD_DEC_USE_COUNT; return 0; } @@ -381,19 +380,15 @@ } #ifdef MODULE -static struct net_device ariadne2_dev = { init: ariadne2_probe }; +static struct net_device ariadne2_dev; int init_module(void) { int err; - if (load_8390_module("ariadne2.c")) - return -ENOSYS; - + ariadne2_dev.init = ariadne2_probe; if ((err = register_netdev(&ariadne2_dev))) { - if (err == -EIO) - printk("No AriadNE2 ethernet card found.\n"); - unload_8390_module(); + printk(KERN_WARNING "No AriadNE2 ethernet card found.\n"); return err; } return 0; @@ -404,7 +399,6 @@ free_irq(IRQ_AMIGA_PORTS, &ariadne2_dev); release_mem_region(ZTWO_PADDR(ariadne2_dev.base_addr), NE_IO_EXTENT*2); unregister_netdev(&ariadne2_dev); - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/arlan.c linux/drivers/net/arlan.c --- v2.4.0-test10/linux/drivers/net/arlan.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/arlan.c Thu Nov 16 12:51:28 2000 @@ -1069,6 +1069,8 @@ int probed = 0; int found = 0; + SET_MODULE_OWNER(dev); + ARLAN_DEBUG_ENTRY("arlan_probe_everywhere"); if (mem != 0 && numDevices == 1) /* Check a single specified location. */ { @@ -1276,11 +1278,12 @@ return ret; arlan = ((struct arlan_private *) dev->priv)->card; - if (request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev)) + ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev); + if (ret) { printk(KERN_ERR "%s: unable to get IRQ %d .\n", dev->name, dev->irq); - return -EAGAIN; + return ret; } @@ -1323,7 +1326,6 @@ udelay(200000); add_timer(&priv->timer); - MOD_INC_USE_COUNT; #ifdef CONFIG_PROC_FS #ifndef MODULE if (arlan_device[0]) @@ -1887,7 +1889,6 @@ priv->open_time = 0; netif_stop_queue(dev); free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; ARLAN_DEBUG_EXIT("arlan_close"); return 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/at1700.c linux/drivers/net/at1700.c --- v2.4.0-test10/linux/drivers/net/at1700.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/at1700.c Thu Nov 16 12:51:28 2000 @@ -117,7 +117,6 @@ uint tx_started:1; /* Packets are on the Tx queue. */ uint tx_queue_ready:1; /* Tx queue is ready to be sent. */ uint rx_started:1; /* Packets are Rxing. */ - uint invalid_irq:1; uchar tx_queue; /* Number of packet on the Tx queue. */ char mca_slot; /* -1 means ISA */ ushort tx_queue_len; /* Current length of the Tx queue. */ @@ -191,10 +190,12 @@ (detachable devices only). */ -int at1700_probe(struct net_device *dev) +int __init at1700_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 at1700_probe1(dev, base_addr); @@ -203,8 +204,6 @@ for (i = 0; at1700_probe_list[i]; i++) { int ioaddr = at1700_probe_list[i]; - if (check_region(ioaddr, AT1700_IO_EXTENT)) - continue; if (at1700_probe1(dev, ioaddr) == 0) return 0; } @@ -219,15 +218,18 @@ that can be done is checking a few bits and then diving right into an EEPROM read. */ -int at1700_probe1(struct net_device *dev, int ioaddr) +static int at1700_probe1(struct net_device *dev, int ioaddr) { char fmv_irqmap[4] = {3, 7, 10, 15}; char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15}; char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15}; unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0; - int slot; + int slot, ret = -ENODEV; struct net_local *lp; + if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) + return -EBUSY; + /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ @@ -306,8 +308,10 @@ && inb(ioaddr + SAPROM + 1) == 0x00 && inb(ioaddr + SAPROM + 2) == 0x0e) is_fmv18x = 1; - else - return -ENODEV; + else { + ret = -ENODEV; + goto err_out; + } #ifdef CONFIG_MCA found: @@ -328,8 +332,10 @@ if (irq == fmv_irqmap_pnp[i]) break; } - if (i == 8) - return -ENODEV; + if (i == 8) { + goto err_out; + ret = -ENODEV; + } } else { if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr) return -ENODEV; @@ -337,10 +343,6 @@ } } - /* Grab the region so that we can find another board if the IRQ request - fails. */ - request_region(ioaddr, AT1700_IO_EXTENT, dev->name); - printk("%s: %s found at %#3x, IRQ %d, address ", dev->name, is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq); @@ -413,8 +415,10 @@ /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (dev->priv == NULL) { + ret = -ENOMEM; + goto err_out; + } memset(dev->priv, 0, sizeof(struct net_local)); dev->open = net_open; @@ -434,14 +438,21 @@ lp->jumpered = is_fmv18x; lp->mca_slot = slot; /* Snarf the interrupt vector now. */ - if (request_irq(irq, &net_interrupt, 0, dev->name, dev)) { + ret = request_irq(irq, &net_interrupt, 0, dev->name, dev); + if (ret) { printk (" AT1700 at %#3x is unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); - lp->invalid_irq = 1; - return 0; + goto err_out_priv; } return 0; + +err_out_priv: + kfree(dev->priv); + dev->priv = NULL; +err_out: + release_region(ioaddr, AT1700_IO_EXTENT); + return ret; } @@ -523,9 +534,6 @@ } netif_start_queue(dev); - - MOD_INC_USE_COUNT; - return 0; } @@ -775,9 +783,6 @@ /* Power-down the chip. Green, green, green! */ outb(0x00, ioaddr + CONFIG_1); - - MOD_DEC_USE_COUNT; - return 0; } @@ -866,8 +871,7 @@ } #ifdef MODULE -static struct net_device dev_at1700 = { init: at1700_probe }; - +static struct net_device dev_at1700; static int io = 0x260; static int irq; @@ -881,6 +885,7 @@ printk("at1700: You should not use auto-probing with insmod!\n"); dev_at1700.base_addr = io; dev_at1700.irq = irq; + dev_at1700.init = at1700_probe; if (register_netdev(&dev_at1700) != 0) { printk("at1700: register_netdev() returned non-zero.\n"); return -EIO; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c --- v2.4.0-test10/linux/drivers/net/atari_bionet.c Fri Jul 14 12:20:22 2000 +++ linux/drivers/net/atari_bionet.c Thu Nov 16 12:51:28 2000 @@ -353,9 +353,8 @@ return -ENODEV; } + SET_MODULE_OWNER(dev); - if (dev == NULL) - return -ENODEV; if (bionet_debug > 0 && version_printed++ == 0) printk(version); @@ -425,7 +424,6 @@ bionet_timer.data = (long)dev; bionet_timer.expires = jiffies + lp->poll_time; add_timer(&bionet_timer); - MOD_INC_USE_COUNT; return 0; } @@ -629,7 +627,6 @@ dev->start = 0; stdma_release(); - MOD_DEC_USE_COUNT; return 0; } @@ -645,19 +642,13 @@ #ifdef MODULE -static char bio_name[16]; -static struct net_device bio_dev = - { - bio_name, /* filled in by register_netdev() */ - 0, 0, 0, 0, /* memory */ - 0, 0, /* base, irq */ - 0, 0, 0, NULL, bionet_probe, - }; +static struct net_device bio_dev; int init_module(void) { int err; + bio_dev.init = bionet_probe; if ((err = register_netdev(&bio_dev))) { if (err == -EEXIST) { printk("BIONET: devices already present. Module not loaded.\n"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c --- v2.4.0-test10/linux/drivers/net/atari_pamsnet.c Fri Jul 14 12:20:22 2000 +++ linux/drivers/net/atari_pamsnet.c Thu Nov 16 12:51:28 2000 @@ -561,7 +561,7 @@ /* Check for a network adaptor of this type, and return '0' if one exists. */ -extern int __init +int __init pamsnet_probe (dev) struct net_device *dev; { @@ -576,6 +576,8 @@ if (no_more_found) return -ENODEV; + SET_MODULE_OWNER(dev); + no_more_found = 1; printk("Probing for PAM's Net/GK Adapter...\n"); @@ -686,7 +688,6 @@ pamsnet_timer.data = (long)dev; pamsnet_timer.expires = jiffies + lp->poll_time; add_timer(&pamsnet_timer); - MOD_INC_USE_COUNT; return 0; } @@ -848,7 +849,6 @@ ENABLE_IRQ(); stdma_release(); - MOD_DEC_USE_COUNT; return 0; } @@ -864,19 +864,13 @@ #ifdef MODULE -static char devicename[9] = { 0, }; -static struct net_device pam_dev = - { - devicename, /* filled in by register_netdev() */ - 0, 0, 0, 0, /* memory */ - 0, 0, /* base, irq */ - 0, 0, 0, NULL, pamsnet_probe, - }; +static struct net_device pam_dev; int init_module(void) { int err; + pam_dev.init = pamsnet_probe; if ((err = register_netdev(&pam_dev))) { if (err == -EEXIST) { printk("PAM's Net/GK: devices already present. Module not loaded.\n"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/atarilance.c linux/drivers/net/atarilance.c --- v2.4.0-test10/linux/drivers/net/atarilance.c Wed Aug 18 11:36:41 1999 +++ linux/drivers/net/atarilance.c Thu Nov 16 12:51:28 2000 @@ -357,7 +357,7 @@ -void *slow_memcpy( void *dst, const void *src, size_t len ) +static void *slow_memcpy( void *dst, const void *src, size_t len ) { char *cto = dst; const char *cfrom = src; @@ -375,6 +375,8 @@ int i; static int found = 0; + SET_MODULE_OWNER(dev); + if (!MACH_IS_ATARI || found) /* Assume there's only one board possible... That seems true, since * the Riebl/PAM board's address cannot be changed. */ @@ -659,7 +661,6 @@ dev->start = 1; DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); - MOD_INC_USE_COUNT; return( 0 ); } @@ -1062,7 +1063,6 @@ memory if we don't. */ DREG = CSR0_STOP; - MOD_DEC_USE_COUNT; return 0; } @@ -1152,20 +1152,13 @@ #ifdef MODULE -static char devicename[9] = { 0, }; - -static struct net_device atarilance_dev = -{ - devicename, /* filled in by register_netdev() */ - 0, 0, 0, 0, /* memory */ - 0, 0, /* base, irq */ - 0, 0, 0, NULL, atarilance_probe, -}; +static struct net_device atarilance_dev; int init_module(void) { int err; + atarilance_dev.init = atarilance_probe; if ((err = register_netdev( &atarilance_dev ))) { if (err == -EIO) { printk( "No Atari Lance board found. Module not loaded.\n"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/atp.c linux/drivers/net/atp.c --- v2.4.0-test10/linux/drivers/net/atp.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/atp.c Thu Nov 16 12:51:28 2000 @@ -46,9 +46,9 @@ #define NUM_UNITS 2 /* The standard set of ISA module parameters. */ -static int io[NUM_UNITS] = {0, 0}; -static int irq[NUM_UNITS] = {0, 0}; -static int xcvr[NUM_UNITS] = {0, 0}; /* The data transfer mode. */ +static int io[NUM_UNITS]; +static int irq[NUM_UNITS]; +static int xcvr[NUM_UNITS]; /* The data transfer mode. */ /* Operational parameters that are set at compile time. */ @@ -292,6 +292,7 @@ dev = init_etherdev(dev, sizeof(struct net_local)); if (!dev) return -ENOMEM; + SET_MODULE_OWNER(dev); /* Find the IRQ used by triggering an interrupt. */ write_reg_byte(ioaddr, CMR2, 0x01); /* No accept mode, IRQ out. */ @@ -425,16 +426,14 @@ static int net_open(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; - - MOD_INC_USE_COUNT; + int ret; /* The interrupt line is turned off (tri-stated) when the device isn't in use. That's especially important for "attached" interfaces where the port or interrupt may be shared. */ - if (request_irq(dev->irq, &atp_interrupt, 0, "ATP Ethernet", dev)) { - MOD_DEC_USE_COUNT; - return -EAGAIN; - } + ret = request_irq(dev->irq, &atp_interrupt, 0, dev->name, dev); + if (ret) + return ret; hardware_init(dev); @@ -835,10 +834,7 @@ free_irq(dev->irq, dev); /* Reset the ethernet hardware and activate the printer pass-through. */ - write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX); - - MOD_DEC_USE_COUNT; - + write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX); return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c --- v2.4.0-test10/linux/drivers/net/bagetlance.c Sat May 13 08:29:40 2000 +++ linux/drivers/net/bagetlance.c Thu Nov 16 12:51:28 2000 @@ -329,8 +329,7 @@ static int addr_accessible( volatile void *regp, int wordflag, int writeflag ); -static unsigned long lance_probe1( struct net_device *dev, struct lance_addr - *init_rec ); +static int lance_probe1( struct net_device *dev, struct lance_addr *init_rec ); static int lance_open( struct net_device *dev ); static void lance_init_ring( struct net_device *dev ); static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev ); @@ -474,10 +473,12 @@ { int i; static int found = 0; + SET_MODULE_OWNER(dev); + if (found) /* Assume there's only one board possible... That seems true, since * the Riebl/PAM board's address cannot be changed. */ - return( ENODEV ); + return( -ENODEV ); for( i = 0; i < N_LANCE_ADDR; ++i ) { if (lance_probe1( dev, &lance_addr_list[i] )) { @@ -486,7 +487,7 @@ } } - return( ENODEV ); + return( -ENODEV ); } @@ -508,8 +509,8 @@ #define IRQ_TYPE_PRIO SA_INTERRUPT #define IRQ_SOURCE_TO_VECTOR(x) (x) -static unsigned long __init lance_probe1( struct net_device *dev, - struct lance_addr *init_rec ) +static int __init lance_probe1( struct net_device *dev, + struct lance_addr *init_rec ) { volatile unsigned short *memaddr = (volatile unsigned short *)init_rec->memaddr; @@ -759,8 +760,6 @@ dev->start = 1; DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG )); - MOD_INC_USE_COUNT; - return( 0 ); } @@ -1222,7 +1221,6 @@ memory if we don't. */ DREG = CSR0_STOP; - MOD_DEC_USE_COUNT; return 0; } @@ -1324,20 +1322,13 @@ #ifdef MODULE -static char devicename[9] = { 0, }; - -static struct net_device bagetlance_dev = -{ - devicename, /* filled in by register_netdev() */ - 0, 0, 0, 0, /* memory */ - 0, 0, /* base, irq */ - 0, 0, 0, NULL, bagetlance_probe, -}; +static struct net_device bagetlance_dev; int init_module(void) { int err; + bagetlance_dev.init = bagetlance_probe; if ((err = register_netdev( &bagetlance_dev ))) { if (err == -EIO) { printk( "No Vme Lance board found. Module not loaded.\n"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/bmac.c linux/drivers/net/bmac.c --- v2.4.0-test10/linux/drivers/net/bmac.c Wed Aug 9 13:49:28 2000 +++ linux/drivers/net/bmac.c Thu Nov 16 12:51:28 2000 @@ -1270,7 +1270,7 @@ static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus) { - int j, rev; + int j, rev, ret; struct bmac_data *bp; unsigned char *addr; struct net_device *dev; @@ -1291,15 +1291,17 @@ } dev = init_etherdev(NULL, PRIV_BYTES); - if (!dev) { printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n", bmac->full_name); return; } + SET_MODULE_OWNER(dev); dev->base_addr = (unsigned long) ioremap(bmac->addrs[0].address, bmac->addrs[0].size); + if (!dev->base_addr) + goto err_out; dev->irq = bmac->intrs[0].line; bmwrite(dev, INTDISABLE, DisableAll); @@ -1322,18 +1324,19 @@ bmac_get_station_address(dev, addr); if (bmac_verify_checksum(dev) != 0) - return; - - ether_setup(dev); + goto err_out_iounmap; bp = (struct bmac_data *) dev->priv; - memset(bp, 0, sizeof(struct bmac_data)); bp->is_bmac_plus = is_bmac_plus; bp->tx_dma = (volatile struct dbdma_regs *) ioremap(bmac->addrs[1].address, bmac->addrs[1].size); + if (!bp->tx_dma) + goto err_out_iounmap; bp->tx_dma_intr = bmac->intrs[1].line; bp->rx_dma = (volatile struct dbdma_regs *) ioremap(bmac->addrs[2].address, bmac->addrs[2].size); + if (!bp->rx_dma) + goto err_out_iounmap_tx; bp->rx_dma_intr = bmac->intrs[2].line; bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1); @@ -1343,23 +1346,44 @@ skb_queue_head_init(bp->queue); bp->node = bmac; - memset(&bp->stats, 0, sizeof(bp->stats)); memset((char *) bp->tx_cmds, 0, (N_TX_RING + N_RX_RING + 2) * sizeof(struct dbdma_cmd)); /* init_timer(&bp->tx_timeout); */ /* bp->timeout_active = 0; */ - if (request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev)) + ret = request_irq(dev->irq, bmac_misc_intr, 0, "BMAC-misc", dev); + if (ret) { printk(KERN_ERR "BMAC: can't get irq %d\n", dev->irq); - if (request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", - dev)) + goto err_out_iounmap_rx; + } + ret = request_irq(bmac->intrs[1].line, bmac_txdma_intr, 0, "BMAC-txdma", dev); + if (ret) { printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[1].line); - if (request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", - dev)) + goto err_out_irq0; + } + ret = request_irq(bmac->intrs[2].line, bmac_rxdma_intr, 0, "BMAC-rxdma", dev); + if (ret) { printk(KERN_ERR "BMAC: can't get irq %d\n", bmac->intrs[2].line); + goto err_out_irq1; + } bp->next_bmac = bmac_devs; bmac_devs = dev; + return; + +err_out_irq1: + free_irq(bmac->intrs[1].line, dev); +err_out_irq0: + free_irq(dev->irq, dev); +err_out_iounmap_rx: + iounmap((void *)bp->rx_dma); +err_out_iounmap_tx: + iounmap((void *)bp->tx_dma); +err_out_iounmap: + iounmap((void *)dev->base_addr); +err_out: + unregister_netdev(dev); + kfree(dev); } static int bmac_open(struct net_device *dev) @@ -1370,8 +1394,6 @@ return -ENOMEM; dev->flags |= IFF_RUNNING; - - MOD_INC_USE_COUNT; return 0; } @@ -1416,8 +1438,6 @@ } bp->reset_and_enabled = 0; XXDEBUG(("bmac: all bufs freed\n")); - - MOD_DEC_USE_COUNT; return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c --- v2.4.0-test10/linux/drivers/net/cs89x0.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/cs89x0.c Tue Nov 14 11:34:25 2000 @@ -66,10 +66,18 @@ : abstracted IRQ mapping to support CONFIG_ARCH_CLPS7500 arch : (Jason Gunthorpe ) + Andrew Morton : Kernel 2.4.0-test11-pre4 + : Use dev->name in request_*() (Andrey Panin) + : Fix an error-path memleak in init_module() + : Preserve return value from request_irq() + : Fix type of `media' module parm (Keith Owens) + : Use SET_MODULE_OWNER() + : Tidied up strange request_irq() abuse in net_open(). + */ -static char *version = -"cs89x0.c: v2.3.99-pre1-2 Russell Nelson , Andrew Morton \n"; +static char version[] = +"cs89x0.c: v2.4.0-test11-pre4 Russell Nelson , Andrew Morton \n"; /* ======================= end of configuration ======================= */ @@ -77,13 +85,8 @@ /* Always include 'config.h' first in case the user wants to turn on or override something. */ #include -#ifdef MODULE #include #include -#else -#define MOD_INC_USE_COUNT -#define MOD_DEC_USE_COUNT -#endif /* * Set this to zero to disable DMA code @@ -97,7 +100,7 @@ * Set this to zero to remove all the debug statements via * dead code elimination */ -#define DEBUGGING 0 +#define DEBUGGING 1 /* Sources: @@ -254,6 +257,8 @@ int i; int base_addr = dev ? dev->base_addr : 0; + SET_MODULE_OWNER(dev); + if (net_debug) printk("cs89x0:cs89x0_probe()\n"); @@ -378,8 +383,8 @@ lp = (struct net_local *)dev->priv; /* Grab the region so we can find another board if autoIRQ fails. */ - if (!request_region(ioaddr, NETCARD_IO_EXTENT, "cs89x0")) { - retval = -ENODEV; + if (!request_region(ioaddr, NETCARD_IO_EXTENT, dev->name)) { + retval = -EBUSY; goto out1; } @@ -985,7 +990,7 @@ int i; if (chip_type == CS8900) { - /* Search the mapping table for the corrisponding IRQ pin. */ + /* Search the mapping table for the corresponding IRQ pin. */ for (i = 0; i != sizeof(cs8900_irq_map)/sizeof(cs8900_irq_map[0]); i++) if (cs8900_irq_map[i] == irq) break; @@ -1016,8 +1021,6 @@ int i; int ret; - MOD_INC_USE_COUNT; - if (dev->irq < 2) { /* Allow interrupts to be generated by the chip */ /* Cirrus' release had this: */ @@ -1027,20 +1030,20 @@ /* And 2.3.47 had this: */ writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); - for (i = 2; i < CS8920_NO_INTS; i++) if ((1 << dev->irq) & lp->irq_map) { - if (request_irq (i, NULL, 0, "cs89x0", dev) != -EBUSY) { - write_irq(dev, lp->chip_type, i); - writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); - if (request_irq (dev->irq = i, &net_interrupt, 0, "cs89x0", dev) == 0) + for (i = 2; i < CS8920_NO_INTS; i++) { + if ((1 << dev->irq) & lp->irq_map) { + if (request_irq(i, net_interrupt, 0, dev->name, dev) == 0) { + dev->irq = i; + write_irq(dev, lp->chip_type, i); + /* writereg(dev, PP_BufCFG, GENERATE_SW_INTERRUPT); */ break; + } } } - if (i >= CS8920_NO_INTS) { writereg(dev, PP_BusCTL, 0); /* disable interrupts. */ - if (net_debug) - printk("cs89x0: can't get an interrupt\n"); + printk(KERN_ERR "cs89x0: can't get an interrupt\n"); ret = -EAGAIN; goto bad_out; } @@ -1058,10 +1061,10 @@ writereg(dev, PP_BusCTL, ENABLE_IRQ | MEMORY_ON); #endif write_irq(dev, lp->chip_type, dev->irq); - if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev)) { + ret = request_irq(dev->irq, &net_interrupt, 0, dev->name, dev); + if (ret) { if (net_debug) - printk("cs89x0: request_irq(%d) failed\n", dev->irq); - ret = -EAGAIN; + printk(KERN_DEBUG "cs89x0: request_irq(%d) failed\n", dev->irq); goto bad_out; } } @@ -1089,7 +1092,7 @@ goto release_irq; } memset(lp->dma_buff, 0, lp->dmasize * 1024); /* Why? */ - if (request_dma(dev->dma, "cs89x0")) { + if (request_dma(dev->dma, dev->name)) { printk(KERN_ERR "%s: cannot get dma channel %d\n", dev->name, dev->dma); goto release_irq; } @@ -1231,11 +1234,10 @@ #endif ); netif_start_queue(dev); - if (net_debug) + if (net_debug > 1) printk("cs89x0: net_open() succeeded\n"); return 0; bad_out: - MOD_DEC_USE_COUNT; return ret; } @@ -1482,7 +1484,6 @@ #endif /* Update the statistics here. */ - MOD_DEC_USE_COUNT; return 0; } @@ -1576,7 +1577,7 @@ MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); MODULE_PARM(debug, "i"); -MODULE_PARM(media, "s"); +MODULE_PARM(media, "c8"); MODULE_PARM(duplex, "i"); MODULE_PARM(dma , "i"); MODULE_PARM(dmasize , "i"); @@ -1616,6 +1617,7 @@ init_module(void) { struct net_local *lp; + int ret = 0; #if DEBUGGING net_debug = debug; @@ -1661,21 +1663,27 @@ if (io == 0) { printk(KERN_ERR "cs89x0.c: Module autoprobing not allowed.\n"); printk(KERN_ERR "cs89x0.c: Append io=0xNNN\n"); - return -EPERM; + ret = -EPERM; + goto out; } #if ALLOW_DMA if (use_dma && dmasize != 16 && dmasize != 64) { printk(KERN_ERR "cs89x0.c: dma size must be either 16K or 64K, not %dK\n", dmasize); - return -EPERM; + ret = -EPERM; + goto out; } #endif if (register_netdev(&dev_cs89x0) != 0) { printk(KERN_ERR "cs89x0.c: No card found at 0x%x\n", io); - return -ENXIO; + ret = -ENXIO; + goto out; } - return 0; +out: + if (ret) + kfree(dev_cs89x0.priv); + return ret; } void @@ -1695,7 +1703,6 @@ /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -DMODULE -DCONFIG_MODVERSIONS -c cs89x0.c" * version-control: t * kept-new-versions: 5 * c-indent-level: 8 diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c --- v2.4.0-test10/linux/drivers/net/de4x5.c Thu Jul 13 11:11:10 2000 +++ linux/drivers/net/de4x5.c Wed Nov 8 17:09:50 2000 @@ -766,6 +766,20 @@ #define DE4X5_PKT_BIN_SZ 128 /* Should be >=100 unless you increase DE4X5_PKT_STAT_SZ */ +struct pkt_stats { + u_int bins[DE4X5_PKT_STAT_SZ]; /* Private stats counters */ + u_int unicast; + u_int multicast; + u_int broadcast; + u_int excessive_collisions; + u_int tx_underruns; + u_int excessive_underruns; + u_int rx_runt_frames; + u_int rx_collision; + u_int rx_dribble; + u_int rx_overflow; +}; + struct de4x5_private { char adapter_name[80]; /* Adapter name */ u_long interrupt; /* Aligned ISR flag */ @@ -779,19 +793,7 @@ char frame[64]; /* Min sized packet for loopback*/ spinlock_t lock; /* Adapter specific spinlock */ struct net_device_stats stats; /* Public stats */ - struct { - u_int bins[DE4X5_PKT_STAT_SZ]; /* Private stats counters */ - u_int unicast; - u_int multicast; - u_int broadcast; - u_int excessive_collisions; - u_int tx_underruns; - u_int excessive_underruns; - u_int rx_runt_frames; - u_int rx_collision; - u_int rx_dribble; - u_int rx_overflow; - } pktStats; + struct pkt_stats pktStats; /* Private stats counters */ char rxRingSize; char txRingSize; int bus; /* EISA or PCI */ @@ -5639,6 +5641,7 @@ break; case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; printk("%s: Boo!\n", dev->name); break; @@ -5650,12 +5653,16 @@ break; case DE4X5_GET_STATS: /* Get the driver statistics */ - ioc->len = sizeof(lp->pktStats); + { + struct pkt_stats statbuf; + ioc->len = sizeof(statbuf); spin_lock_irqsave(&lp->lock, flags); - if (copy_to_user(ioc->data, &lp->pktStats, ioc->len)) return -EFAULT; + memcpy(&statbuf, &lp->pktStats, ioc->len); spin_unlock_irqrestore(&lp->lock, flags); + if (copy_to_user(ioc->data, &statbuf, ioc->len)) + return -EFAULT; break; - + } case DE4X5_CLR_STATS: /* Zero out the driver statistics */ if (!capable(CAP_NET_ADMIN)) return -EPERM; spin_lock_irqsave(&lp->lock, flags); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/de600.c linux/drivers/net/de600.c --- v2.4.0-test10/linux/drivers/net/de600.c Mon Jun 19 13:30:57 2000 +++ linux/drivers/net/de600.c Thu Nov 16 12:51:28 2000 @@ -342,15 +342,14 @@ static int de600_open(struct net_device *dev) { - if (request_irq(DE600_IRQ, de600_interrupt, 0, "de600", dev)) { + int ret = request_irq(DE600_IRQ, de600_interrupt, 0, dev->name, dev); + if (ret) { printk ("%s: unable to get IRQ %d\n", dev->name, DE600_IRQ); - return 1; + return ret; } - MOD_INC_USE_COUNT; - if (adapter_init(dev)) { - return 1; - } + if (adapter_init(dev)) + return -EIO; return 0; } @@ -370,7 +369,6 @@ if (netif_running(dev)) { /* perhaps not needed? */ free_irq(DE600_IRQ, dev); - MOD_DEC_USE_COUNT; } return 0; } @@ -637,6 +635,8 @@ static struct net_device_stats de600_netstats; /*dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);*/ + SET_MODULE_OWNER(dev); + printk("%s: D-Link DE-600 pocket adapter", dev->name); /* Alpha testers must have the version number to report bugs. */ if (de600_debug > 1) @@ -819,12 +819,12 @@ #endif #ifdef MODULE -static struct net_device de600_dev = { - "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de600_probe }; +static struct net_device de600_dev; int init_module(void) { + de600_dev.init = de600_probe; if (register_netdev(&de600_dev) != 0) return -EIO; return 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/de620.c linux/drivers/net/de620.c --- v2.4.0-test10/linux/drivers/net/de620.c Mon Jun 19 13:30:57 2000 +++ linux/drivers/net/de620.c Thu Nov 16 12:51:28 2000 @@ -437,15 +437,15 @@ */ static int de620_open(struct net_device *dev) { - if (request_irq(dev->irq, de620_interrupt, 0, "de620", dev)) { + int ret = request_irq(dev->irq, de620_interrupt, 0, dev->name, dev); + if (ret) { printk (KERN_ERR "%s: unable to get IRQ %d\n", dev->name, dev->irq); - return 1; + return ret; } if (adapter_init(dev)) - return 1; + return -EIO; - MOD_INC_USE_COUNT; netif_start_queue(dev); return 0; } @@ -462,7 +462,6 @@ /* disable recv */ de620_set_register(dev, W_TCR, RXOFF); free_irq(dev->irq, dev); - MOD_DEC_USE_COUNT; return 0; } @@ -812,6 +811,8 @@ int i; byte checkbyte = 0xa5; + SET_MODULE_OWNER(dev); + /* * This is where the base_addr and irq gets set. * Tunable at compile-time and insmod-time @@ -985,11 +986,11 @@ * */ #ifdef MODULE -static struct net_device de620_dev = { - "", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, de620_probe }; +static struct net_device de620_dev; int init_module(void) { + de620_dev.init = de620_probe; if (register_netdev(&de620_dev) != 0) return -EIO; return 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/e2100.c linux/drivers/net/e2100.c --- v2.4.0-test10/linux/drivers/net/e2100.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/e2100.c Tue Nov 7 10:59:42 2000 @@ -395,9 +395,6 @@ { int this_dev, found = 0; - if (load_8390_module("e2100.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_E21_CARDS; this_dev++) { struct net_device *dev = &dev_e21[this_dev]; dev->irq = irq[this_dev]; @@ -414,7 +411,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -437,7 +433,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/es3210.c linux/drivers/net/es3210.c --- v2.4.0-test10/linux/drivers/net/es3210.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/es3210.c Tue Nov 7 10:59:42 2000 @@ -401,9 +401,6 @@ { int this_dev, found = 0; - if (load_8390_module("es3210.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ES_CARDS; this_dev++) { struct net_device *dev = &dev_es3210[this_dev]; dev->irq = irq[this_dev]; @@ -417,7 +414,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -440,6 +436,5 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c --- v2.4.0-test10/linux/drivers/net/eth16i.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/eth16i.c Sat Nov 11 18:56:58 2000 @@ -451,20 +451,14 @@ return -ENXIO; /* Seek card from the ISA io address space */ - for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) { - if(check_region(ioaddr, ETH16I_IO_EXTENT)) - continue; + for(i = 0; (ioaddr = eth16i_portlist[i]) ; i++) if(eth16i_probe1(dev, ioaddr) == 0) return 0; - } /* Seek card from the EISA io address space */ - for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) { - if(check_region(ioaddr, ETH16I_IO_EXTENT)) - continue; + for(i = 0; (ioaddr = eth32i_portlist[i]) ; i++) if(eth16i_probe1(dev, ioaddr) == 0) return 0; - } return -ENODEV; } @@ -472,10 +466,15 @@ static int __init eth16i_probe1(struct net_device *dev, int ioaddr) { struct eth16i_local *lp; - - static unsigned version_printed = 0; + static unsigned version_printed; + int retval; + boot = 1; /* To inform initilization that we are in boot probe */ + /* Let's grab the region */ + if (!request_region(ioaddr, ETH16I_IO_EXTENT, dev->name)) + return -EBUSY; + /* The MB86985 chip has on register which holds information in which io address the chip lies. First read this register and compare @@ -485,14 +484,18 @@ if(ioaddr < 0x1000) { if(eth16i_portlist[(inb(ioaddr + JUMPERLESS_CONFIG) & 0x07)] - != ioaddr) - return -ENODEV; + != ioaddr) { + retval = -ENODEV; + goto out; + } } /* Now we will go a bit deeper and try to find the chip's signature */ - if(eth16i_check_signature(ioaddr) != 0) - return -ENODEV; + if(eth16i_check_signature(ioaddr) != 0) { + retval = -ENODEV; + goto out; + } /* Now it seems that we have found a ethernet chip in this particular @@ -516,17 +519,15 @@ /* Try to obtain interrupt vector */ - if (request_irq(dev->irq, (void *)ð16i_interrupt, 0, "eth16i", dev)) { + if ((retval = request_irq(dev->irq, (void *)ð16i_interrupt, 0, dev->name, dev))) { printk(KERN_WARNING "%s: %s at %#3x, but is unusable due conflicting IRQ %d.\n", dev->name, cardname, ioaddr, dev->irq); - return -EAGAIN; + goto out; } printk(KERN_INFO "%s: %s at %#3x, IRQ %d, ", dev->name, cardname, ioaddr, dev->irq); - /* Let's grab the region */ - request_region(ioaddr, ETH16I_IO_EXTENT, "eth16i"); /* Now we will have to lock the chip's io address */ eth16i_select_regbank(TRANSCEIVER_MODE_RB, ioaddr); @@ -540,8 +541,11 @@ /* Initialize the device structure */ if(dev->priv == NULL) { dev->priv = kmalloc(sizeof(struct eth16i_local), GFP_KERNEL); - if(dev->priv == NULL) - return -ENOMEM; + if(dev->priv == NULL) { + free_irq(dev->irq, dev); + retval = -ENOMEM; + goto out; + } } memset(dev->priv, 0, sizeof(struct eth16i_local)); @@ -562,6 +566,9 @@ boot = 0; return 0; +out: + release_region(ioaddr, ETH16I_IO_EXTENT); + return retval; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c --- v2.4.0-test10/linux/drivers/net/fc/iph5526.c Sat Aug 5 08:39:14 2000 +++ linux/drivers/net/fc/iph5526.c Wed Nov 8 17:09:50 2000 @@ -3791,6 +3791,9 @@ sprintf(fi->name, "fc%d", count); host = scsi_register(tmpt, sizeof(struct iph5526_hostdata)); + if(host==NULL) + return no_of_hosts; + hostdata = (struct iph5526_hostdata *)host->hostdata; memset(hostdata, 0 , sizeof(struct iph5526_hostdata)); for (j = 0; j < MAX_SCSI_TARGETS; j++) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c --- v2.4.0-test10/linux/drivers/net/fmv18x.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/fmv18x.c Tue Nov 7 11:06:09 2000 @@ -132,20 +132,16 @@ int __init fmv18x_probe(struct net_device *dev) { int i; - int base_addr = dev ? dev->base_addr : 0; + int base_addr = dev->base_addr; if (base_addr > 0x1ff) /* Check a single specified location. */ return fmv18x_probe1(dev, base_addr); else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; fmv18x_probe_list[i]; i++) { - int ioaddr = fmv18x_probe_list[i]; - if (check_region(ioaddr, FMV18X_IO_EXTENT)) - continue; - if (fmv18x_probe1(dev, ioaddr) == 0) + for (i = 0; fmv18x_probe_list[i]; i++) + if (fmv18x_probe1(dev, fmv18x_probe_list[i]) == 0) return 0; - } return -ENODEV; } @@ -158,21 +154,26 @@ that can be done is checking a few bits and then diving right into MAC address check. */ -int __init fmv18x_probe1(struct net_device *dev, short ioaddr) +static int __init fmv18x_probe1(struct net_device *dev, short ioaddr) { char irqmap[4] = {3, 7, 10, 15}; char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15}; - unsigned int i, irq; + unsigned int i, irq, retval; /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. */ + if (!request_region(ioaddr, FMV18X_IO_EXTENT, dev->name)) + return -EBUSY; + /* Check I/O address configuration and Fujitsu vendor code */ if (inb(ioaddr+FJ_MACADDR ) != 0x00 || inb(ioaddr+FJ_MACADDR+1) != 0x00 - || inb(ioaddr+FJ_MACADDR+2) != 0x0e) - return -ENODEV; + || inb(ioaddr+FJ_MACADDR+2) != 0x0e) { + retval = -ENODEV; + goto out; + } /* Check PnP mode for FMV-183/184/183A/184A. */ /* This PnP routine is very poor. IO and IRQ should be known. */ @@ -182,8 +183,10 @@ if (irq == irqmap_pnp[i]) break; } - if (i == 8) - return -ENODEV; + if (i == 8) { + retval = -ENODEV; + goto out; + } } else { if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr) return -ENODEV; @@ -191,16 +194,13 @@ } /* Snarf the interrupt vector now. */ - if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) { + retval = request_irq(irq, &net_interrupt, 0, dev->name, dev); + if (retval) { printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on" "IRQ %d.\n", ioaddr, irq); - return -EAGAIN; + goto out; } - /* Grab the region so that we can find another board if the IRQ request - fails. */ - request_region(ioaddr, FMV18X_IO_EXTENT, "fmv18x"); - printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name, ioaddr, irq); @@ -261,8 +261,10 @@ /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); - if (dev->priv == NULL) - return -ENOMEM; + if (!dev->priv) { + retval = -ENOMEM; + goto out_irq; + } memset(dev->priv, 0, sizeof(struct net_local)); dev->open = net_open; @@ -277,6 +279,12 @@ ether_setup(dev); return 0; + +out_irq: + free_irq(irq, dev); +out: + release_region(ioaddr, FMV18X_IO_EXTENT); + return retval; } @@ -603,8 +611,7 @@ } #ifdef MODULE -static struct net_device dev_fmv18x = { init: fmv18x_probe }; - +static struct net_device dev_fmv18x; static int io = 0x220; static int irq; @@ -616,8 +623,9 @@ { if (io == 0) printk("fmv18x: You should not use auto-probing with insmod!\n"); - dev_fmv18x.base_addr = io; - dev_fmv18x.irq = irq; + dev_fmv18x.base_addr = io; + dev_fmv18x.irq = irq; + dev_fmv18x.init = fmv18x_probe; if (register_netdev(&dev_fmv18x) != 0) { printk("fmv18x: register_netdev() returned non-zero.\n"); return -EIO; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/gmac.c linux/drivers/net/gmac.c --- v2.4.0-test10/linux/drivers/net/gmac.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/gmac.c Sat Nov 11 18:23:10 2000 @@ -343,7 +343,7 @@ mdelay(10); /* Find the PHY */ - for(i=31; i>0; --i) { + for(i=0; i<=31; i++) { mii_control = mii_read(gm, i, MII_CR); mii_status = mii_read(gm, i, MII_SR); if (mii_control != -1 && mii_status != -1 && @@ -351,7 +351,7 @@ break; } gm->phy_addr = i; - if (gm->phy_addr < 0) + if (gm->phy_addr > 31) return 0; /* Reset it */ @@ -972,10 +972,11 @@ { struct gmac *gm = (struct gmac *) dev->priv; int i, timeout; - + unsigned long flags; + printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name); - spin_lock_irq(&gm->lock); + spin_lock_irqsave(&gm->lock, flags); /* Stop chip */ gmac_stop_dma(gm); @@ -1011,7 +1012,7 @@ /* Restart chip */ gmac_start_dma(gm); - spin_unlock_irq(&gm->lock); + spin_unlock_irqrestore(&gm->lock, flags); netif_wake_queue(dev); } @@ -1024,9 +1025,10 @@ { struct gmac *gm = (struct gmac *) dev->priv; volatile struct gmac_dma_desc *dp; + unsigned long flags; int i; - spin_lock_irq(&gm->lock); + spin_lock_irqsave(&gm->lock, flags); i = gm->next_tx; if (gm->tx_buff[i] != 0) { @@ -1036,7 +1038,7 @@ * Can this ever happen in 2.4 ? */ netif_stop_queue(dev); - spin_unlock_irq(&gm->lock); + spin_unlock_irqrestore(&gm->lock, flags); return 1; } gm->next_tx = (i + 1) & (NTX - 1); @@ -1058,7 +1060,7 @@ if (gm->tx_buff[gm->next_tx] != 0) netif_stop_queue(dev); - spin_unlock_irq(&gm->lock); + spin_unlock_irqrestore(&gm->lock, flags); dev->trans_start = jiffies; @@ -1078,9 +1080,12 @@ int gone, i; i = gm->tx_gone; - gone = GM_IN(GM_TX_COMP); - - while (force_cleanup || i != gone) { + + /* Note: If i==gone, we empty the entire ring. This works because + * if the ring was empty, we wouldn't have received the interrupt + */ + do { + gone = GM_IN(GM_TX_COMP); skb = gm->tx_buff[i]; if (skb == NULL) break; @@ -1095,14 +1100,12 @@ dev_kfree_skb_irq(skb); if (++i >= NTX) i = 0; - } + } while (force_cleanup || i != gone); gm->tx_gone = i; if (!force_cleanup && netif_queue_stopped(dev) && (gm->tx_buff[gm->next_tx] == 0)) netif_wake_queue(dev); - - spin_unlock(&gm->lock); } /* @@ -1373,6 +1376,8 @@ dev->irq = gmac->intrs[0].line; gm->dev = dev; gm->of_node = gmac; + + spin_lock_init(&gm->lock); if (pci_device_loc(gmac, &gm->pci_bus, &gm->pci_devfn)) { gm->pci_bus = gm->pci_devfn = 0xff; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/hamradio/baycom_epp.c linux/drivers/net/hamradio/baycom_epp.c --- v2.4.0-test10/linux/drivers/net/hamradio/baycom_epp.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/hamradio/baycom_epp.c Thu Nov 16 14:12:03 2000 @@ -814,7 +814,7 @@ #ifdef __i386__ #define GETTICK(x) \ ({ \ - if (current_cpu_data.x86_capability & X86_FEATURE_TSC) \ + if (cpu_has_tsc) \ __asm__ __volatile__("rdtsc" : "=a" (x) : : "dx");\ }) #else /* __i386__ */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/hamradio/soundmodem/sm.h linux/drivers/net/hamradio/soundmodem/sm.h --- v2.4.0-test10/linux/drivers/net/hamradio/soundmodem/sm.h Wed Aug 18 11:38:50 1999 +++ linux/drivers/net/hamradio/soundmodem/sm.h Thu Nov 16 14:11:14 2000 @@ -299,8 +299,6 @@ #ifdef __i386__ -#define HAS_RDTSC (current_cpu_data.x86_capability & X86_FEATURE_TSC) - /* * only do 32bit cycle counter arithmetic; we hope we won't overflow. * in fact, overflowing modems would require over 2THz CPU clock speeds :-) @@ -308,7 +306,7 @@ #define time_exec(var,cmd) \ ({ \ - if (HAS_RDTSC) { \ + if (cpu_has_tsc) { \ unsigned int cnt1, cnt2, cnt3; \ __asm__(".byte 0x0f,0x31" : "=a" (cnt1), "=d" (cnt3)); \ cmd; \ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c --- v2.4.0-test10/linux/drivers/net/hp-plus.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/hp-plus.c Sat Nov 11 18:56:58 2000 @@ -141,10 +141,10 @@ unsigned char checksum = 0; const char *name = "HP-PC-LAN+"; int mem_start; - static unsigned version_printed = 0; + static unsigned version_printed; - if (!request_region(ioaddr, HP_IO_EXTENT, "hp-plus")) - return -ENODEV; + if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) + return -EBUSY; /* Check for the HP+ signature, 50 48 0x 53. */ if (inw(ioaddr + HP_ID) != 0x4850 @@ -249,9 +249,10 @@ { int ioaddr = dev->base_addr - NIC_OFFSET; int option_reg; + int retval; - if (request_irq(dev->irq, ei_interrupt, 0, "hp-plus", dev)) { - return -EAGAIN; + if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { + return retval; } /* Reset the 8390 and HP chip. */ @@ -423,9 +424,6 @@ { int this_dev, found = 0; - if (load_8390_module("hp-plus.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) { struct net_device *dev = &dev_hpp[this_dev]; dev->irq = irq[this_dev]; @@ -440,7 +438,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -464,7 +461,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/hp.c linux/drivers/net/hp.c --- v2.4.0-test10/linux/drivers/net/hp.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/hp.c Sat Nov 11 18:56:58 2000 @@ -101,9 +101,9 @@ { int i, retval, board_id, wordmode; const char *name; - static unsigned version_printed = 0; + static unsigned version_printed; - if (!request_region(ioaddr, HP_IO_EXTENT, "hp")) + if (!request_region(ioaddr, HP_IO_EXTENT, dev->name)) return -ENODEV; /* Check for the HP physical address, 08 00 09 xx xx xx. */ @@ -150,12 +150,12 @@ do { int irq = *irqp; if (request_irq (irq, NULL, 0, "bogus", NULL) != -EBUSY) { - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); /* Twinkle the interrupt, and check if it's seen. */ outb_p(irqmap[irq] | HP_RUN, ioaddr + HP_CONFIGURE); outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE); - if (irq == autoirq_report(0) /* It's a good IRQ line! */ - && request_irq (irq, ei_interrupt, 0, "hp", dev) == 0) { + if (irq == probe_irq_off(cookie) /* It's a good IRQ line! */ + && request_irq (irq, ei_interrupt, 0, dev->name, dev) == 0) { printk(" selecting IRQ %d.\n", irq); dev->irq = *irqp; break; @@ -170,9 +170,8 @@ } else { if (dev->irq == 2) dev->irq = 9; - if (request_irq(dev->irq, ei_interrupt, 0, "hp", dev)) { + if ((retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev))) { printk (" unable to get IRQ %d.\n", dev->irq); - retval = -EBUSY; goto out1; } } @@ -396,9 +395,6 @@ { int this_dev, found = 0; - if (load_8390_module("hp.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_HP_CARDS; this_dev++) { struct net_device *dev = &dev_hp[this_dev]; dev->irq = irq[this_dev]; @@ -413,7 +409,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -437,7 +432,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ibmlana.c linux/drivers/net/ibmlana.c --- v2.4.0-test10/linux/drivers/net/ibmlana.c Tue Jul 18 16:09:27 2000 +++ linux/drivers/net/ibmlana.c Sat Nov 11 18:56:58 2000 @@ -857,7 +857,7 @@ result = request_irq(priv->realirq, irq_handler, - SA_SHIRQ | SA_SAMPLE_RANDOM, "ibm_lana", dev); + SA_SHIRQ | SA_SAMPLE_RANDOM, dev->name, dev); if (result != 0) { printk("%s: failed to register irq %d\n", dev->name, dev->irq); @@ -1046,7 +1046,7 @@ /* can't work without an MCA bus ;-) */ if (MCA_bus == 0) - return ENODEV; + return -ENODEV; /* start address of 1 --> forced detection */ @@ -1101,19 +1101,18 @@ /* nothing found ? */ if (slot == -1) - return ((base != 0) || (irq != 0)) ? ENXIO : ENODEV; + return ((base != 0) || (irq != 0)) ? -ENXIO : -ENODEV; /* announce success */ printk("%s: IBM LAN Adapter/A found in slot %d\n", dev->name, slot + 1); /* try to obtain I/O range */ - if (check_region(iobase, IBM_LANA_IORANGE) < 0) { - printk("cannot allocate I/O range at %#x!\n", iobase); + if (!request_region(iobase, IBM_LANA_IORANGE, dev->name)) { + printk("%s: cannot allocate I/O range at %#x!\n", dev->name, iobase); startslot = slot + 1; - return 0; + return -EBUSY; } - request_region(iobase, IBM_LANA_IORANGE, "ibm_lana"); /* make procfs entries */ @@ -1128,6 +1127,10 @@ priv = dev->priv = (ibmlana_priv *) kmalloc(sizeof(ibmlana_priv), GFP_KERNEL); + if (!priv) { + release_region(iobase, IBM_LANA_IORANGE); + return -ENOMEM; + } priv->slot = slot; priv->realirq = irq; priv->medium = medium; @@ -1189,24 +1192,11 @@ #define DEVMAX 5 -#if (LINUX_VERSION_CODE >= 0x020363) -static struct IBMLANA_NETDEV moddevs[DEVMAX] = - { {" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{" ", 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe} -}; -#else -static char NameSpace[8 * DEVMAX]; -static struct IBMLANA_NETDEV moddevs[DEVMAX] = - { {NameSpace + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{NameSpace + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{NameSpace + 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{NameSpace + 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe}, -{NameSpace + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, ibmlana_probe} +static struct IBMLANA_NETDEV moddevs[DEVMAX] = { + { init: ibmlana_probe }, { init: ibmlana_probe }, + { init: ibmlana_probe }, { init: ibmlana_probe }, + { init: ibmlana_probe } }; -#endif int irq = 0; int io = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c --- v2.4.0-test10/linux/drivers/net/irda/irport.c Tue Mar 21 11:17:28 2000 +++ linux/drivers/net/irda/irport.c Sun Nov 12 20:43:07 2000 @@ -230,7 +230,7 @@ dev->init = irport_net_init; dev->hard_start_xmit = irport_hard_xmit; dev->tx_timeout = irport_timeout; - dev->watchdog_timeo = HZ/20; + dev->watchdog_timeo = HZ; /* Allow time enough for speed change */ dev->open = irport_net_open; dev->stop = irport_net_close; dev->get_stats = irport_net_get_stats; @@ -496,7 +496,6 @@ self->tx_buff.data += actual; self->tx_buff.len -= actual; } else { - /* * Now serial buffer is almost free & we can start * transmission of another packet. But first we must check @@ -629,8 +628,16 @@ netif_stop_queue(dev); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + irda_task_execute(self, __irport_change_speed, + irport_change_speed_complete, + NULL, (void *) speed); + return 0; + } else + self->new_speed = speed; + } spin_lock_irqsave(&self->lock, flags); @@ -999,7 +1006,9 @@ #ifdef MODULE MODULE_PARM(io, "1-4i"); +MODULE_PARM_DESC(io, "Base I/O adresses"); MODULE_PARM(irq, "1-4i"); +MODULE_PARM_DESC(irq, "IRQ lines"); MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- v2.4.0-test10/linux/drivers/net/irda/irtty.c Tue Mar 21 11:17:28 2000 +++ linux/drivers/net/irda/irtty.c Sat Nov 11 18:11:23 2000 @@ -176,7 +176,7 @@ MINOR(tty->device) - tty->driver.minor_start + tty->driver.name_base); - hashbin_insert(irtty, (queue_t *) self, (int) self, NULL); + hashbin_insert(irtty, (irda_queue_t *) self, (int) self, NULL); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); @@ -233,8 +233,6 @@ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n"); return -ENOMEM; } - /* dev_alloc doesn't clear the struct */ - memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*)); dev->priv = (void *) self; self->netdev = dev; @@ -640,8 +638,16 @@ netif_stop_queue(dev); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + irda_task_execute(self, irtty_change_speed, + irtty_change_speed_complete, + NULL, (void *) speed); + return 0; + } else + self->new_speed = speed; + } /* Init tx buffer*/ self->tx_buff.data = self->tx_buff.head; @@ -1029,6 +1035,7 @@ MODULE_DESCRIPTION("IrDA TTY device driver"); MODULE_PARM(qos_mtt_bits, "i"); +MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); /* * Function init_module (void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c --- v2.4.0-test10/linux/drivers/net/irda/nsc-ircc.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/irda/nsc-ircc.c Sun Nov 12 09:40:48 2000 @@ -1076,9 +1076,15 @@ netif_stop_queue(dev); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; - + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + nsc_ircc_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } + spin_lock_irqsave(&self->lock, flags); /* Save current bank */ @@ -1120,8 +1126,14 @@ netif_stop_queue(dev); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + nsc_ircc_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } spin_lock_irqsave(&self->lock, flags); @@ -2029,10 +2041,15 @@ MODULE_DESCRIPTION("NSC IrDA Device Driver"); MODULE_PARM(qos_mtt_bits, "i"); +MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time"); MODULE_PARM(io, "1-4i"); +MODULE_PARM_DESC(io, "Base I/O addresses"); MODULE_PARM(irq, "1-4i"); +MODULE_PARM_DESC(irq, "IRQ lines"); MODULE_PARM(dma, "1-4i"); +MODULE_PARM_DESC(dma, "DMA channels"); MODULE_PARM(dongle_id, "i"); +MODULE_PARM_DESC(dongle_id, "Type-id of used dongle"); int init_module(void) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c --- v2.4.0-test10/linux/drivers/net/irda/smc-ircc.c Wed Jul 5 10:56:13 2000 +++ linux/drivers/net/irda/smc-ircc.c Sun Nov 12 20:43:11 2000 @@ -7,7 +7,7 @@ * Author: Thomas Davis (tadavis@jps.net) * Created at: * Modified at: Tue Feb 22 10:05:06 2000 - * Modified by: Dag Brattli + * Modified by: Dag Brattli * * Copyright (c) 1999-2000 Dag Brattli * Copyright (c) 1998-1999 Thomas Davis, @@ -252,6 +252,7 @@ IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8); irport->qos.min_turn_time.bits = 0x07; + irport->qos.window_size.bits = 0x01; irda_qos_bits_to_value(&irport->qos); irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO; @@ -508,6 +509,10 @@ outb(0x00, iobase+IRCC_MASTER); switch (speed) { + default: + IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", + speed); + /* FALLTHROUGH */ case 9600: case 19200: case 38400: @@ -535,10 +540,6 @@ fast = IRCC_LCR_A_FAST; IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n"); break; - default: - IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n", - speed); - return; } register_bank(iobase, 0); @@ -589,6 +590,8 @@ register_bank(iobase, 0); outb(fast, iobase+IRCC_LCR_A); + + netif_start_queue(dev); } /* @@ -612,13 +615,19 @@ iobase = self->io.fir_base; - spin_lock_irqsave(&self->lock, flags); + netif_stop_queue(dev); /* Check if we need to change the speed after this frame */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + ircc_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } - netif_stop_queue(dev); + spin_lock_irqsave(&self->lock, flags); memcpy(self->tx_buff.head, skb->data, skb->len); @@ -630,7 +639,7 @@ int bofs; /* - * Compute who many BOFS (STA or PA's) we need to waste the + * Compute how many BOFs (STA or PA's) we need to waste the * min turn time given the speed of the link. */ bofs = mtt * (self->io.speed / 1000) / 8000; @@ -642,7 +651,6 @@ /* Transmit frame */ ircc_dma_xmit(self, iobase, 0); } - spin_unlock_irqrestore(&self->lock, flags); dev_kfree_skb(skb); @@ -759,6 +767,7 @@ setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize, DMA_RX_MODE); + /* Set max Rx frame size */ register_bank(iobase, 4); outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI); @@ -787,7 +796,6 @@ * * Finished with receiving frames * - * */ static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase) { @@ -814,7 +822,7 @@ else len -= 4; - if ((len < 2) && (len > 2050)) { + if ((len < 2) || (len > 2050)) { WARNING(__FUNCTION__ "(), bogus len=%d\n", len); return; } @@ -1039,7 +1047,9 @@ MODULE_AUTHOR("Thomas Davis "); MODULE_DESCRIPTION("SMC IrCC controller driver"); MODULE_PARM(ircc_dma, "1i"); +MODULE_PARM_DESC(ircc_dma, "DMA channel"); MODULE_PARM(ircc_irq, "1i"); +MODULE_PARM_DESC(ircc_irq, "IRQ line"); int init_module(void) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- v2.4.0-test10/linux/drivers/net/irda/toshoboe.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/irda/toshoboe.c Sun Nov 12 20:43:11 2000 @@ -272,8 +272,14 @@ ); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + toshoboe_setbaud(self, speed); + return 0; + } else + self->new_speed = speed; + } netif_stop_queue(dev); @@ -628,7 +634,10 @@ #ifdef MODULE +MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver"); +MODULE_AUTHOR("James McKenzie "); MODULE_PARM (max_baud, "i"); +MODULE_PARM_DESC(max_baus, "Maximum baud rate"); static int toshoboe_close (struct toshoboe_cb *self) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c --- v2.4.0-test10/linux/drivers/net/irda/w83977af_ir.c Tue Mar 21 11:17:28 2000 +++ linux/drivers/net/irda/w83977af_ir.c Sat Nov 11 18:11:23 2000 @@ -255,13 +255,12 @@ dev->get_stats = w83977af_net_get_stats; rtnl_lock(); - err = register_netdev(dev); + err = register_netdevice(dev); rtnl_unlock(); if (err) { - ERROR(__FUNCTION__ "(), register_netdev() failed!\n"); + ERROR(__FUNCTION__ "(), register_netdevice() failed!\n"); return -1; } - MESSAGE("IrDA: Registered device %s\n", dev->name); return 0; @@ -514,8 +513,14 @@ netif_stop_queue(dev); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + w83977af_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } /* Save current set */ set = inb(iobase+SSR); @@ -1366,9 +1371,11 @@ MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver"); MODULE_PARM(qos_mtt_bits, "i"); +MODULE_PARM_DESC(qos_mtt_bits, "Mimimum Turn Time"); MODULE_PARM(io, "1-4i"); -MODULE_PARM(io2, "1-4i"); +MODULE_PARM_DESC(io, "Base I/O addresses"); MODULE_PARM(irq, "1-4i"); +MODULE_PARM_DESC(irq, "IRQ lines"); /* * Function init_module (void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/lance.c linux/drivers/net/lance.c --- v2.4.0-test10/linux/drivers/net/lance.c Mon Jun 19 13:30:58 2000 +++ linux/drivers/net/lance.c Thu Nov 16 12:51:28 2000 @@ -224,7 +224,6 @@ int dma; struct net_device_stats stats; unsigned char chip_version; /* See lance_chip_type. */ - char tx_full; spinlock_t devlock; }; @@ -268,8 +267,6 @@ enum {OLD_LANCE = 0, PCNET_ISA=1, PCNET_ISAP=2, PCNET_PCI=3, PCNET_VLB=4, PCNET_PCI_II=5, LANCE_UNKNOWN=6}; -/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned int pci_irq_line = 0; /* Non-zero if lance_probe1() needs to allocate low-memory bounce buffers. Assume yes until we know the memory size. */ @@ -360,29 +357,6 @@ if (high_memory <= phys_to_virt(16*1024*1024)) lance_need_isa_bounce_buffers = 0; -#if defined(CONFIG_PCI) - { - struct pci_dev *pdev = NULL; - if (lance_debug > 1) - printk("lance.c: PCI bios is present, checking for devices...\n"); - - while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) { - unsigned int pci_ioaddr; - - if (pci_enable_device(pdev)) - continue; - pci_set_master(pdev); - pci_irq_line = pdev->irq; - pci_ioaddr = pci_resource_start (pdev, 0); - printk("Found PCnet/PCI at %#x, irq %d.\n", - pci_ioaddr, pci_irq_line); - result = lance_probe1(dev, pci_ioaddr, pci_irq_line, 0); - pci_irq_line = 0; - if (!result) return 0; - } - } -#endif /* defined(CONFIG_PCI) */ - for (port = lance_portlist; *port; port++) { int ioaddr = *port; @@ -671,7 +645,7 @@ static int lance_open(struct net_device *dev) { - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; int ioaddr = dev->base_addr; int i; @@ -761,7 +735,7 @@ static void lance_purge_ring(struct net_device *dev) { - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; int i; /* Free all the skbuffs in the Rx and Tx queues. */ @@ -770,11 +744,11 @@ lp->rx_skbuff[i] = 0; lp->rx_ring[i].base = 0; /* Not owned by LANCE chip. */ if (skb) - dev_kfree_skb(skb); + dev_kfree_skb_any(skb); } for (i = 0; i < TX_RING_SIZE; i++) { if (lp->tx_skbuff[i]) { - dev_kfree_skb(lp->tx_skbuff[i]); + dev_kfree_skb_any(lp->tx_skbuff[i]); lp->tx_skbuff[i] = NULL; } } @@ -785,10 +759,9 @@ static void lance_init_ring(struct net_device *dev, int gfp) { - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; int i; - lp->tx_full = 0; lp->cur_rx = lp->cur_tx = 0; lp->dirty_rx = lp->dirty_tx = 0; @@ -828,7 +801,7 @@ static void lance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit) { - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; if (must_reinit || (chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) { @@ -854,7 +827,7 @@ if (lance_debug > 3) { int i; printk (" Ring data dump: dirty_tx %d cur_tx %d%s cur_rx %d.", - lp->dirty_tx, lp->cur_tx, lp->tx_full ? " (full)" : "", + lp->dirty_tx, lp->cur_tx, netif_queue_stopped(dev) ? " (full)" : "", lp->cur_rx); for (i = 0; i < RX_RING_SIZE; i++) printk ("%s %08x %04x %04x", i & 0x3 ? "" : "\n ", @@ -876,10 +849,13 @@ static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev) { - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; int ioaddr = dev->base_addr; int entry; unsigned long flags; + + spin_lock_irqsave(&lp->devlock, flags); + if (lance_debug > 3) { outw(0x0000, ioaddr+LANCE_ADDR); printk("%s: lance_start_xmit() called, csr0 %4.4x.\n", dev->name, @@ -887,8 +863,6 @@ outw(0x0000, ioaddr+LANCE_DATA); } - netif_stop_queue (dev); - /* Fill in a Tx ring entry */ /* Mask to ring buffer boundary. */ @@ -929,13 +903,10 @@ dev->trans_start = jiffies; - spin_lock_irqsave (&lp->devlock, flags); - if (lp->tx_ring[(entry+1) & TX_RING_MOD_MASK].base == 0) - netif_start_queue (dev); - else - lp->tx_full = 1; - spin_unlock_irqrestore (&lp->devlock, flags); + if ((lp->cur_tx - lp->dirty_tx) >= TX_RING_SIZE) + netif_stop_queue(dev); + spin_unlock_irqrestore(&lp->devlock, flags); return 0; } @@ -954,7 +925,7 @@ } ioaddr = dev->base_addr; - lp = (struct lance_private *)dev->priv; + lp = dev->priv; spin_lock (&lp->devlock); @@ -1018,19 +989,17 @@ #ifndef final_version if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) { - printk("out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dirty_tx, lp->cur_tx, lp->tx_full); + printk("out-of-sync dirty pointer, %d vs. %d, full=%s.\n", + dirty_tx, lp->cur_tx, + netif_queue_stopped(dev) ? "yes" : "no"); dirty_tx += TX_RING_SIZE; } #endif - if (lp->tx_full && - (netif_queue_stopped(dev)) && - dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) { - /* The ring is no longer full, clear tbusy. */ - lp->tx_full = 0; + /* if the ring is no longer full, accept more packets */ + if (netif_queue_stopped(dev) && + dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) netif_wake_queue (dev); - } lp->dirty_tx = dirty_tx; } @@ -1068,7 +1037,7 @@ static int lance_rx(struct net_device *dev) { - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; int entry = lp->cur_rx & RX_RING_MOD_MASK; int i; @@ -1147,7 +1116,7 @@ lance_close(struct net_device *dev) { int ioaddr = dev->base_addr; - struct lance_private *lp = (struct lance_private *)dev->priv; + struct lance_private *lp = dev->priv; netif_stop_queue (dev); @@ -1181,19 +1150,19 @@ static struct net_device_stats *lance_get_stats(struct net_device *dev) { - struct lance_private *lp = (struct lance_private *)dev->priv; - short ioaddr = dev->base_addr; - short saved_addr; - unsigned long flags; + struct lance_private *lp = dev->priv; if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) { - save_flags(flags); - cli(); + short ioaddr = dev->base_addr; + short saved_addr; + unsigned long flags; + + spin_lock_irqsave(&lp->devlock, flags); saved_addr = inw(ioaddr+LANCE_ADDR); outw(112, ioaddr+LANCE_ADDR); lp->stats.rx_missed_errors = inw(ioaddr+LANCE_DATA); outw(saved_addr, ioaddr+LANCE_ADDR); - restore_flags(flags); + spin_unlock_irqrestore(&lp->devlock, flags); } return &lp->stats; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/lne390.c linux/drivers/net/lne390.c --- v2.4.0-test10/linux/drivers/net/lne390.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/lne390.c Tue Nov 7 10:59:42 2000 @@ -394,9 +394,6 @@ { int this_dev, found = 0; - if (load_8390_module("lne390.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_LNE_CARDS; this_dev++) { struct net_device *dev = &dev_lne[this_dev]; dev->irq = irq[this_dev]; @@ -410,7 +407,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -434,7 +430,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ne.c linux/drivers/net/ne.c --- v2.4.0-test10/linux/drivers/net/ne.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/ne.c Tue Nov 7 11:02:24 2000 @@ -29,21 +29,22 @@ occur after memory is allocated for dev->priv. Deallocated memory last in cleanup_modue() Richard Guenther : Added support for ISAPnP cards - + Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead. + */ /* Routines for the NatSemi-based designs (NE[12]000). */ -static const char *version = - "ne.c:v1.10 9/23/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n"; +static const char version1[] = +"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n"; +static const char version2[] = +"Last modified Nov 1, 2000 by Paul Gortmaker\n"; #include -#include #include #include #include -#include #include #include #include @@ -70,28 +71,11 @@ /* A zero-terminated list of I/O addresses to be probed at boot. */ #ifndef MODULE -static unsigned int netcard_portlist[] __initdata = { +static unsigned int netcard_portlist[] __initdata = { 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0 }; #endif -#ifdef CONFIG_PCI -/* Ack! People are making PCI ne2000 clones! Oh the horror, the horror... */ -static struct { unsigned short vendor, dev_id; char *name; } -pci_clone_list[] __initdata = { - {PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8029, "Realtek 8029" }, - {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940, "Winbond 89C940" }, - {PCI_VENDOR_ID_COMPEX, PCI_DEVICE_ID_COMPEX_RL2000, "Compex ReadyLink 2000" }, - {PCI_VENDOR_ID_KTI, PCI_DEVICE_ID_KTI_ET32P2, "KTI ET32P2" }, - {PCI_VENDOR_ID_NETVIN, PCI_DEVICE_ID_NETVIN_NV5000SC, "NetVin NV5000" }, - {PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C926, "VIA 82C926 Amazon" }, - {PCI_VENDOR_ID_SURECOM, PCI_DEVICE_ID_SURECOM_NE34, "SureCom NE34"}, - {0,} -}; - -static int probe_pci = 1; -#endif - static struct { unsigned short vendor, function; char *name; } isapnp_clone_list[] __initdata = { {ISAPNP_VENDOR('E','D','I'), ISAPNP_FUNCTION(0x0216), "NN NE2000" }, @@ -114,7 +98,9 @@ {"ET-100","ET-200", {0x00, 0x45, 0x54}}, /* YANG and YA clone */ {"COMPEX","COMPEX16",{0x00,0x80,0x48}}, /* Broken ISA Compex cards */ {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */ - {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ + {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ + {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */ + {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */ {0,} }; #endif @@ -132,15 +118,9 @@ #define NESM_START_PG 0x40 /* First page of TX buffer */ #define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ -/* Non-zero only if the current card is a PCI with BIOS-set IRQ. */ -static unsigned int pci_irq_line = 0; - int ne_probe(struct net_device *dev); static int ne_probe1(struct net_device *dev, int ioaddr); static int ne_probe_isapnp(struct net_device *dev); -#ifdef CONFIG_PCI -static int ne_probe_pci(struct net_device *dev); -#endif static int ne_open(struct net_device *dev); static int ne_close(struct net_device *dev); @@ -175,16 +155,9 @@ E2010 starts at 0x100 and ends at 0x4000. E2010-x starts at 0x100 and ends at 0xffff. */ -/* - * Note that at boot, this probe only picks up one card at a time, even for - * multiple PCI ne2k cards. Use "ether=0,0,eth1" if you have a second PCI - * ne2k card. This keeps things consistent regardless of the bus type of - * the card. - */ - int __init ne_probe(struct net_device *dev) { - int base_addr = dev ? dev->base_addr : 0; + unsigned int base_addr = dev ? dev->base_addr : 0; /* First check any supplied i/o locations. User knows best. */ if (base_addr > 0x1ff) /* Check a single specified location. */ @@ -192,12 +165,6 @@ else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; -#ifdef CONFIG_PCI - /* Then look for any installed PCI clones */ - if (probe_pci && pci_present() && (ne_probe_pci(dev) == 0)) - return 0; -#endif - /* Then look for any installed ISAPnP clones */ if (isapnp_present() && (ne_probe_isapnp(dev) == 0)) return 0; @@ -206,8 +173,6 @@ /* Last resort. The semi-risky ISA auto-probe. */ for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) { int ioaddr = netcard_portlist[base_addr]; - if (check_region(ioaddr, NE_IO_EXTENT)) - continue; if (ne_probe1(dev, ioaddr) == 0) return 0; } @@ -216,47 +181,10 @@ return -ENODEV; } -#ifdef CONFIG_PCI -static int __init ne_probe_pci(struct net_device *dev) -{ - int i; - - for (i = 0; pci_clone_list[i].vendor != 0; i++) { - struct pci_dev *pdev = NULL; - unsigned int pci_ioaddr = 0; - - while ((pdev = pci_find_device(pci_clone_list[i].vendor, pci_clone_list[i].dev_id, pdev))) { - if (pci_enable_device(pdev)) - continue; - pci_ioaddr = pci_resource_start (pdev, 0); - /* Avoid already found cards from previous calls */ - if (check_region(pci_ioaddr, NE_IO_EXTENT)) - continue; - pci_irq_line = pdev->irq; - if (pci_irq_line) break; /* Found it */ - } - if (!pdev) - continue; - printk(KERN_INFO "ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n", - pci_clone_list[i].name, - pci_ioaddr, pci_irq_line); - printk("*\n* Use of the PCI-NE2000 driver with this card is recommended!\n*\n"); - if (ne_probe1(dev, pci_ioaddr) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of PCI card at %#x failed.\n", pci_ioaddr); - pci_irq_line = 0; - return -ENXIO; - } - pci_irq_line = 0; - return 0; - } - return -ENODEV; -} -#endif /* CONFIG_PCI */ - static int __init ne_probe_isapnp(struct net_device *dev) { int i; - + for (i = 0; isapnp_clone_list[i].vendor != 0; i++) { struct pci_dev *idev = NULL; @@ -269,14 +197,18 @@ continue; if (idev->activate(idev)) continue; - pci_irq_line = idev->irq_resource[0].start; /* if no irq, search for next */ - if (!pci_irq_line) + if (idev->irq_resource[0].start == 0) continue; /* found it */ - if (ne_probe1(dev, idev->resource[0].start) != 0) { /* Shouldn't happen. */ - printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", - idev->resource[0].start); + dev->base_addr = idev->resource[0].start; + dev->irq = idev->irq_resource[0].start; + printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", + isapnp_clone_list[i].name, + + dev->base_addr, dev->irq); + if (ne_probe1(dev, dev->base_addr) != 0) { /* Shouldn't happen. */ + printk(KERN_ERR "ne.c: Probe of ISAPnP card at %#lx failed.\n", dev->base_addr); return -ENXIO; } ei_status.priv = (unsigned long)idev; @@ -284,9 +216,6 @@ } if (!idev) continue; - printk(KERN_INFO "ne.c: ISAPnP reports %s at i/o %#lx, irq %d.\n", - isapnp_clone_list[i].name, - dev->base_addr, dev->irq); return 0; } @@ -301,11 +230,17 @@ const char *name = NULL; int start_page, stop_page; int neX000, ctron, copam, bad_card; - int reg0 = inb_p(ioaddr); + int reg0, ret; static unsigned version_printed = 0; - if (reg0 == 0xFF) - return -ENODEV; + if (!request_region(ioaddr, NE_IO_EXTENT, dev->name)) + return -EBUSY; + + reg0 = inb_p(ioaddr); + if (reg0 == 0xFF) { + ret = -ENODEV; + goto err_out; + } /* Do a preliminary verification that we have a 8390. */ { @@ -318,12 +253,13 @@ if (inb_p(ioaddr + EN0_COUNTER0) != 0) { outb_p(reg0, ioaddr); outb_p(regd, ioaddr + 0x0d); /* Restore the old values. */ - return -ENODEV; + ret = -ENODEV; + goto err_out; } } if (ei_debug && version_printed++ == 0) - printk(version); + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr); @@ -350,10 +286,11 @@ break; } else { printk(" not found (no reset ack).\n"); - return -ENODEV; + ret = -ENODEV; + goto err_out; } } - + outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ } @@ -362,7 +299,7 @@ We can't reliably read the SAPROM address without this. (I learned the hard way!). */ { - struct {unsigned char value, offset; } program_seq[] = + struct {unsigned char value, offset; } program_seq[] = { {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ @@ -390,20 +327,10 @@ wordlength = 1; } - /* At this point, wordlength *only* tells us if the SA_prom is doubled - up or not because some broken PCI cards don't respect the byte-wide - request in program_seq above, and hence don't have doubled up values. - These broken cards would otherwise be detected as an ne1000. */ - if (wordlength == 2) + { for (i = 0; i < 16; i++) SA_prom[i] = SA_prom[i+i]; - - if (pci_irq_line || ioaddr >= 0x400) - wordlength = 2; /* Catch broken PCI cards mentioned above. */ - - if (wordlength == 2) - { /* We must set the 8390 for word mode. */ outb_p(0x49, ioaddr + EN0_DCFG); start_page = NESM_START_PG; @@ -416,13 +343,12 @@ neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); copam = (SA_prom[14] == 0x49 && SA_prom[15] == 0x00); - /* Set up the rest of the parameters. */ if (neX000 || bad_card || copam) { name = (wordlength == 2) ? "NE2000" : "NE1000"; } - else if (ctron) + else if (ctron) { name = (wordlength == 2) ? "Ctron-8" : "Ctron-16"; start_page = 0x01; @@ -433,13 +359,13 @@ #ifdef SUPPORT_NE_BAD_CLONES /* Ack! Well, there might be a *bad* NE*000 clone there. Check for total bogus addresses. */ - for (i = 0; bad_clone_list[i].name8; i++) + for (i = 0; bad_clone_list[i].name8; i++) { if (SA_prom[0] == bad_clone_list[i].SAprefix[0] && SA_prom[1] == bad_clone_list[i].SAprefix[1] && - SA_prom[2] == bad_clone_list[i].SAprefix[2]) + SA_prom[2] == bad_clone_list[i].SAprefix[2]) { - if (wordlength == 2) + if (wordlength == 2) { name = bad_clone_list[i].name16; } else { @@ -448,31 +374,30 @@ break; } } - if (bad_clone_list[i].name8 == NULL) + if (bad_clone_list[i].name8 == NULL) { printk(" not found (invalid signature %2.2x %2.2x).\n", SA_prom[14], SA_prom[15]); - return -ENXIO; + ret = -ENXIO; + goto err_out; } #else printk(" not found.\n"); - return -ENXIO; + ret = -ENXIO; + goto err_out; #endif } - if (pci_irq_line) - dev->irq = pci_irq_line; - - if (dev->irq < 2) + if (dev->irq < 2) { - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */ outb_p(0x00, ioaddr + EN0_RCNTLO); outb_p(0x00, ioaddr + EN0_RCNTHI); outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */ mdelay(10); /* wait 10ms for interrupt to propagate */ outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ - dev->irq = autoirq_report(0); + dev->irq = probe_irq_off(cookie); if (ei_debug > 2) printk(" autoirq is %d\n", dev->irq); } else if (dev->irq == 2) @@ -482,31 +407,27 @@ if (! dev->irq) { printk(" failed to detect IRQ line.\n"); - return -EAGAIN; + ret = -EAGAIN; + goto err_out; } /* Allocate dev->priv and fill in 8390 specific dev fields. */ - if (ethdev_init(dev)) + if (ethdev_init(dev)) { printk (" unable to get memory for dev->priv.\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err_out; } - + /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - - { - int irqval = request_irq(dev->irq, ei_interrupt, - pci_irq_line ? SA_SHIRQ : 0, name, dev); - if (irqval) { - printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); - kfree(dev->priv); - dev->priv = NULL; - return -EAGAIN; - } + ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); + if (ret) { + printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); + goto err_out_kfree; } + dev->base_addr = ioaddr; - request_region(ioaddr, NE_IO_EXTENT, name); for(i = 0; i < ETHER_ADDR_LEN; i++) { printk(" %2.2x", SA_prom[i]); @@ -536,6 +457,13 @@ dev->stop = &ne_close; NS8390_init(dev, 0); return 0; + +err_out_kfree: + kfree(dev->priv); + dev->priv = NULL; +err_out: + release_region(ioaddr, NE_IO_EXTENT); + return ret; } static int ne_open(struct net_device *dev) @@ -589,7 +517,7 @@ /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) + if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " "[DMAstat:%d][irqlock:%d].\n", @@ -628,7 +556,7 @@ char *buf = skb->data; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) + if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_block_input " "[DMAstat:%d][irqlock:%d].\n", @@ -642,10 +570,10 @@ outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); - if (ei_status.word16) + if (ei_status.word16) { insw(NE_BASE + NE_DATAPORT,buf,count>>1); - if (count & 0x01) + if (count & 0x01) { buf[count-1] = inb(NE_BASE + NE_DATAPORT); #ifdef NE_SANITY_CHECK @@ -662,7 +590,7 @@ this message you either 1) have a slightly incompatible clone or 2) have noise/speed problems with your bus. */ - if (ei_debug > 1) + if (ei_debug > 1) { /* DMA termination address check... */ int addr, tries = 20; @@ -697,12 +625,12 @@ /* Round the count up for word writes. Do we need to do this? What effect will an odd byte count have on the 8390? I should check someday. */ - + if (ei_status.word16 && (count & 0x01)) count++; /* This *shouldn't* happen. If it does, it's the last thing you'll see */ - if (ei_status.dmaing) + if (ei_status.dmaing) { printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." "[DMAstat:%d][irqlock:%d]\n", @@ -722,7 +650,7 @@ Crynwr packet driver -- the NatSemi method doesn't work. Actually this doesn't always work either, but if you have problems with your NEx000 this is better than nothing! */ - + outb_p(0x42, nic_base + EN0_RCNTLO); outb_p(0x00, nic_base + EN0_RCNTHI); outb_p(0x42, nic_base + EN0_RSARLO); @@ -752,8 +680,8 @@ #ifdef NE_SANITY_CHECK /* This was for the ALPHA version only, but enough people have been encountering problems so it is still here. */ - - if (ei_debug > 1) + + if (ei_debug > 1) { /* DMA termination address check... */ int addr, tries = 20; @@ -765,7 +693,7 @@ break; } while (--tries > 0); - if (tries <= 0) + if (tries <= 0) { printk(KERN_WARNING "%s: Tx packet transfer address mismatch," "%#4.4x (expected) vs. %#4.4x (actual).\n", @@ -801,10 +729,6 @@ MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); -#ifdef CONFIG_PCI -MODULE_PARM(probe_pci, "i"); -#endif - /* This is set up so that no ISA autoprobe takes place. We can't guarantee that the ne2k probe is the last 8390 based probe to take place (as it is at boot) and so the probe will get confused by any other 8390 cards. @@ -814,9 +738,6 @@ { int this_dev, found = 0; - if (load_8390_module("ne.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { struct net_device *dev = &dev_ne[this_dev]; dev->irq = irq[this_dev]; @@ -833,8 +754,7 @@ if (io[this_dev] != 0) printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); else - printk(KERN_NOTICE "ne.c: No PCI cards found. Use \"io=0xNNN\" value(s) for ISA cards.\n"); - unload_8390_module(); + printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for ISA cards.\n"); return -ENXIO; } return 0; @@ -857,7 +777,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ne2.c linux/drivers/net/ne2.c --- v2.4.0-test10/linux/drivers/net/ne2.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/ne2.c Sat Nov 11 18:56:58 2000 @@ -200,12 +200,12 @@ static int __init ne2_probe1(struct net_device *dev, int slot) { - int i, base_addr, irq; + int i, base_addr, irq, retval; unsigned char POS; unsigned char SA_prom[32]; const char *name = "NE/2"; int start_page, stop_page; - static unsigned version_printed = 0; + static unsigned version_printed; if (ei_debug && version_printed++ == 0) printk(version); @@ -226,6 +226,9 @@ base_addr = addresses[i - 1]; irq = irqs[(POS & 0x60)>>5]; + if (!request_region(base_addr, NE_IO_EXTENT, dev->name)) + return -EBUSY; + #ifdef DEBUG printk("POS info : pos 2 = %#x ; base = %#x ; irq = %ld\n", POS, base_addr, irq); @@ -239,7 +242,8 @@ outb(0x21, base_addr + NE_CMD); if (inb(base_addr + NE_CMD) != 0x21) { printk("NE/2 adapter not responding\n"); - return -ENODEV; + retval = -ENODEV; + goto out; } /* In the crynwr sources they do a RAM-test here. I skip it. I suppose @@ -260,7 +264,8 @@ while ((inb_p(base_addr + EN0_ISR) & ENISR_RESET) == 0) if (jiffies - reset_start_time > 2*HZ/100) { printk(" not found (no reset ack).\n"); - return -ENODEV; + retval = -ENODEV; + goto out; } outb_p(0xff, base_addr + EN0_ISR); /* Ack all intr. */ @@ -309,14 +314,11 @@ /* Snarf the interrupt now. There's no point in waiting since we cannot share and the board will usually be enabled. */ - { - int irqval = request_irq(dev->irq, ei_interrupt, - 0, name, dev); - if (irqval) { - printk (" unable to get IRQ %d (irqval=%d).\n", - dev->irq, +irqval); - return -EAGAIN; - } + retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (retval) { + printk (" unable to get IRQ %d (irqval=%d).\n", + dev->irq, retval); + goto out; } dev->base_addr = base_addr; @@ -325,11 +327,10 @@ if (ethdev_init(dev)) { printk (" unable to get memory for dev->priv.\n"); free_irq(dev->irq, dev); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - request_region(base_addr, NE_IO_EXTENT, name); - for(i = 0; i < ETHER_ADDR_LEN; i++) { printk(" %2.2x", SA_prom[i]); dev->dev_addr[i] = SA_prom[i]; @@ -362,6 +363,9 @@ dev->stop = &ne_close; NS8390_init(dev, 0); return 0; +out: + release_region(base_addr, NE_IO_EXTENT); + return retval; } static int ne_open(struct net_device *dev) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c --- v2.4.0-test10/linux/drivers/net/ne2k-pci.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/ne2k-pci.c Tue Nov 7 11:02:24 2000 @@ -2,29 +2,48 @@ /* A Linux device driver for PCI NE2000 clones. - Authorship and other copyrights: - 1992-1998 by Donald Becker, NE2000 core and various modifications. + Authors and other copyright holders: + 1992-2000 by Donald Becker, NE2000 core and various modifications. 1995-1998 by Paul Gortmaker, core modifications and PCI support. - Copyright 1993 assigned to the United States Government as represented by the Director, National Security Agency. - This software may be used and distributed according to the terms - of the GNU Public License, incorporated herein by reference. - - The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O - Center of Excellence in Space Data and Information Sciences - Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771 - - People are making PCI ne2000 clones! Oh the horror, the horror... + This software may be used and distributed according to the terms of + the GNU General Public License (GPL), incorporated herein by reference. + Drivers based on or derived from this code fall under the GPL and must + retain the authorship, copyright and license notice. This file is not + a complete program and may only be used when the entire operating + system is licensed under the GPL. + + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation + 410 Severn Ave., Suite 210 + Annapolis MD 21403 Issues remaining: - No full-duplex support. + People are making PCI ne2000 clones! Oh the horror, the horror... + Limited full-duplex support. */ -/* Our copyright info must remain in the binary. */ -static const char *version = -"ne2k-pci.c:vpre-1.00e 5/27/99 D. Becker/P. Gortmaker http://cesdis.gsfc.nasa.gov/linux/drivers/ne2k-pci.html\n"; +/* These identify the driver base version and may not be removed. */ +static const char version1[] = +"ne2k-pci.c:v1.02 10/19/2000 D. Becker/P. Gortmaker\n"; +static const char version2[] = +" http://www.scyld.com/network/ne2k-pci.html\n"; + +/* The user-configurable values. + These may be modified when a driver module is loaded.*/ + +static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ + +#define MAX_UNITS 8 /* More are supported, limit only on options */ +/* Used to pass the full-duplex flag, etc. */ +static int full_duplex[MAX_UNITS]; +static int options[MAX_UNITS]; + +/* Force a non std. amount of memory. Units are 256 byte pages. */ +/* #define PACKETBUF_MEMSIZE 0x40 */ + #include #include @@ -48,8 +67,11 @@ #define outsl outsl_ns #endif -/* Set statically or when loading the driver module. */ -static int debug = 1; +MODULE_AUTHOR("Donald Becker / Paul Gortmaker"); +MODULE_DESCRIPTION("PCI NE2000 clone driver"); +MODULE_PARM(debug, "i"); +MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); +MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); /* Some defines that people can play with if so inclined. */ @@ -59,19 +81,16 @@ /* Do we implement the read before write bugfix ? */ /* #define NE_RW_BUGFIX */ -/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ -/* #define PACKETBUF_MEMSIZE 0x40 */ - -#define ne2k_flags reg0 /* Rename an existing field to store flags! */ - -/* Only the low 8 bits are usable for non-init-time flags! */ +/* Flags. We rename an existing ei_status field to store flags! */ +/* Thus only the low 8 bits are usable for non-init-time flags. */ +#define ne2k_flags reg0 enum { - HOLTEK_FDX=1, /* Full duplex -> set 0x80 at offset 0x20. */ - ONLY_16BIT_IO=2, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ + ONLY_16BIT_IO=8, ONLY_32BIT_IO=4, /* Chip can do only 16/32-bit xfers. */ + FORCE_FDX=0x20, /* User override. */ + REALTEK_FDX=0x40, HOLTEK_FDX=0x80, STOP_PG_0x60=0x100, }; - enum ne2k_pci_chipsets { CH_RealTek_RTL_8029 = 0, CH_Winbond_89C940, @@ -90,7 +109,7 @@ char *name; int flags; } pci_clone_list[] __devinitdata = { - {"RealTek RTL-8029", 0}, + {"RealTek RTL-8029", REALTEK_FDX}, {"Winbond 89C940", 0}, {"Compex RL2000", 0}, {"KTI ET32P2", 0}, @@ -145,7 +164,8 @@ -/* No room in the standard 8390 structure for extra info we need. */ +/* There is no room in the standard 8390 structure for extra info we need, + so we build a meta/outer-wrapper structure.. */ struct ne2k_pci_card { struct net_device *dev; struct pci_dev *pci_dev; @@ -171,33 +191,35 @@ const struct pci_device_id *ent) { struct net_device *dev; - int i, irq, reg0, start_page, stop_page; + int i; unsigned char SA_prom[32]; - int chip_idx = ent->driver_data; - static unsigned version_printed = 0; + int start_page, stop_page; + int irq, reg0, chip_idx = ent->driver_data; + static unsigned int fnd_cnt; long ioaddr; - - if (version_printed++ == 0) - printk(KERN_INFO "%s", version); + int flags = pci_clone_list[chip_idx].flags; + + if (fnd_cnt++ == 0) + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; - + if (!ioaddr || ((pci_resource_flags (pdev, 0) & IORESOURCE_IO) == 0)) { printk (KERN_ERR "ne2k-pci: no I/O resource at PCI BAR #0\n"); return -ENODEV; } - + i = pci_enable_device (pdev); if (i) return i; - + if (request_region (ioaddr, NE_IO_EXTENT, "ne2k-pci") == NULL) { printk (KERN_ERR "ne2k-pci: I/O resource 0x%x @ 0x%lx busy\n", NE_IO_EXTENT, ioaddr); return -EBUSY; } - + reg0 = inb(ioaddr); if (reg0 == 0xFF) goto err_out_free_res; @@ -222,7 +244,7 @@ printk (KERN_ERR "ne2k-pci: cannot allocate ethernet device\n"); goto err_out_free_res; } - + /* Reset card. Who knows what dain-bramaged state it was left in. */ { unsigned long reset_start_time = jiffies; @@ -238,7 +260,7 @@ printk("ne2k-pci: Card failure (no reset ack).\n"); goto err_out_free_netdev; } - + outb(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ } @@ -269,7 +291,7 @@ /* Note: all PCI cards have at least 16 bit access, so we don't have to check for 8 bit cards. Most cards permit 32 bit access. */ - if (pci_clone_list[chip_idx].flags & ONLY_32BIT_IO) { + if (flags & ONLY_32BIT_IO) { for (i = 0; i < 4 ; i++) ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT)); } else @@ -280,8 +302,7 @@ outb(0x49, ioaddr + EN0_DCFG); start_page = NESM_START_PG; - stop_page = - pci_clone_list[chip_idx].flags&STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; + stop_page = flags & STOP_PG_0x60 ? 0x60 : NESM_STOP_PG; /* Set up the rest of the parameters. */ dev->irq = irq; @@ -305,7 +326,11 @@ ei_status.tx_start_page = start_page; ei_status.stop_page = stop_page; ei_status.word16 = 1; - ei_status.ne2k_flags = pci_clone_list[chip_idx].flags; + ei_status.ne2k_flags = flags; + if (fnd_cnt < MAX_UNITS) { + if (full_duplex[fnd_cnt] > 0 || (options[fnd_cnt] & FORCE_FDX)) + ei_status.ne2k_flags |= FORCE_FDX; + } ei_status.rx_start_page = start_page + TX_PAGES; #ifdef PACKETBUF_MEMSIZE @@ -331,20 +356,27 @@ } -static int -ne2k_pci_open(struct net_device *dev) +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; } + /* Set full duplex for the chips that we know about. */ + if (ei_status.ne2k_flags & FORCE_FDX) { + long ioaddr = dev->base_addr; + if (ei_status.ne2k_flags & REALTEK_FDX) { + outb(0xC0 + E8390_NODMA, ioaddr + NE_CMD); /* Page 3 */ + outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); + } else if (ei_status.ne2k_flags & HOLTEK_FDX) + outb(inb(ioaddr + 0x20) | 0x80, ioaddr + 0x20); + } ei_open(dev); return 0; } -static int -ne2k_pci_close(struct net_device *dev) +static int ne2k_pci_close(struct net_device *dev) { ei_close(dev); free_irq(dev->irq, dev); @@ -354,8 +386,7 @@ /* Hard reset the card. This used to pause for the same period that a 8390 reset command required, but that shouldn't be necessary. */ -static void -ne2k_pci_reset_8390(struct net_device *dev) +static void ne2k_pci_reset_8390(struct net_device *dev) { unsigned long reset_start_time = jiffies; @@ -380,8 +411,7 @@ we don't need to be concerned with ring wrap as the header will be at the start of a page, so we optimize accordingly. */ -static void -ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) +static void ne2k_pci_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) { long nic_base = dev->base_addr; @@ -418,8 +448,8 @@ The NEx000 doesn't share the on-board packet memory -- you have to put the packet out through the "remote DMA" dataport using outb. */ -static void -ne2k_pci_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) +static void ne2k_pci_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset) { long nic_base = dev->base_addr; char *buf = skb->data; @@ -461,9 +491,8 @@ ei_status.dmaing &= ~0x01; } -static void -ne2k_pci_block_output(struct net_device *dev, int count, - const unsigned char *buf, const int start_page) +static void ne2k_pci_block_output(struct net_device *dev, int count, + const unsigned char *buf, const int start_page) { long nic_base = NE_BASE; unsigned long dma_start; @@ -520,8 +549,8 @@ dma_start = jiffies; while ((inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) - if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ - printk("%s: timeout waiting for Tx RDC.\n", dev->name); + if (jiffies - dma_start > 2) { /* Avoid clock roll-over. */ + printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); ne2k_pci_reset_8390(dev); NS8390_init(dev,1); break; @@ -536,12 +565,10 @@ static void __devexit ne2k_pci_remove_one (struct pci_dev *pdev) { struct net_device *dev = pci_get_drvdata(pdev); - - if (!dev) { - printk (KERN_ERR "bug! ne2k_pci_remove_one called w/o net_device\n"); - return; - } - + + if (!dev) + BUG(); + unregister_netdev(dev); release_region(dev->base_addr, NE_IO_EXTENT); kfree(dev); @@ -559,43 +586,14 @@ static int __init ne2k_pci_init(void) { - int rc; - - if (load_8390_module("ne2k-pci.c")) - return -ENOSYS; - - rc = pci_module_init (&ne2k_driver); - - /* XXX should this test CONFIG_HOTPLUG like pci_module_init? */ - - /* YYY No. If we're returning non-zero, we're being unloaded - * immediately. dwmw2 - */ - if (rc <= 0) - unload_8390_module(); - - return rc; + return pci_module_init (&ne2k_driver); } static void __exit ne2k_pci_cleanup(void) { pci_unregister_driver (&ne2k_driver); - unload_8390_module(); } module_init(ne2k_pci_init); module_exit(ne2k_pci_cleanup); - - -/* - * Local variables: - * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/ -c ne2k-pci.c" - * alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/ -c ne2k-pci.c" - * c-indent-level: 4 - * c-basic-offset: 4 - * tab-width: 4 - * version-control: t - * kept-new-versions: 5 - * End: - */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c --- v2.4.0-test10/linux/drivers/net/ne3210.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/ne3210.c Tue Nov 7 11:06:09 2000 @@ -44,7 +44,7 @@ #include "8390.h" int ne3210_probe(struct net_device *dev); -int ne3210_probe1(struct net_device *dev, int ioaddr); +static int ne3210_probe1(struct net_device *dev, int ioaddr); static int ne3210_open(struct net_device *dev); static int ne3210_close(struct net_device *dev); @@ -112,23 +112,26 @@ } /* EISA spec allows for up to 16 slots, but 8 is typical. */ - for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) { - if (check_region(ioaddr , NE3210_IO_EXTENT)) - continue; + for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) if (ne3210_probe1(dev, ioaddr) == 0) return 0; - } return -ENODEV; } -int __init ne3210_probe1(struct net_device *dev, int ioaddr) +static int __init ne3210_probe1(struct net_device *dev, int ioaddr) { - int i; + int i, retval; unsigned long eisa_id; const char *ifmap[] = {"UTP", "?", "BNC", "AUI"}; - if (inb_p(ioaddr + NE3210_ID_PORT) == 0xff) return -ENODEV; + if (!request_region(dev->base_addr, NE3210_IO_EXTENT, dev->name)) + return -EBUSY; + + if (inb_p(ioaddr + NE3210_ID_PORT) == 0xff) { + retval = -ENODEV; + goto out; + } #if NE3210_DEBUG & NE3210_D_PROBE printk("ne3210-debug: probe at %#x, ID %#8x\n", ioaddr, inl(ioaddr + NE3210_ID_PORT)); @@ -140,7 +143,8 @@ /* Check the EISA ID of the card. */ eisa_id = inl(ioaddr + NE3210_ID_PORT); if (eisa_id != NE3210_ID) { - return -ENODEV; + retval = -ENODEV; + goto out; } @@ -153,14 +157,16 @@ for(i = 0; i < ETHER_ADDR_LEN; i++) printk(" %02x", inb(ioaddr + NE3210_SA_PROM + i)); printk(" (invalid prefix).\n"); - return -ENODEV; + retval = -ENODEV; + goto out; } #endif /* Allocate dev->priv and fill in 8390 specific dev fields. */ if (ethdev_init(dev)) { printk ("ne3210.c: unable to allocate memory for dev->priv!\n"); - return -ENOMEM; + retval = -ENOMEM; + goto out; } printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr:", @@ -181,11 +187,10 @@ } printk(" IRQ %d,", dev->irq); - if (request_irq(dev->irq, ei_interrupt, 0, "ne3210", dev)) { + retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (retval) { printk (" unable to get IRQ %d.\n", dev->irq); - kfree(dev->priv); - dev->priv = NULL; - return -EAGAIN; + goto out1; } if (dev->mem_start == 0) { @@ -211,20 +216,16 @@ printk(KERN_CRIT "ne3210.c: Use EISA SCU to set card memory below 1MB,\n"); printk(KERN_CRIT "ne3210.c: or to an address above 0x%lx.\n", virt_to_bus(high_memory)); printk(KERN_CRIT "ne3210.c: Driver NOT installed.\n"); - free_irq(dev->irq, dev); - kfree(dev->priv); - dev->priv = NULL; - return -EINVAL; + retval = -EINVAL; + goto out2; } dev->mem_start = (unsigned long)ioremap(dev->mem_start, NE3210_STOP_PG*0x100); if (dev->mem_start == 0) { printk(KERN_ERR "ne3210.c: Unable to remap card memory above 1MB !!\n"); printk(KERN_ERR "ne3210.c: Try using EISA SCU to set memory below 1MB.\n"); printk(KERN_ERR "ne3210.c: Driver NOT installed.\n"); - free_irq(dev->irq, dev); - kfree(dev->priv); - dev->priv = NULL; - return -EAGAIN; + retval = -EAGAIN; + goto out2; } ei_status.reg0 = 1; /* Use as remap flag */ printk("ne3210.c: remapped %dkB card memory to virtual address %#lx\n", @@ -237,7 +238,6 @@ /* The 8390 offset is zero for the NE3210 */ dev->base_addr = ioaddr; - request_region(dev->base_addr, NE3210_IO_EXTENT, "ne3210"); ei_status.name = "NE3210"; ei_status.tx_start_page = NE3210_START_PG; @@ -257,6 +257,14 @@ dev->stop = &ne3210_close; NS8390_init(dev, 0); return 0; +out2: + free_irq(dev->irq, dev); +out1: + kfree(dev->priv); + dev->priv = NULL; +out: + release_region(ioaddr, NE3210_IO_EXTENT); + return retval; } /* @@ -367,9 +375,6 @@ { int this_dev, found = 0; - if (load_8390_module("ne3210.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) { struct net_device *dev = &dev_ne3210[this_dev]; dev->irq = irq[this_dev]; @@ -383,7 +388,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -398,16 +402,15 @@ for (this_dev = 0; this_dev < MAX_NE3210_CARDS; this_dev++) { struct net_device *dev = &dev_ne3210[this_dev]; if (dev->priv != NULL) { - void *priv = dev->priv; free_irq(dev->irq, dev); release_region(dev->base_addr, NE3210_IO_EXTENT); if (ei_status.reg0) iounmap((void *)dev->mem_start); unregister_netdev(dev); - kfree(priv); + kfree(dev->priv); + dev->priv = NULL; } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/oaknet.c linux/drivers/net/oaknet.c --- v2.4.0-test10/linux/drivers/net/oaknet.c Mon Jun 19 13:30:56 2000 +++ linux/drivers/net/oaknet.c Tue Nov 7 10:59:42 2000 @@ -664,25 +664,10 @@ */ static int __init oaknet_init_module (void) { - int status; - - /* - * We're dependent on the 8390 generic driver module, make - * sure its symbols are loaded. - */ - - if (load_8390_module("oaknet.c")) - return (-ENOSYS); - if (oaknet_devs != NULL) return (-EBUSY); - status = oaknet_init() - - if (status != 0) - unload_8390_module(); - - return (status); + return (oaknet_init()); } /* @@ -704,7 +689,6 @@ oaknet_devs = NULL; - unload_8390_module(); } module_init(oaknet_init_module); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/pcmcia/Config.in linux/drivers/net/pcmcia/Config.in --- v2.4.0-test10/linux/drivers/net/pcmcia/Config.in Sun Aug 13 10:21:20 2000 +++ linux/drivers/net/pcmcia/Config.in Sat Nov 11 18:56:58 2000 @@ -36,7 +36,8 @@ "$CONFIG_PCMCIA_FMVJ18X" = "y" -o "$CONFIG_PCMCIA_PCNET" = "y" -o \ "$CONFIG_PCMCIA_NMCLAN" = "y" -o "$CONFIG_PCMCIA_SMC91C92" = "y" -o \ "$CONFIG_PCMCIA_XIRC2PS" = "y" -o "$CONFIG_PCMCIA_RAYCS" = "y" -o \ - "$CONFIG_PCMCIA_NETWAVE" = "y" -o "$CONFIG_PCMCIA_WAVELAN" = "y" ]; then + "$CONFIG_PCMCIA_NETWAVE" = "y" -o "$CONFIG_PCMCIA_WAVELAN" = "y" -o \ + "$CONFIG_PCMCIA_XIRTULIP" = "y" ]; then define_bool CONFIG_PCMCIA_NETCARD y fi diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c --- v2.4.0-test10/linux/drivers/net/pcmcia/xircom_tulip_cb.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/pcmcia/xircom_tulip_cb.c Tue Nov 7 11:09:19 2000 @@ -466,7 +466,7 @@ restore_flags(flags); return; } - newcsr6 &= 0x726cfeca; /* mask out the reserved CSR6 bits that always */ + newcsr6 &= 0x726cfecb; /* mask out the reserved CSR6 bits that always */ /* read 0 on the Xircom cards */ newcsr6 |= 0x320c0000; /* or in the reserved bits that always read 1 */ currcsr6 = inl(ioaddr + CSR6); @@ -1350,7 +1350,7 @@ tp->tx_ring[0].length = 0x08000000 | 192; /* Lie about the address of our setup frame to make the */ /* chip happy */ - tp->tx_ring[0].buffer1 = (virt_to_bus(tp->setup_frame) + 4); + tp->tx_ring[0].buffer1 = virt_to_bus(tp->setup_frame); tp->tx_ring[0].status = DescOwned; tp->cur_tx++; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c --- v2.4.0-test10/linux/drivers/net/pppoe.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/pppoe.c Fri Nov 17 16:48:51 2000 @@ -5,7 +5,7 @@ * PPPoE --- PPP over Ethernet (RFC 2516) * * - * Version: 0.6.3 + * Version: 0.6.4 * * 030700 : Fixed connect logic to allow for disconnect. * 270700 : Fixed potential SMP problems; we must protect against @@ -13,12 +13,11 @@ * and ppp_unregister_channel. * 040800 : Respect reference count mechanisms on net-devices. * 200800 : fix kfree(skb) in pppoe_rcv (acme) - * * Module reference count is decremented in the right spot now, * guards against sock_put not actually freeing the sk * in pppoe_release. - * - * 051000 : Initialization cleanup + * 051000 : Initialization cleanup. + * 111100 : Fix recvmsg. * * Author: Michal Ostrowski * Contributors: @@ -292,9 +291,7 @@ static struct notifier_block pppoe_notifier = { - pppoe_device_event, - NULL, - 0 + notifier_call: pppoe_device_event, }; @@ -535,13 +532,10 @@ if (po->pppoe_dev) dev_put(po->pppoe_dev); - /* Should also do a queue purge here */ - sock_orphan(sk); sock->sk = NULL; skb_queue_purge(&sk->receive_queue); - sock_put(sk); return error; @@ -568,7 +562,7 @@ if ((sk->state & PPPOX_CONNECTED) && sp->sa_addr.pppoe.sid) goto end; - /* Check for already disconnected sockets, + /* Check for already disconnected sockets, on attempts to disconnect */ error = -EALREADY; if((sk->state & PPPOX_DEAD) && !sp->sa_addr.pppoe.sid ) @@ -592,7 +586,7 @@ /* Don't re-bind if sid==0 */ if (sp->sa_addr.pppoe.sid != 0) { dev = dev_get_by_name(sp->sa_addr.pppoe.dev); - + error = -ENODEV; if (!dev) goto end; @@ -728,6 +722,7 @@ if (!relay_po) break; + sock_put(relay_po->sk); sk->state |= PPPOX_RELAY; err = 0; break; @@ -759,7 +754,6 @@ struct pppoe_hdr *ph; struct net_device *dev; char *start; - int copied = 0; if (sk->dead || !(sk->state & PPPOX_CONNECTED)) { error = -ENOTCONN; @@ -775,6 +769,11 @@ dev = sk->protinfo.pppox->pppoe_dev; + error = -EMSGSIZE; + if(total_len > dev->mtu+dev->hard_header_len) + goto end; + + skb = sock_wmalloc(sk, total_len + dev->hard_header_len + 32, 0, GFP_KERNEL); if (!skb) { @@ -795,21 +794,25 @@ ph = (struct pppoe_hdr *) skb_put(skb, total_len + sizeof(struct pppoe_hdr)); start = (char *) &ph->tag[0]; - error = copied = memcpy_fromiovec( start, m->msg_iov, m->msg_iovlen); - if( error <= 0 ) - goto end; + error = memcpy_fromiovec( start, m->msg_iov, total_len); + + if (error < 0) { + kfree_skb(skb); + goto end; + } + error = total_len; dev->hard_header(skb, dev, ETH_P_PPP_SES, sk->protinfo.pppox->pppoe_pa.remote, - NULL, copied); + NULL, total_len); memcpy(ph, &hdr, sizeof(struct pppoe_hdr)); - ph->length = htons(copied); + ph->length = htons(total_len); dev_queue_xmit(skb); -end: + end: release_sock(sk); return error; } @@ -1027,7 +1030,7 @@ int err = register_pppox_proto(PX_PROTO_OE, &pppoe_proto); if (err == 0) { - printk(KERN_INFO "Registered PPPoE v0.6.3\n"); + printk(KERN_INFO "Registered PPPoE v0.6.4\n"); dev_add_pack(&pppoes_ptype); register_netdevice_notifier(&pppoe_notifier); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c --- v2.4.0-test10/linux/drivers/net/rrunner.c Sun Oct 8 10:50:19 2000 +++ linux/drivers/net/rrunner.c Thu Nov 16 12:51:28 2000 @@ -1548,74 +1548,76 @@ unsigned int i; int error = -EOPNOTSUPP; - rrpriv = (struct rr_private *)dev->priv; - - spin_lock(&rrpriv->lock); + rrpriv = dev->priv; switch(cmd){ case SIOCRRGFW: if (!capable(CAP_SYS_RAWIO)){ - error = -EPERM; - goto out; - } - - if (rrpriv->fw_running){ - printk("%s: Firmware already running\n", dev->name); - error = -EPERM; - goto out; + return -EPERM; } image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); if (!image){ printk(KERN_ERR "%s: Unable to allocate memory " "for EEPROM image\n", dev->name); - error = -ENOMEM; - goto out; + return -ENOMEM; + } + + spin_lock(&rrpriv->lock); + + if (rrpriv->fw_running){ + printk("%s: Firmware already running\n", dev->name); + error = -EPERM; + goto out_spin; } + i = rr_read_eeprom(rrpriv, 0, image, EEPROM_BYTES); if (i != EEPROM_BYTES){ - kfree(image); - printk(KERN_ERR "%s: Error reading EEPROM\n", - dev->name); + printk(KERN_ERR "%s: Error reading EEPROM\n", dev->name); error = -EFAULT; - goto out; + goto out_spin; } + spin_unlock(&rrpriv->lock); error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES); if (error) error = -EFAULT; kfree(image); - break; + return error; + case SIOCRRPFW: if (!capable(CAP_SYS_RAWIO)){ - error = -EPERM; - goto out; - } - - if (rrpriv->fw_running){ - printk("%s: Firmware already running\n", dev->name); - error = -EPERM; - goto out; + return -EPERM; } image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); if (!image){ printk(KERN_ERR "%s: Unable to allocate memory " "for EEPROM image\n", dev->name); - error = -ENOMEM; - goto out; + return -ENOMEM; } oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL); if (!oldimage){ + kfree(image); printk(KERN_ERR "%s: Unable to allocate memory " "for old EEPROM image\n", dev->name); - error = -ENOMEM; - goto out; + return -ENOMEM; } error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES); - if (error) - error = -EFAULT; + if (error) { + kfree(image); + kfree(oldimage); + return -EFAULT; + } + + spin_lock(&rrpriv->lock); + if (rrpriv->fw_running){ + kfree(oldimage); + printk("%s: Firmware already running\n", dev->name); + error = -EPERM; + goto out_spin; + } printk("%s: Updating EEPROM firmware\n", dev->name); @@ -1629,6 +1631,7 @@ printk(KERN_ERR "%s: Error reading back EEPROM " "image\n", dev->name); + spin_unlock(&rrpriv->lock); error = memcmp(image, oldimage, EEPROM_BYTES); if (error){ printk(KERN_ERR "%s: Error verifying EEPROM image\n", @@ -1637,16 +1640,16 @@ } kfree(image); kfree(oldimage); - break; + return error; + case SIOCRRID: - error = put_user(0x52523032, (int *)(&rq->ifr_data[0])); - if (error) - error = -EFAULT; - break; + return put_user(0x52523032, (int *)(&rq->ifr_data[0])); default: + return error; } - out: + out_spin: + kfree(image); spin_unlock(&rrpriv->lock); return error; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c --- v2.4.0-test10/linux/drivers/net/seeq8005.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/seeq8005.c Sat Nov 11 18:56:58 2000 @@ -116,13 +116,9 @@ else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; seeq8005_portlist[i]; i++) { - int ioaddr = seeq8005_portlist[i]; - if (check_region(ioaddr, SEEQ8005_IO_EXTENT)) - continue; - if (seeq8005_probe1(dev, ioaddr) == 0) + for (i = 0; seeq8005_portlist[i]; i++) + if (seeq8005_probe1(dev, seeq8005_portlist[i]) == 0) return 0; - } return -ENODEV; } @@ -133,7 +129,7 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr) { - static unsigned version_printed = 0; + static unsigned version_printed; int i,j; unsigned char SA_prom[32]; int old_cfg1; @@ -141,33 +137,42 @@ int old_stat; int old_dmaar; int old_rear; + int retval; + + if (!request_region(ioaddr, SEEQ8005_IO_EXTENT, "seeq8005")) + return -ENODEV; if (net_debug>1) printk("seeq8005: probing at 0x%x\n",ioaddr); old_stat = inw(SEEQ_STATUS); /* read status register */ - if (old_stat == 0xffff) - return -ENODEV; /* assume that 0xffff == no device */ + if (old_stat == 0xffff) { + retval = -ENODEV; + goto out; /* assume that 0xffff == no device */ + } if ( (old_stat & 0x1800) != 0x1800 ) { /* assume that unused bits are 1, as my manual says */ if (net_debug>1) { printk("seeq8005: reserved stat bits != 0x1800\n"); printk(" == 0x%04x\n",old_stat); } - return -ENODEV; + retval = -ENODEV; + goto out; } old_rear = inw(SEEQ_REA); if (old_rear == 0xffff) { outw(0,SEEQ_REA); if (inw(SEEQ_REA) == 0xffff) { /* assume that 0xffff == no device */ - return -ENODEV; + retval = -ENODEV; + goto out; } } else if ((old_rear & 0xff00) != 0xff00) { /* assume that unused bits are 1 */ if (net_debug>1) { printk("seeq8005: unused rear bits != 0xff00\n"); printk(" == 0x%04x\n",old_rear); } - return -ENODEV; + retval = -ENODEV; + goto out; } old_cfg2 = inw(SEEQ_CFG2); /* read CFG2 register */ @@ -185,8 +190,8 @@ outw( SEEQCMD_FIFO_WRITE | SEEQCMD_SET_ALL_OFF, SEEQ_CMD); /* setup for reading PROM */ outw( 0, SEEQ_DMAAR); /* set starting PROM address */ outw( SEEQCFG1_BUFFER_PROM, SEEQ_CFG1); /* set buffer to look at PROM */ - - + + j=0; for(i=0; i <32; i++) { j+= SA_prom[i] = inw(SEEQ_BUFFER) & 0xff; @@ -201,7 +206,8 @@ outw( old_stat, SEEQ_STATUS); outw( old_dmaar, SEEQ_DMAAR); outw( old_cfg1, SEEQ_CFG1); - return -ENODEV; + retval = -ENODEV; + goto out; } #endif @@ -279,11 +285,11 @@ if (dev->irq == 0xff) ; /* Do nothing: a user-level program will set it. */ else if (dev->irq < 2) { /* "Auto-IRQ" */ - autoirq_setup(0); + unsigned long cookie = probe_irq_on(); outw( SEEQCMD_RX_INT_EN | SEEQCMD_SET_RX_ON | SEEQCMD_SET_RX_OFF, SEEQ_CMD ); - dev->irq = autoirq_report(0); + dev->irq = probe_irq_off(cookie); if (net_debug >= 2) printk(" autoirq is %d\n", dev->irq); @@ -299,14 +305,12 @@ if (irqval) { printk ("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, irqval); - return -EAGAIN; + retval = -EAGAIN; + goto out; } } #endif - /* Grab the region so we can find another board if autoIRQ fails. */ - request_region(ioaddr, SEEQ8005_IO_EXTENT,"seeq8005"); - /* Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); if (dev->priv == NULL) @@ -327,6 +331,9 @@ dev->flags &= ~IFF_MULTICAST; return 0; +out: + release_region(ioaddr, SEEQ8005_IO_EXTENT); + return retval; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/sis900.c linux/drivers/net/sis900.c --- v2.4.0-test10/linux/drivers/net/sis900.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/net/sis900.c Sat Nov 11 18:56:58 2000 @@ -1,6 +1,6 @@ /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux. Copyright 1999 Silicon Integrated System Corporation - Revision: 1.07.04 Sep. 6 2000 + Revision: 1.07.06 Nov. 7 2000 Modified from the driver which is originally written by Donald Becker. @@ -18,6 +18,8 @@ preliminary Rev. 1.0 Jan. 18, 1998 http://www.sis.com.tw/support/databook.htm + Rev 1.07.06 Nov. 7 2000 Jeff Garzik some bug fix and cleaning + Rev 1.07.05 Nov. 6 2000 metapirat contribute media type select by ifconfig Rev 1.07.04 Sep. 6 2000 Lei-Chun Chang added ICS1893 PHY support Rev 1.07.03 Aug. 24 2000 Lei-Chun Chang (lcchang@sis.com.tw) modified 630E eqaulizer workaroung rule Rev 1.07.01 Aug. 08 2000 Ollie Lho minor update for SiS 630E and SiS 630E A1 @@ -56,21 +58,19 @@ #include "sis900.h" static const char *version = -"sis900.c: v1.07.04 09/06/2000\n"; +"sis900.c: v1.07.06 11/07/2000\n"; static int max_interrupt_work = 20; static int multicast_filter_limit = 128; #define sis900_debug debug -static int sis900_debug = 0; +static int sis900_debug; /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (4*HZ) /* SiS 900 is capable of 32 bits BM DMA */ #define SIS900_DMA_MASK 0xffffffff -static struct net_device * sis900_mac_probe (struct pci_dev * pci_dev, - char *card_name); enum { SIS_900 = 0, SIS_7016 @@ -140,7 +140,6 @@ BufferDesc rx_ring[NUM_RX_DESC]; unsigned int tx_full; /* The Tx queue is full. */ - int LinkOn; }; MODULE_AUTHOR("Jim Huang , Ollie Lho "); @@ -171,39 +170,10 @@ static void set_rx_mode(struct net_device *net_dev); static void sis900_reset(struct net_device *net_dev); static void sis630e_set_eq(struct net_device *net_dev); - -/* walk through every ethernet PCI devices to see if some of them are matched with our card list*/ -static int __init sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) -{ - u32 pci_io_base; - - if (!pci_dma_supported(pci_dev, SIS900_DMA_MASK)) { - printk(KERN_ERR "sis900.c: architecture does not support " - "32bit PCI busmaster DMA\n"); - return -ENODEV; - } - - pci_io_base = pci_resource_start(pci_dev, 0); - if (check_region(pci_io_base, SIS900_TOTAL_SIZE)) { - printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%08x\n", - pci_io_base); - return -ENODEV; - } - - /* setup various bits in PCI command register */ - if (pci_enable_device (pci_dev)) - return -ENODEV; - pci_set_master(pci_dev); - - /* do the real low level jobs */ - if (sis900_mac_probe(pci_dev, card_names[pci_id->driver_data]) == NULL) - return -ENODEV; - - return 0; -} +static int sis900_set_config(struct net_device *dev, struct ifmap *map); /* older SiS900 and friends, use EEPROM to store MAC address */ -static int sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) { long ioaddr = pci_resource_start(pci_dev, 0); u16 signature; @@ -225,7 +195,7 @@ } /* SiS630E model, use APC CMOS RAM to store MAC address */ -static int sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) +static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev) { struct pci_dev *isa_bridge = NULL; u8 reg; @@ -247,17 +217,36 @@ return 1; } -static struct net_device * __init sis900_mac_probe (struct pci_dev * pci_dev, char * card_name) +static int __devinit sis900_probe (struct pci_dev *pci_dev, const struct pci_device_id *pci_id) { struct sis900_private *sis_priv; long ioaddr = pci_resource_start(pci_dev, 0); - struct net_device *net_dev = NULL; + struct net_device *net_dev; int irq = pci_dev->irq; int i, ret = 0; u8 revision; + char *card_name = card_names[pci_id->driver_data]; + + if (!pci_dma_supported(pci_dev, SIS900_DMA_MASK)) { + printk(KERN_ERR "sis900.c: architecture does not support " + "32bit PCI busmaster DMA\n"); + return -ENODEV; + } - if ((net_dev = init_etherdev(net_dev, 0)) == NULL) - return NULL; + /* setup various bits in PCI command register */ + if (pci_enable_device (pci_dev)) + return -ENODEV; + pci_set_master(pci_dev); + + net_dev = init_etherdev(NULL, sizeof(struct sis900_private)); + if (!net_dev) + return -ENOMEM; + + 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); + ret = -EBUSY; + goto err_out; + } pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision); if (revision == SIS630E_REV || revision == SIS630EA1_REV) @@ -268,8 +257,8 @@ ret = sis900_get_mac_addr(pci_dev, net_dev); if (ret == 0) { - unregister_netdevice(net_dev); - return NULL; + ret = -ENODEV; + goto err_out_region; } /* print some information about our NIC */ @@ -279,16 +268,9 @@ printk("%2.2x:", (u8)net_dev->dev_addr[i]); printk("%2.2x.\n", net_dev->dev_addr[i]); - if ((net_dev->priv = kmalloc(sizeof(struct sis900_private), GFP_KERNEL)) == NULL) { - unregister_netdevice(net_dev); - return NULL; - } - sis_priv = net_dev->priv; - memset(sis_priv, 0, sizeof(struct sis900_private)); /* We do a request_region() to register /proc/ioports info. */ - request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name); net_dev->base_addr = ioaddr; net_dev->irq = irq; sis_priv->pci_dev = pci_dev; @@ -296,10 +278,8 @@ /* probe for mii transciver */ if (sis900_mii_probe(net_dev) == 0) { - unregister_netdev(net_dev); - kfree(sis_priv); - release_region(ioaddr, SIS900_TOTAL_SIZE); - return NULL; + ret = -ENODEV; + goto err_out_region; } pci_dev->driver_data = net_dev; @@ -310,12 +290,20 @@ net_dev->hard_start_xmit = &sis900_start_xmit; net_dev->stop = &sis900_close; net_dev->get_stats = &sis900_get_stats; + net_dev->set_config = &sis900_set_config; net_dev->set_multicast_list = &set_rx_mode; net_dev->do_ioctl = &mii_ioctl; net_dev->tx_timeout = sis900_tx_timeout; net_dev->watchdog_timeo = TX_TIMEOUT; - return net_dev; + return 0; + +err_out_region: + release_region(ioaddr, SIS900_TOTAL_SIZE); +err_out: + unregister_netdev(net_dev); + kfree(net_dev); + return ret; } static int __init sis900_mii_probe (struct net_device * net_dev) @@ -385,9 +373,9 @@ } if (sis_priv->mii->status & MII_STAT_LINK) - sis_priv->LinkOn = TRUE; + netif_carrier_on(net_dev); else - sis_priv->LinkOn = FALSE; + netif_carrier_off(net_dev); return 1; } @@ -720,7 +708,7 @@ u16 reg14h, eq_value, max_value=0, min_value=0; int i, maxcount=10; - if (sis_priv->LinkOn == TRUE) { + if (netif_carrier_ok(net_dev)) { reg14h=mdio_read(net_dev, sis_priv->cur_phy, MII_RESV); mdio_write(net_dev, sis_priv->cur_phy, MII_RESV, (0x2200 | reg14h) & 0xBFFF); for (i=0; i < maxcount; i++) { @@ -764,10 +752,10 @@ /* current mii phy is failed to link, try another one */ while (!(status & MII_STAT_LINK)) { if (mii_phy->next == NULL) { - if (sis_priv->LinkOn) { + if (netif_carrier_ok(net_dev)) { /* link stat change from ON to OFF */ next_tick = HZ; - sis_priv->LinkOn = FALSE; + netif_carrier_off(net_dev); /* Equalizer workaroung Rule */ pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision); @@ -785,9 +773,9 @@ status = mdio_read(net_dev, mii_phy->phy_addr, MII_STATUS); } - if (!sis_priv->LinkOn) { + if (!netif_carrier_ok(net_dev)) { /* link stat change forn OFF to ON, read and report link mode */ - sis_priv->LinkOn = TRUE; + netif_carrier_on(net_dev); next_tick = 5*HZ; /* Equalizer workaroung Rule */ @@ -1326,6 +1314,96 @@ return &sis_priv->stats; } +/* Support for media type changes via net_device->set_config */ +static int sis900_set_config(struct net_device *dev, struct ifmap *map) +{ + struct sis900_private *sis_priv = (struct sis900_private *)dev->priv; + struct mii_phy *mii_phy = sis_priv->mii; + + u16 status; + + /* we support only port changes. All other runtime configuration + changes will be ignored (io base and interrupt changes for example)*/ + if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) { + /* we switch on the ifmap->port field. I couldn't find anything + like a definition or standard for the values of that field. + I think the meaning of those values is device specific. But + since I would like to change the media type via the ifconfig + command I use the definition from linux/netdevice.h + (which seems to be different from the ifport(pcmcia) definition) + */ + switch(map->port){ + case IF_PORT_UNKNOWN: /* use auto here */ + dev->if_port = map->port; + /* we are going to change the media type, so the Link will + be temporary down and we need to reflect that here. When + the Link comes up again, it will be sensed by the sis_timer + procedure, which also does all the rest for us */ + netif_carrier_off(dev); + + /* read current state */ + status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); + + /* enable auto negotiation and reset the negotioation + (I dont really know what the auto negatiotiation reset + really means, but it sounds for me right to do one here)*/ + mdio_write(dev, mii_phy->phy_addr, + MII_CONTROL, status | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); + + break; + + case IF_PORT_10BASET: /* 10BaseT */ + dev->if_port = map->port; + + /* we are going to change the media type, so the Link will + be temporary down and we need to reflect that here. When + the Link comes up again, it will be sensed by the sis_timer + procedure, which also does all the rest for us */ + netif_carrier_off(dev); + + /* set Speed to 10Mbps */ + /* read current state */ + status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); + + /* disable auto negotiation and force 10MBit mode*/ + mdio_write(dev, mii_phy->phy_addr, + MII_CONTROL, status & ~(MII_CNTL_SPEED | MII_CNTL_AUTO)); + break; + + case IF_PORT_100BASET: /* 100BaseT */ + case IF_PORT_100BASETX: /* 100BaseTx */ + dev->if_port = map->port; + + /* we are going to change the media type, so the Link will + be temporary down and we need to reflect that here. When + the Link comes up again, it will be sensed by the sis_timer + procedure, which also does all the rest for us */ + netif_carrier_off(dev); + + /* set Speed to 100Mbps */ + /* disable auto negotiation and enable 100MBit Mode */ + status = mdio_read(dev, mii_phy->phy_addr, MII_CONTROL); + mdio_write(dev, mii_phy->phy_addr, + MII_CONTROL, (status & ~MII_CNTL_SPEED) | MII_CNTL_SPEED); + + break; + + case IF_PORT_10BASE2: /* 10Base2 */ + case IF_PORT_AUI: /* AUI */ + case IF_PORT_100BASEFX: /* 100BaseFx */ + /* These Modes are not supported (are they?)*/ + printk(KERN_INFO "Not supported"); + return -EOPNOTSUPP; + break; + + default: + printk(KERN_INFO "Invalid"); + return -EINVAL; + } + } + return 0; +} + /* SiS 900 uses the most sigificant 7 bits to index a 128 bits multicast hash table, which makes this function a little bit different from other drivers */ static u16 sis900_compute_hashtable_index(u8 *addr) @@ -1431,15 +1509,12 @@ outl(PESEL, ioaddr + cfg); } -static void __exit sis900_remove(struct pci_dev *pci_dev) +static void __devexit sis900_remove(struct pci_dev *pci_dev) { struct net_device *net_dev = pci_dev->driver_data; - struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv; unregister_netdev(net_dev); release_region(net_dev->base_addr, SIS900_TOTAL_SIZE); - - kfree(sis_priv); kfree(net_dev); } @@ -1454,16 +1529,9 @@ static int __init sis900_init_module(void) { - if (!pci_present()) /* No PCI bus in this machine! */ - return -ENODEV; - printk(KERN_INFO "%s", version); - if (!pci_register_driver(&sis900_pci_driver)) { - pci_unregister_driver(&sis900_pci_driver); - return -ENODEV; - } - return 0; + return pci_module_init(&sis900_pci_driver); } static void __exit sis900_cleanup_module(void) @@ -1473,3 +1541,4 @@ module_init(sis900_init_module); module_exit(sis900_cleanup_module); + diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/sis900.h linux/drivers/net/sis900.h --- v2.4.0-test10/linux/drivers/net/sis900.h Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/sis900.h Sat Nov 11 18:56:58 2000 @@ -10,7 +10,10 @@ * http://www.sis.com.tw/support/databook.htm */ -/* MAC operation registers of SiS 7016 and SiS 900 ethernet controller */ +/* + * SiS 7016 and SiS 900 ethernet controller registers + */ + /* The I/O extent, SiS 900 needs 256 bytes of io address */ #define SIS900_TOTAL_SIZE 0x100 @@ -252,14 +255,11 @@ #define NUM_TX_DESC 16 /* Number of Tx descriptor registers. */ #define NUM_RX_DESC 16 /* Number of Rx descriptor registers. */ -#define TRUE 1 -#define FALSE 0 - /* PCI stuff, should be move to pic.h */ #define PCI_DEVICE_ID_SI_900 0x900 #define PCI_DEVICE_ID_SI_7016 0x7016 -/* ioctl for accessing MII transveiver */ +/* ioctl for accessing MII transceiver */ #define SIOCGMIIPHY (SIOCDEVPRIVATE) /* Get the PHY in use. */ #define SIOCGMIIREG (SIOCDEVPRIVATE+1) /* Read a PHY register. */ #define SIOCSMIIREG (SIOCDEVPRIVATE+2) /* Write a PHY register */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c --- v2.4.0-test10/linux/drivers/net/smc-mca.c Mon Jun 19 13:42:39 2000 +++ linux/drivers/net/smc-mca.c Sat Nov 11 18:56:58 2000 @@ -194,7 +194,7 @@ } if(!adapter_found) { - return ((base_addr || irq) ? ENXIO : ENODEV); + return ((base_addr || irq) ? -ENXIO : -ENODEV); } /* Adapter found. */ @@ -249,6 +249,9 @@ if (dev->mem_start == 0) /* sanity check, shouldn't happen */ return -ENODEV; + if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) + return -EBUSY; + reg4 = inb(ioaddr + 4) & 0x7f; outb(reg4, ioaddr + 4); @@ -279,14 +282,10 @@ if (ethdev_init(dev)) { printk (KERN_INFO ", no memory for dev->priv.\n"); + release_region(ioaddr, ULTRA_IO_EXTENT); return -ENOMEM; } - /* OK, we are certain this is going to work. Setup the device. - */ - - request_region(ioaddr, ULTRA_IO_EXTENT, "smc-mca"); - /* The 8390 isn't at the base address, so fake the offset */ @@ -322,9 +321,10 @@ static int ultramca_open(struct net_device *dev) { int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ + int retval; - 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; outb(ULTRA_MEMENB, ioaddr); /* Enable memory */ outb(0x80, ioaddr + 5); /* ??? */ @@ -455,9 +455,6 @@ { int this_dev, found = 0; - if (load_8390_module("wd.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ULTRAMCA_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->irq = irq[this_dev]; @@ -468,7 +465,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); printk(KERN_NOTICE "smc-mca.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); return -ENXIO; } @@ -493,7 +489,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c --- v2.4.0-test10/linux/drivers/net/smc-ultra.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/smc-ultra.c Sat Nov 11 18:56:58 2000 @@ -112,41 +112,44 @@ else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; - for (i = 0; ultra_portlist[i]; i++) { - int ioaddr = ultra_portlist[i]; - if (check_region(ioaddr, ULTRA_IO_EXTENT)) - continue; - if (ultra_probe1(dev, ioaddr) == 0) + for (i = 0; ultra_portlist[i]; i++) + if (ultra_probe1(dev, ultra_portlist[i]) == 0) return 0; - } return -ENODEV; } static int __init ultra_probe1(struct net_device *dev, int ioaddr) { - int i; + int i, retval; int checksum = 0; const char *model_name; unsigned char eeprom_irq = 0; - static unsigned version_printed = 0; + static unsigned version_printed; /* Values from various config regs. */ unsigned char num_pages, irqreg, addr, piomode; unsigned char idreg = inb(ioaddr + 7); unsigned char reg4 = inb(ioaddr + 4) & 0x7f; + if (!request_region(ioaddr, ULTRA_IO_EXTENT, dev->name)) + return -EBUSY; + /* Check the ID nibble. */ if ((idreg & 0xF0) != 0x20 /* SMC Ultra */ - && (idreg & 0xF0) != 0x40) /* SMC EtherEZ */ - return -ENODEV; + && (idreg & 0xF0) != 0x40) { /* SMC EtherEZ */ + 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); @@ -181,7 +184,8 @@ if (irq == 0) { printk(", failed to detect IRQ line.\n"); - return -EAGAIN; + retval = -EAGAIN; + goto out; } dev->irq = irq; eeprom_irq = 1; @@ -190,12 +194,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, ULTRA_IO_EXTENT, model_name); - /* The 8390 isn't at the base address, so fake the offset */ dev->base_addr = ioaddr+ULTRA_NIC_OFFSET; @@ -236,17 +238,22 @@ NS8390_init(dev, 0); return 0; +out: + release_region(ioaddr, ULTRA_IO_EXTENT); + return retval; } static int ultra_open(struct net_device *dev) { + int retval; int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET; /* ASIC addr */ unsigned char irq2reg[] = {0, 0, 0x04, 0x08, 0, 0x0C, 0, 0x40, - 0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, }; + 0, 0x04, 0x44, 0x48, 0, 0, 0, 0x4C, }; - if (request_irq(dev->irq, ei_interrupt, 0, ei_status.name, dev)) - return -EAGAIN; + retval = request_irq(dev->irq, ei_interrupt, 0, dev->name, dev); + if (retval) + return retval; outb(0x00, ioaddr); /* Disable shared memory for safety. */ outb(0x80, ioaddr + 5); @@ -429,9 +436,6 @@ { int this_dev, found = 0; - if (load_8390_module("smc-ultra.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ULTRA_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->irq = irq[this_dev]; @@ -444,7 +448,6 @@ if (register_netdev(dev) != 0) { printk(KERN_WARNING "smc-ultra.c: No SMC Ultra card found (i/o = 0x%x).\n", io[this_dev]); if (found != 0) return 0; /* Got at least one. */ - unload_8390_module(); return -ENXIO; } found++; @@ -468,7 +471,6 @@ kfree(dev->priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c --- v2.4.0-test10/linux/drivers/net/smc-ultra32.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/smc-ultra32.c Tue Nov 7 10:59:43 2000 @@ -365,9 +365,6 @@ { int this_dev, found = 0; - if (load_8390_module("smc-ultra32.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_ULTRA32_CARDS; this_dev++) { struct net_device *dev = &dev_ultra[this_dev]; dev->init = ultra32_probe; @@ -375,7 +372,6 @@ if (found > 0) { /* Got at least one. */ return 0; } - unload_8390_module(); printk(KERN_WARNING "smc-ultra32.c: No SMC Ultra32 found.\n"); return -ENXIO; } @@ -399,6 +395,5 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c --- v2.4.0-test10/linux/drivers/net/smc9194.c Tue Aug 22 08:59:00 2000 +++ linux/drivers/net/smc9194.c Sat Nov 11 18:56:58 2000 @@ -200,13 +200,6 @@ static void smc_timeout(struct net_device *dev); /* - . This is called by the kernel to send a packet out into the net. it's - . responsible for doing a best-effort send, but if it's simply not possible - . to send it, the packet gets dropped. -*/ -static int smc_send_packet(struct sk_buff *skb, struct net_device *dev); - -/* . This is called by the kernel in response to 'ifconfig ethX down'. It . is responsible for cleaning up everything that the open routine . does, and maybe putting the card into a powerdown state. @@ -512,6 +505,10 @@ unsigned short numPages; word time_out; + netif_stop_queue(dev); + /* Well, I want to send the packet.. but I don't know + if I can send it right now... */ + if ( lp->saved_skb) { /* THIS SHOULD NEVER HAPPEN. */ lp->stats.tx_aborted_errors++; @@ -626,7 +623,7 @@ if ( packet_no & 0x80 ) { /* or isn't there? BAD CHIP! */ printk(KERN_DEBUG CARDNAME": Memory allocation failed. \n"); - kfree_skb(skb); + dev_kfree_skb(skb); lp->saved_skb = NULL; netif_wake_queue(dev); return; @@ -761,6 +758,7 @@ int __init smc_findirq( int ioaddr ) { int timeout = 20; + unsigned long cookie; /* I have to do a STI() here, because this is called from @@ -768,7 +766,7 @@ rather difficult to get interrupts for auto detection */ sti(); - autoirq_setup( 0 ); + cookie = probe_irq_on(); /* * What I try to do here is trigger an ALLOC_INT. This is done @@ -821,7 +819,7 @@ cli(); /* and return what I found */ - return autoirq_report( 0 ); + return probe_irq_off(cookie); } /*---------------------------------------------------------------------- @@ -922,13 +920,6 @@ int irqval; - /* see if I need to initialize the ethernet card structure */ - if (dev == NULL) { - dev = init_etherdev(0, 0); - if (dev == NULL) - return -ENOMEM; - } - if (version_printed++ == 0) printk("%s", version); @@ -1060,7 +1051,7 @@ dev->open = smc_open; dev->stop = smc_close; - dev->hard_start_xmit = smc_send_packet; + dev->hard_start_xmit = smc_wait_to_send_packet; dev->tx_timeout = smc_timeout; dev->watchdog_timeo = HZ/20; dev->get_stats = smc_query_statistics; @@ -1181,14 +1172,6 @@ netif_wake_queue(dev); } -static int smc_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - netif_stop_queue(dev); - /* Well, I want to send the packet.. but I don't know - if I can send it right now... */ - return smc_wait_to_send_packet( skb, dev ); -} - /*-------------------------------------------------------------------- . . This is the main routine of the driver, to handle the device when @@ -1594,15 +1577,11 @@ #ifdef MODULE -static struct net_device devSMC9194 = { - "", /* device name is inserted by linux/drivers/net/net_init.c */ - 0, 0, 0, 0, - 0, 0, /* I/O address, IRQ */ - 0, 0, 0, NULL, smc_init }; - -int io = 0; -int irq = 0; -int ifport = 0; +static struct net_device devSMC9194 = { init: smc_init }; + +static int io; +static int irq; +static int ifport; MODULE_PARM(io, "i"); MODULE_PARM(irq, "i"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/stnic.c linux/drivers/net/stnic.c --- v2.4.0-test10/linux/drivers/net/stnic.c Wed Aug 9 13:59:04 2000 +++ linux/drivers/net/stnic.c Tue Nov 7 10:59:43 2000 @@ -105,9 +105,6 @@ if (! MACH_SE) return -ENODEV; - if (load_8390_module ("stnic.c")) - return -ENOSYS; - /* New style probing API */ dev = init_etherdev (0, 0); stnic_dev = dev; @@ -313,6 +310,4 @@ } module_init(stnic_probe); -/* No cleanup routine - if there were one, it should do a: - unload_8390_module() -*/ +/* No cleanup routine. */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c --- v2.4.0-test10/linux/drivers/net/sunhme.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/sunhme.c Fri Nov 17 16:48:51 2000 @@ -1,9 +1,16 @@ -/* $Id: sunhme.c,v 1.98 2000/10/22 16:08:38 davem Exp $ +/* $Id: sunhme.c,v 1.104 2000/11/17 01:40:00 davem Exp $ * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching, * auto carrier detecting ethernet driver. Also known as the * "Happy Meal Ethernet" found on SunSwift SBUS cards. * * Copyright (C) 1996, 1998, 1999 David S. Miller (davem@redhat.com) + * + * Changes : + * 2000/11/11 Willy Tarreau + * - port to non-sparc architectures. Tested only on x86 and + * only currently works with QFE PCI cards. + * - ability to specify the MAC address at module load time by passing this + * argument : macaddr=0x00,0x10,0x20,0x30,0x40,0x50 */ static char *version = @@ -24,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -31,33 +39,46 @@ #include #include +#ifdef __sparc__ #include #include #include #include #include -#include -#include #ifndef __sparc_v9__ #include #endif -#include +#endif #include +#include +#include + #include #include #include #ifdef CONFIG_PCI #include +#ifdef __sparc__ #include #endif +#endif #include "sunhme.h" + +static int macaddr[6]; + +/* accept MAC address of the form macaddr=0x08,0x00,0x20,0x30,0x40,0x50 */ +MODULE_PARM(macaddr, "6i"); + static struct happy_meal *root_happy_dev = NULL; +#ifdef CONFIG_SBUS static struct quattro *qfe_sbus_list = NULL; +#endif + #ifdef CONFIG_PCI static struct quattro *qfe_pci_list = NULL; #endif @@ -150,6 +171,25 @@ #define DEFAULT_IPG2 4 /* For all modes */ #define DEFAULT_JAMSIZE 4 /* Toe jam */ +#ifdef CONFIG_PCI +/* This happy_pci_ids is declared __initdata because it is only used + as an advisory to depmod. If this is ported to the new PCI interface + where it could be referenced at any time due to hot plugging, + it should be changed to __devinitdata. */ + +struct pci_device_id happymeal_pci_ids[] __initdata = { + { + vendor: PCI_VENDOR_ID_SUN, + device: PCI_DEVICE_ID_SUN_HAPPYMEAL, + subvendor: PCI_ANY_ID, + subdevice: PCI_ANY_ID, + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(pci, happymeal_pci_ids); +#endif + /* NOTE: In the descriptor writes one _must_ write the address * member _first_. The card must not be allowed to see * the updated descriptor flags until the address is @@ -282,9 +322,25 @@ #endif #endif -#define DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL -#define DMA_FROMDEVICE SBUS_DMA_FROMDEVICE -#define DMA_TODEVICE SBUS_DMA_TODEVICE + +#ifdef SBUS_DMA_BIDIRECTIONAL +# define DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL +#else +# define DMA_BIDIRECTIONAL 0 +#endif + +#ifdef SBUS_DMA_FROMDEVICE +# define DMA_FROMDEVICE SBUS_DMA_FROMDEVICE +#else +# define DMA_TODEVICE 1 +#endif + +#ifdef SBUS_DMA_TODEVICE +# define DMA_TODEVICE SBUS_DMA_TODEVICE +#else +# define DMA_FROMDEVICE 2 +#endif + /* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ static void BB_PUT_BIT(struct happy_meal *hp, unsigned long tregs, int bit) @@ -1563,6 +1619,10 @@ HMD(("happy_meal_init: old[%08x] bursts<", hme_read32(hp, gregs + GREG_CFG))); +#ifndef __sparc__ + /* It is always PCI and can handle 64byte bursts. */ + hme_write32(hp, gregs + GREG_CFG, GREG_CFG_BURST64); +#else if ((hp->happy_bursts & DMA_BURST64) && ((hp->happy_flags & HFLAG_PCI) != 0 #ifdef CONFIG_SBUS @@ -1596,6 +1656,7 @@ HMD(("XXX>")); hme_write32(hp, gregs + GREG_CFG, 0); } +#endif /* __sparc__ */ /* Turn off interrupts we do not want to hear. */ HMD((", enable global interrupts, ")); @@ -2071,6 +2132,7 @@ HMD(("done\n")); } +#ifdef CONFIG_SBUS static void quattro_sbus_interrupt(int irq, void *cookie, struct pt_regs *ptregs) { struct quattro *qp = (struct quattro *) cookie; @@ -2112,6 +2174,7 @@ } HMD(("done\n")); } +#endif static int happy_meal_open(struct net_device *dev) { @@ -2127,8 +2190,14 @@ if (request_irq(dev->irq, &happy_meal_interrupt, SA_SHIRQ, "HAPPY MEAL", (void *)dev)) { HMD(("EAGAIN\n")); +#ifdef __sparc__ printk(KERN_ERR "happy_meal(SBUS): Can't order irq %s to go.\n", __irq_itoa(dev->irq)); +#else + printk(KERN_ERR "happy_meal(SBUS): Can't order irq %d to go.\n", + dev->irq); +#endif + return -EAGAIN; } } @@ -2168,6 +2237,7 @@ #define SXD(x) #endif +#ifdef CONFIG_SBUS static void happy_meal_tx_timeout(struct net_device *dev) { struct happy_meal *hp = (struct happy_meal *) dev->priv; @@ -2181,6 +2251,7 @@ happy_meal_init(hp, 0); netif_wake_queue(dev); } +#endif static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) { @@ -2541,11 +2612,25 @@ printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ", dev->name); - /* Quattro local-mac-address... */ - if (qfe_slot != -1 && prom_getproplen(sdev->prom_node,"local-mac-address")==6) - prom_getproperty(sdev->prom_node,"local-mac-address",dev->dev_addr,6); - else - memcpy(dev->dev_addr,idprom->id_ethaddr,6); + /* If user did not specify a MAC address specifically, use + * the Quattro local-mac-address property... + */ + for (i = 0; i < 6; i++) { + if (macaddr[i] != 0) + break; + } + if (i < 6) { /* a mac address was given */ + for (i = 0; i < 6; i++) + dev->dev_addr[i] = macaddr[i]; + } else if (qfe_slot != -1 && + prom_getproplen(sdev->prom_node, + "local-mac-address") == 6) { + prom_getproperty(sdev->prom_node, "local-mac-address", + dev->dev_addr, 6); + } else { + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + } + for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':'); @@ -2683,13 +2768,17 @@ static int __init happy_meal_pci_init(struct net_device *dev, struct pci_dev *pdev) { struct quattro *qp = NULL; +#ifdef __sparc__ struct pcidev_cookie *pcp; + int node; +#endif struct happy_meal *hp; unsigned long hpreg_base; - int i, node, qfe_slot = -1; + int i, qfe_slot = -1; char prom_name[64]; /* Now make sure pci_dev cookie is there. */ +#ifdef __sparc__ pcp = pdev->sysdata; if (pcp == NULL || pcp->prom_node == -1) { printk(KERN_ERR "happymeal(PCI): Some PCI device info missing\n"); @@ -2698,6 +2787,11 @@ node = pcp->prom_node; prom_getstring(node, "name", prom_name, sizeof(prom_name)); +#else +#warning This needs to be corrected... -DaveM + strcpy(prom_name, "qfe"); +#endif + if (!strcmp(prom_name, "SUNW,qfe") || !strcmp(prom_name, "qfe")) { qp = quattro_pci_find(pdev); if (qp == NULL) @@ -2763,10 +2857,27 @@ } hpreg_base = (unsigned long) ioremap(hpreg_base, 0x8000); - if (qfe_slot != -1 && prom_getproplen(node, "local-mac-address") == 6) - prom_getproperty(node, "local-mac-address", dev->dev_addr, 6); - else - memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + for (i = 0; i < 6; i++) { + if (macaddr[i] != 0) + break; + } + if (i < 6) { /* a mac address was given */ + for (i = 0; i < 6; i++) + dev->dev_addr[i] = macaddr[i]; + } else { +#ifdef __sparc__ + if (qfe_slot != -1 && + prom_getproplen(node, "local-mac-address") == 6) { + prom_getproperty(node, "local-mac-address", + dev->dev_addr, 6); + } else { + memcpy(dev->dev_addr, idprom->id_ethaddr, 6); + } +#else + memset(dev->dev_addr, 0, 6); +#endif + } + for (i = 0; i < 6; i++) printk("%2.2x%c", dev->dev_addr[i], i == 5 ? ' ' : ':'); @@ -2779,9 +2890,14 @@ hp->bigmacregs = (hpreg_base + 0x6000UL); hp->tcvregs = (hpreg_base + 0x7000UL); +#ifdef __sparc__ hp->hm_revision = prom_getintdefault(node, "hm-rev", 0xff); if (hp->hm_revision == 0xff) hp->hm_revision = 0xa0; +#else + /* works with this on non-sparc hosts */ + hp->hm_revision = 0x20; +#endif /* Now enable the feature flags we can. */ if (hp->hm_revision == 0x20 || hp->hm_revision == 0x21) @@ -2795,8 +2911,10 @@ /* And of course, indicate this is PCI. */ hp->happy_flags |= HFLAG_PCI; +#ifdef __sparc__ /* Assume PCI happy meals can handle all burst sizes. */ hp->happy_bursts = DMA_BURSTBITS; +#endif hp->happy_block = (struct hmeal_init_block *) pci_alloc_consistent(pdev, PAGE_SIZE, &hp->hblock_dvma); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/sunhme.h linux/drivers/net/sunhme.h --- v2.4.0-test10/linux/drivers/net/sunhme.h Fri Feb 18 15:07:20 2000 +++ linux/drivers/net/sunhme.h Sun Nov 12 20:37:17 2000 @@ -1,4 +1,4 @@ -/* $Id: sunhme.h,v 1.30 2000/02/18 13:49:26 davem Exp $ +/* $Id: sunhme.h,v 1.31 2000/11/12 10:23:30 davem Exp $ * sunhme.h: Definitions for Sparc HME/BigMac 10/100baseT ethernet driver. * Also known as the "Happy Meal". * @@ -9,6 +9,7 @@ #define _SUNHME_H #include +#include /* Happy Meal global registers. */ #define GREG_SWRESET 0x000UL /* Software Reset */ @@ -589,7 +590,9 @@ struct quattro *next; /* PROM ranges, if any. */ +#ifdef CONFIG_SBUS struct linux_prom_ranges ranges[8]; +#endif int nranges; }; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c --- v2.4.0-test10/linux/drivers/net/tulip/21142.c Thu Jun 29 10:14:01 2000 +++ linux/drivers/net/tulip/21142.c Tue Nov 7 11:08:09 2000 @@ -115,7 +115,7 @@ outl(csr14, ioaddr + CSR14); if (tp->chip_id == PNIC2) tp->csr6 = 0x01a80000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); - else + else tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0); tulip_outl_csr(tp, tp->csr6, CSR6); if (tp->mtable && tp->mtable->csr15dir) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog --- v2.4.0-test10/linux/drivers/net/tulip/ChangeLog Wed Dec 31 16:00:00 1969 +++ linux/drivers/net/tulip/ChangeLog Tue Nov 7 11:08:09 2000 @@ -0,0 +1,29 @@ +2000-11-02 Jeff Garzik + + * tulip_core.c (set_rx_mode): This is synchronized via + dev->xmit_lock, so only the queueing of the setup frame needs to + be locked, against tulip_interrupt. + +2000-11-02 Alexey Kuznetov + + * timer.c (tulip_timer): Call netif_carrier_{on,off} to report + link state to the rest of the kernel, and userspace. + * interrupt.c (tulip_interrupt): Remove tx_full. + * tulip.h: Likewise. + * tulip_core.c (tulip_init_ring, tulip_start_xmit, set_rx_mode): + Likewise. + +2000-10-18 Jeff Garzik + + * tulip_core.c: (tulip_init_one) Print out ethernet interface + on error. Print out a message when pci_enable_device fails. + Handle DMA alloc failure. + +2000-10-18 Jeff Garzik + + * Makefile: New file. + * tulip_core.c (tulip_init_one): Correct error messages + on PIO/MMIO region reserve failure. + (tulip_init_one) Add new check to ensure that PIO region is + sufficient for our needs. + diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c --- v2.4.0-test10/linux/drivers/net/tulip/interrupt.c Fri Sep 8 12:34:58 2000 +++ linux/drivers/net/tulip/interrupt.c Tue Nov 7 11:08:09 2000 @@ -19,7 +19,7 @@ int tulip_rx_copybreak; -int tulip_max_interrupt_work; +unsigned int tulip_max_interrupt_work; @@ -177,12 +177,17 @@ int maxrx = RX_RING_SIZE; int maxtx = TX_RING_SIZE; int maxoi = TX_RING_SIZE; - int work_count = tulip_max_interrupt_work; - + unsigned int work_count = tulip_max_interrupt_work; + + /* Let's see whether the interrupt really is for us */ + csr5 = inl(ioaddr + CSR5); + + if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) + return; + tp->nir++; do { - csr5 = inl(ioaddr + CSR5); /* Acknowledge all of the current interrupt sources ASAP. */ outl(csr5 & 0x0001ffff, ioaddr + CSR5); @@ -190,9 +195,6 @@ printk(KERN_DEBUG "%s: interrupt csr5=%#8.8x new csr5=%#8.8x.\n", dev->name, csr5, inl(dev->base_addr + CSR5)); - if ((csr5 & (NormalIntr|AbnormalIntr)) == 0) - break; - if (csr5 & (RxIntr | RxNoBuf)) { rx += tulip_rx(dev); tulip_refill_rx(dev); @@ -221,7 +223,7 @@ PCI_DMA_TODEVICE); continue; } - + if (status & 0x8000) { /* There was an major error, log it. */ #ifndef final_version @@ -256,17 +258,14 @@ #ifndef final_version if (tp->cur_tx - dirty_tx > TX_RING_SIZE) { - printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n", - dev->name, dirty_tx, tp->cur_tx, tp->tx_full); + printk(KERN_ERR "%s: Out-of-sync dirty pointer, %d vs. %d.\n", + dev->name, dirty_tx, tp->cur_tx); dirty_tx += TX_RING_SIZE; } #endif - if (tp->tx_full && tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) { - /* The ring is no longer full, clear tbusy. */ - tp->tx_full = 0; + if (tp->cur_tx - dirty_tx < TX_RING_SIZE - 2) netif_wake_queue(dev); - } tp->dirty_tx = dirty_tx; if (csr5 & TxDied) { @@ -330,22 +329,28 @@ /* Acknowledge all interrupt sources. */ outl(0x8001ffff, ioaddr + CSR5); if (tp->flags & HAS_INTR_MITIGATION) { - /* Josip Loncaric at ICASE did extensive experimentation + /* Josip Loncaric at ICASE did extensive experimentation to develop a good interrupt mitigation setting.*/ outl(0x8b240000, ioaddr + CSR11); } else { - /* Mask all interrupting sources, set timer to + /* Mask all interrupting sources, set timer to re-enable. */ outl(((~csr5) & 0x0001ebef) | AbnormalIntr | TimerInt, ioaddr + CSR7); outl(0x0012, ioaddr + CSR11); } break; } - } while (work_count-- > 0); + + work_count--; + if (work_count == 0) + break; + + csr5 = inl(ioaddr + CSR5); + } while ((csr5 & (NormalIntr|AbnormalIntr)) != 0); tulip_refill_rx(dev); - /* check if we card is in suspend mode */ + /* check if the card is in suspend mode */ entry = tp->dirty_rx % RX_RING_SIZE; if (tp->rx_buffers[entry].skb == NULL) { if (tulip_debug > 1) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/tulip/timer.c linux/drivers/net/tulip/timer.c --- v2.4.0-test10/linux/drivers/net/tulip/timer.c Mon Jun 19 13:42:39 2000 +++ linux/drivers/net/tulip/timer.c Tue Nov 7 11:08:09 2000 @@ -130,13 +130,15 @@ /* Check that the specified bit has the proper value. */ if ((bitnum < 0) != ((csr12 & (1 << ((bitnum >> 1) & 7))) != 0)) { - if (tulip_debug > 1) + if (tulip_debug > 2) printk(KERN_DEBUG "%s: Link beat detected for %s.\n", dev->name, medianame[mleaf->media]); if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */ goto actually_mii; + netif_carrier_on(dev); break; } + netif_carrier_off(dev); if (tp->medialock) break; select_next_media: @@ -160,7 +162,10 @@ } case 1: case 3: /* 21140, 21142 MII */ actually_mii: - tulip_check_duplex(dev); + if (tulip_check_duplex(dev) < 0) + netif_carrier_off(dev); + else + netif_carrier_on(dev); next_tick = 60*HZ; break; case 2: /* 21142 serial block has no link beat. */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h --- v2.4.0-test10/linux/drivers/net/tulip/tulip.h Mon Jun 19 13:42:39 2000 +++ linux/drivers/net/tulip/tulip.h Tue Nov 7 11:08:09 2000 @@ -208,7 +208,7 @@ csr6_ho = (1<<2), /* Hash-only filtering mode: can't be set */ csr6_sr = (1<<1), /* Start(1)/Stop(0) Receive */ csr6_hp = (1<<0), /* Hash/Perfect Receive Filtering Mode: can't be set */ - + csr6_mask_capture = (csr6_sc | csr6_ca), csr6_mask_defstate = (csr6_mask_capture | csr6_mbo), csr6_mask_hdcap = (csr6_mask_defstate | csr6_hbd | csr6_ps), @@ -340,7 +340,6 @@ spinlock_t lock; unsigned int cur_rx, cur_tx; /* The next free ring entry */ unsigned int dirty_rx, dirty_tx; /* The ring entries to be free()ed. */ - unsigned int tx_full:1; /* The Tx queue is full. */ unsigned int full_duplex:1; /* Full-duplex operation requested. */ unsigned int full_duplex_lock:1; unsigned int fake_addr:1; /* Multiport board faked address. */ @@ -389,7 +388,7 @@ int tulip_read_eeprom(long ioaddr, int location, int addr_len); /* interrupt.c */ -extern int tulip_max_interrupt_work; +extern unsigned int tulip_max_interrupt_work; extern int tulip_rx_copybreak; void tulip_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -435,6 +434,5 @@ tulip_outl_csr(tp, csr6mask | csr6_sr, CSR6); tulip_outl_csr(tp, csr6mask | csr6_st | csr6_sr, CSR6); } - #endif /* __NET_TULIP_H__ */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c --- v2.4.0-test10/linux/drivers/net/tulip/tulip_core.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/tulip/tulip_core.c Tue Nov 7 11:08:09 2000 @@ -7,11 +7,11 @@ This software may be used and distributed according to the terms of the GNU Public License, incorporated herein by reference. - + Please read Documentation/networking/tulip.txt for more information. - For this specific driver variant please use linux-kernel for + For this specific driver variant please use linux-kernel for bug reports. Additional information available at @@ -28,13 +28,13 @@ #include static char version[] __devinitdata = - "Linux Tulip driver version 0.9.10 (September 6, 2000)\n"; + "Linux Tulip driver version 0.9.11 (November 3, 2000)\n"; /* A few user-configurable values. */ /* Maximum events (Rx packets, etc.) to handle at each interrupt. */ -static int max_interrupt_work = 25; +static unsigned int max_interrupt_work = 25; #define MAX_UNITS 8 /* Used to pass the full-duplex flag, etc. */ @@ -415,11 +415,11 @@ } tulip_init_ring (dev); - + tulip_up (dev); - + netif_start_queue (dev); - + return 0; } @@ -429,7 +429,7 @@ struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; unsigned long flags; - + DPRINTK("ENTER\n"); spin_lock_irqsave (&tp->lock, flags); @@ -541,7 +541,6 @@ DPRINTK("ENTER\n"); - tp->tx_full = 0; tp->cur_rx = tp->cur_tx = 0; tp->dirty_rx = tp->dirty_tx = 0; tp->susp_rx = 0; @@ -597,9 +596,6 @@ u32 flag; dma_addr_t mapping; - /* Caution: the write order is important here, set the field - with the ownership bits last. */ - spin_lock_irq(&tp->lock); /* Calculate the next Tx descriptor entry. */ @@ -618,7 +614,6 @@ } else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) { flag = 0x60000000; /* No Tx-done intr. */ } else { /* Leave room for set_rx_mode() to fill entries. */ - tp->tx_full = 1; flag = 0xe0000000; /* Tx-done intr. */ netif_stop_queue(dev); } @@ -626,7 +621,11 @@ flag = 0xe0000000 | DESC_RING_WRAP; tp->tx_ring[entry].length = cpu_to_le32(skb->len | flag); + /* if we were using Transmit Automatic Polling, we would need a + * wmb() here. */ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); + wmb(); + tp->cur_tx++; /* Trigger an immediate transmit demand. */ @@ -670,14 +669,14 @@ if (tp->flags & HAS_ACPI) pci_write_config_dword (tp->pdev, 0x40, 0x40000000); } - - + + static int tulip_close (struct net_device *dev) { long ioaddr = dev->base_addr; struct tulip_private *tp = (struct tulip_private *) dev->priv; int i; - + netif_stop_queue (dev); tulip_down (dev); @@ -846,18 +845,77 @@ return crc; } +#undef set_bit_le +#define set_bit_le(i,p) do { ((char *)(p))[(i)/8] |= (1<<((i)%8)); } while(0) + +static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + u16 hash_table[32]; + struct dev_mc_list *mclist; + int i; + u16 *eaddrs; + + memset(hash_table, 0, sizeof(hash_table)); + set_bit_le(255, hash_table); /* Broadcast entry */ + /* This should work on big-endian machines as well. */ + for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; + i++, mclist = mclist->next) { + int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff; + + set_bit_le(index, hash_table); + + for (i = 0; i < 32; i++) { + *setup_frm++ = hash_table[i]; + *setup_frm++ = hash_table[i]; + } + setup_frm = &tp->setup_frame[13*6]; + } + + /* Fill the final entry with our physical address. */ + eaddrs = (u16 *)dev->dev_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; +} + +static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev) +{ + struct tulip_private *tp = (struct tulip_private *)dev->priv; + struct dev_mc_list *mclist; + int i; + u16 *eaddrs; + + /* We have <= 14 addresses so we can use the wonderful + 16 address perfect filtering of the Tulip. */ + for (i = 0, mclist = dev->mc_list; i < dev->mc_count; + i++, mclist = mclist->next) { + eaddrs = (u16 *)mclist->dmi_addr; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + *setup_frm++ = *eaddrs; *setup_frm++ = *eaddrs++; + } + /* Fill the unused entries with the broadcast address. */ + memset(setup_frm, 0xff, (15-i)*12); + setup_frm = &tp->setup_frame[15*6]; + + /* Fill the final entry with our physical address. */ + eaddrs = (u16 *)dev->dev_addr; + *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; + *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; + *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; +} + + static void set_rx_mode(struct net_device *dev) { struct tulip_private *tp = (struct tulip_private *)dev->priv; long ioaddr = dev->base_addr; - int csr6, need_lock = 0; - unsigned long flags; + int csr6; DPRINTK("ENTER\n"); - spin_lock_irqsave(&tp->lock, flags); csr6 = inl(ioaddr + CSR6) & ~0x00D5; - spin_unlock_irqrestore(&tp->lock, flags); tp->csr6 &= ~0x00D5; if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */ @@ -865,14 +923,10 @@ csr6 |= 0x00C0; /* Unconditionally log net taps. */ printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name); - - need_lock = 1; } else if ((dev->mc_count > 1000) || (dev->flags & IFF_ALLMULTI)) { /* Too many to filter well -- accept all multicasts. */ tp->csr6 |= 0x0080; csr6 |= 0x0080; - - need_lock = 1; } else if (tp->flags & MC_HASH_ONLY) { /* Some work-alikes have only a 64-entry hash filter table. */ /* Should verify correctness on big-endian/__powerpc__ */ @@ -882,7 +936,6 @@ if (dev->mc_count > 64) { /* Arbitrary non-effective limit. */ tp->csr6 |= 0x0080; csr6 |= 0x0080; - need_lock = 1; } else { mc_filter[1] = mc_filter[0] = 0; for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; @@ -890,71 +943,32 @@ set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, mc_filter); if (tp->chip_id == AX88140) { - spin_lock_irqsave(&tp->lock, flags); outl(2, ioaddr + CSR13); outl(mc_filter[0], ioaddr + CSR14); outl(3, ioaddr + CSR13); outl(mc_filter[1], ioaddr + CSR14); - /* need_lock = 0; */ } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */ - spin_lock_irqsave(&tp->lock, flags); outl(mc_filter[0], ioaddr + 0xAC); outl(mc_filter[1], ioaddr + 0xB0); - /* need_lock = 0; */ - } else { - need_lock = 1; } } - } else { - u16 *eaddrs, *setup_frm = tp->setup_frame; - struct dev_mc_list *mclist; - u32 tx_flags = 0x08000000 | 192; - int i; + unsigned long flags; /* Note that only the low-address shortword of setup_frame is valid! The values are doubled for big-endian architectures. */ if (dev->mc_count > 14) { /* Must use a multicast hash table. */ - u16 hash_table[32]; - tx_flags = 0x08400000 | 192; /* Use hash filter. */ - memset(hash_table, 0, sizeof(hash_table)); - set_bit(255, hash_table); /* Broadcast entry */ - /* This should work on big-endian machines as well. */ - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) - set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff, - hash_table); - for (i = 0; i < 32; i++) { - *setup_frm++ = hash_table[i]; - *setup_frm++ = hash_table[i]; - } - setup_frm = &tp->setup_frame[13*6]; + build_setup_frame_hash(tp->setup_frame, dev); } else { - /* We have <= 14 addresses so we can use the wonderful - 16 address perfect filtering of the Tulip. */ - for (i = 0, mclist = dev->mc_list; i < dev->mc_count; - i++, mclist = mclist->next) { - u16 *eaddrs = (u16 *)mclist->dmi_addr; - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; - } - /* Fill the unused entries with the broadcast address. */ - memset(setup_frm, 0xff, (15-i)*12); - setup_frm = &tp->setup_frame[15*6]; + build_setup_frame_perfect(tp->setup_frame, dev); } - /* Fill the final entry with our physical address. */ - eaddrs = (u16 *)dev->dev_addr; - *setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0]; - *setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1]; - *setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2]; - spin_lock_irqsave(&tp->lock, flags); if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) { /* Same setup recently queued, we need not add it. */ } else { + u32 tx_flags = 0x08000000 | 192; unsigned int entry; int dummy = -1; @@ -988,24 +1002,18 @@ tp->tx_ring[entry].status = cpu_to_le32(DescOwned); if (dummy >= 0) tp->tx_ring[dummy].status = cpu_to_le32(DescOwned); - if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) { + if (tp->cur_tx - tp->dirty_tx >= TX_RING_SIZE - 2) netif_stop_queue(dev); - tp->tx_full = 1; - } /* Trigger an immediate transmit demand. */ outl(0, ioaddr + CSR1); - } + + spin_unlock_irqrestore(&tp->lock, flags); } - - if (need_lock) - spin_lock_irqsave(&tp->lock, flags); /* Can someone explain to me what the OR here is supposed to accomplish???? */ tulip_outl_csr(tp, csr6 | 0x0000, CSR6); - - spin_unlock_irqrestore(&tp->lock, flags); } @@ -1026,7 +1034,7 @@ long ioaddr; static int board_idx = -1; int chip_idx = ent->driver_data; - + board_idx++; if (tulip_debug > 0 && did_version++ == 0) @@ -1036,7 +1044,7 @@ printk (KERN_ERR PFX "skipping LMC card.\n"); return -ENODEV; } - + ioaddr = pci_resource_start (pdev, 0); irq = pdev->irq; @@ -1047,25 +1055,37 @@ return -ENOMEM; } + if (pci_resource_len (pdev, 0) < tulip_tbl[chip_idx].io_size) { + printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) too small, " + "aborting\n", dev->name, pci_resource_len (pdev, 0), + pci_resource_start (pdev, 0)); + goto err_out_free_netdev; + } + /* grab all resources from both PIO and MMIO regions, as we * don't want anyone else messing around with our hardware */ if (!request_region (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0), dev->name)) { - printk (KERN_ERR PFX "I/O ports (0x%x@0x%lx) unavailable, " - "aborting\n", tulip_tbl[chip_idx].io_size, ioaddr); + printk (KERN_ERR PFX "%s: I/O region (0x%lx@0x%lx) unavailable, " + "aborting\n", dev->name, pci_resource_len (pdev, 0), + pci_resource_start (pdev, 0)); goto err_out_free_netdev; } if (!request_mem_region (pci_resource_start (pdev, 1), pci_resource_len (pdev, 1), dev->name)) { - printk (KERN_ERR PFX "MMIO resource (0x%x@0x%lx) unavailable, " - "aborting\n", tulip_tbl[chip_idx].io_size, ioaddr); + printk (KERN_ERR PFX "%s: MMIO region (0x%lx@0x%lx) unavailable, " + "aborting\n", dev->name, pci_resource_len (pdev, 1), + pci_resource_start (pdev, 1)); goto err_out_free_pio_res; } - if (pci_enable_device(pdev)) + if (pci_enable_device(pdev)) { + printk (KERN_ERR PFX "%s: Cannot enable PCI device, aborting\n", + dev->name); goto err_out_free_mmio_res; + } pci_set_master(pdev); @@ -1081,6 +1101,8 @@ sizeof(struct tulip_rx_desc) * RX_RING_SIZE + sizeof(struct tulip_tx_desc) * TX_RING_SIZE, &tp->rx_ring_dma); + if (!tp->rx_ring) + goto err_out_free_mmio_res; tp->tx_ring = (struct tulip_tx_desc *)(tp->rx_ring + RX_RING_SIZE); tp->tx_ring_dma = tp->rx_ring_dma + sizeof(struct tulip_rx_desc) * RX_RING_SIZE; @@ -1122,7 +1144,7 @@ tulip_stop_rxtx(tp, inl(ioaddr + CSR6)); /* Clear the missed-packet counter. */ - (volatile int)inl(ioaddr + CSR8); + inl(ioaddr + CSR8); if (chip_idx == DC21041) { if (inl(ioaddr + CSR9) & 0x8000) { @@ -1240,7 +1262,7 @@ tp->to_advertise = media2advert[tp->default_port - 9]; } else if (tp->flags & HAS_8023X) tp->to_advertise = 0x05e1; - else + else tp->to_advertise = 0x01e1; /* This is logically part of _init_one(), but too complex to write inline. */ @@ -1455,7 +1477,7 @@ /* copy module parms into globals */ tulip_rx_copybreak = rx_copybreak; tulip_max_interrupt_work = max_interrupt_work; - + /* probe for and init boards */ return pci_module_init (&tulip_driver); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/wan/comx-proto-lapb.c linux/drivers/net/wan/comx-proto-lapb.c --- v2.4.0-test10/linux/drivers/net/wan/comx-proto-lapb.c Wed Jul 5 10:56:13 2000 +++ linux/drivers/net/wan/comx-proto-lapb.c Sat Nov 11 19:02:39 2000 @@ -15,6 +15,9 @@ * Version 0.80 (99/06/14): * - cleaned up the source code a bit * - ported back to kernel, now works as non-module + * + * Changed (00/10/29, Henner Eisen): + * - comx_rx() / comxlapb_data_indication() return status. * */ @@ -359,7 +362,7 @@ comx_status(ch->dev, ch->line_status); } -static void comxlapb_data_indication(void *token, struct sk_buff *skb) +static int comxlapb_data_indication(void *token, struct sk_buff *skb) { struct comx_channel *ch = token; @@ -373,7 +376,7 @@ skb->dev = ch->dev; skb->mac.raw = skb->data; - comx_rx(ch->dev, skb); + return comx_rx(ch->dev, skb); } static void comxlapb_data_transmit(void *token, struct sk_buff *skb) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/wan/comx.c linux/drivers/net/wan/comx.c --- v2.4.0-test10/linux/drivers/net/wan/comx.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/net/wan/comx.c Thu Nov 16 14:08:25 2000 @@ -46,6 +46,9 @@ * Version 0.85 (00/08/15): * - resource release on failure in comx_mkdir * - fix return value on failure at comx_write_proc + * + * Changed (00/10/29, Henner Eisen): + * - comx_rx() / comxlapb_data_indication() return status. */ #define VERSION "0.85" @@ -852,7 +855,7 @@ cleanup_filename_hardware: remove_proc_entry(FILENAME_HARDWARE, new_dir); cleanup_new_dir: - remove_proc_entry(dentry->d_name.name, &comx_root_dir); + remove_proc_entry(dentry->d_name.name, comx_root_dir); cleanup_dev: kfree(dev); return ret; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/wan/lapbether.c linux/drivers/net/wan/lapbether.c --- v2.4.0-test10/linux/drivers/net/wan/lapbether.c Thu May 4 11:31:21 2000 +++ linux/drivers/net/wan/lapbether.c Fri Nov 17 16:48:51 2000 @@ -16,6 +16,8 @@ * * History * LAPBETH 001 Jonathan Naylor Cloned from bpqether.c + * 2000-10-29 Henner Eisen lapb_data_indication() return status. + * 2000-11-14 Henner Eisen dev_hold/put, NETDEV_GOING_DOWN support */ #include @@ -79,6 +81,7 @@ /* * Get the ethernet device for a LAPB device */ +#if 0 static __inline__ struct net_device *lapbeth_get_ether_dev(struct net_device *dev) { struct lapbethdev *lapbeth; @@ -87,7 +90,7 @@ return (lapbeth != NULL) ? lapbeth->ethdev : NULL; } - +#endif /* * Get the LAPB device for the ethernet device */ @@ -136,6 +139,7 @@ result = 1; unregister_netdev(&lapbeth->axdev); + dev_put(lapbeth->ethdev); kfree(lapbeth); } @@ -185,7 +189,7 @@ return 0; } -static void lapbeth_data_indication(void *token, struct sk_buff *skb) +static int lapbeth_data_indication(void *token, struct sk_buff *skb) { struct lapbethdev *lapbeth = (struct lapbethdev *)token; unsigned char *ptr; @@ -198,7 +202,7 @@ skb->mac.raw = skb->data; skb->pkt_type = PACKET_HOST; - netif_rx(skb); + return netif_rx(skb); } /* @@ -418,6 +422,7 @@ memset(lapbeth, 0, sizeof(struct lapbethdev)); + dev_hold(dev); lapbeth->ethdev = dev; lapbeth->ethname[sizeof(lapbeth->ethname)-1] = '\0'; @@ -436,6 +441,7 @@ } if (k == MAXLAPBDEV) { + dev_put(dev); kfree(lapbeth); return -ENODEV; } @@ -445,6 +451,7 @@ dev->init = lapbeth_dev_init; if (register_netdev(dev) != 0) { + dev_put(dev); kfree(lapbeth); return -EIO; } @@ -498,6 +505,7 @@ lapbeth_new_device(dev); break; + case NETDEV_GOING_DOWN: case NETDEV_DOWN: /* ethernet device closed -> close LAPB interface */ if ((dev = lapbeth_get_x25_dev(dev)) != NULL) dev_close(dev); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/wan/x25_asy.c linux/drivers/net/wan/x25_asy.c --- v2.4.0-test10/linux/drivers/net/wan/x25_asy.c Thu May 4 11:31:21 2000 +++ linux/drivers/net/wan/x25_asy.c Sat Nov 11 19:02:39 2000 @@ -9,6 +9,9 @@ * recommendations. Its primarily for testing purposes. If you wanted * to do CCITT then in theory all you need is to nick the HDLC async * checksum routines from ppp.c + * Changes: + * + * 2000-10-29 Henner Eisen lapb_data_indication() return status. */ #include @@ -390,9 +393,9 @@ * at the net layer. */ -static void x25_asy_data_indication(void *token, struct sk_buff *skb) +static int x25_asy_data_indication(void *token, struct sk_buff *skb) { - netif_rx(skb); + return netif_rx(skb); } /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/net/wd.c linux/drivers/net/wd.c --- v2.4.0-test10/linux/drivers/net/wd.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/net/wd.c Tue Nov 7 11:06:09 2000 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -84,19 +85,33 @@ int __init wd_probe(struct net_device *dev) { int i; + struct resource *r; int base_addr = dev ? dev->base_addr : 0; - if (base_addr > 0x1ff) /* Check a single specified location. */ - return wd_probe1(dev, base_addr); + if (base_addr > 0x1ff) { /* Check a user specified location. */ + r = request_region(base_addr, WD_IO_EXTENT, "wd-probe"); + if ( r == NULL) + return -EBUSY; + i = wd_probe1(dev, base_addr); + if (i != 0) + release_resource(r); + else + r->name = ei_status.name; + return i; + } else if (base_addr != 0) /* Don't probe at all. */ return -ENXIO; for (i = 0; wd_portlist[i]; i++) { int ioaddr = wd_portlist[i]; - if (check_region(ioaddr, WD_IO_EXTENT)) + r = request_region(ioaddr, WD_IO_EXTENT, "wd-probe"); + if (r == NULL) continue; - if (wd_probe1(dev, ioaddr) == 0) + if (wd_probe1(dev, ioaddr) == 0) { + r->name = ei_status.name; return 0; + } + release_resource(r); } return -ENODEV; @@ -256,8 +271,6 @@ } /* OK, were are certain this is going to work. Setup the device. */ - request_region(ioaddr, WD_IO_EXTENT, model_name); - ei_status.name = model_name; ei_status.word16 = word16; ei_status.tx_start_page = WD_START_PG; @@ -444,9 +457,6 @@ { int this_dev, found = 0; - if (load_8390_module("wd.c")) - return -ENOSYS; - for (this_dev = 0; this_dev < MAX_WD_CARDS; this_dev++) { struct net_device *dev = &dev_wd[this_dev]; dev->irq = irq[this_dev]; @@ -463,7 +473,6 @@ if (found != 0) { /* Got at least one. */ return 0; } - unload_8390_module(); return -ENXIO; } found++; @@ -487,7 +496,6 @@ kfree(priv); } } - unload_8390_module(); } #endif /* MODULE */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/nubus/proc.c linux/drivers/nubus/proc.c --- v2.4.0-test10/linux/drivers/nubus/proc.c Sat Nov 27 15:27:48 1999 +++ linux/drivers/nubus/proc.c Fri Nov 17 16:51:47 2000 @@ -148,7 +148,7 @@ struct proc_dir_entry *e; if ((e = dev->procdir)) { - if (e->count) + if (atomic_read(&e->count)) return -EBUSY; remove_proc_entry(e->name, proc_bus_nubus_dir); dev->procdir = NULL; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pci/pci.c linux/drivers/pci/pci.c --- v2.4.0-test10/linux/drivers/pci/pci.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/pci/pci.c Thu Nov 16 12:51:28 2000 @@ -20,6 +20,8 @@ #include #include #include +#include +#include /* for hotplug_path */ #include #include /* isa_dma_bridge_buggy */ @@ -343,6 +345,49 @@ #ifdef CONFIG_HOTPLUG +#ifndef FALSE +#define FALSE (0) +#define TRUE (!FALSE) +#endif + +static void +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]; + + 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); + + i = 0; + argv[i++] = hotplug_path; + argv[i++] = "pci"; + argv[i] = 0; + + i = 0; + /* minimal command environment */ + envp[i++] = "HOME=/"; + envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; + + /* other stuff we want to pass to /sbin/hotplug */ + envp[i++] = id; + envp[i++] = sub_id; + envp[i++] = bus_id; + if (insert) + envp[i++] = "ACTION=add"; + else + envp[i++] = "ACTION=remove"; + envp[i] = 0; + + call_usermodehelper (argv [0], argv, envp); +} + void pci_insert_device(struct pci_dev *dev, struct pci_bus *bus) { @@ -358,9 +403,13 @@ if (drv->remove && pci_announce_device(drv, dev)) break; } + + /* notify userspace of new hotplug device */ + run_sbin_hotplug(dev, TRUE); } -static void pci_free_resources(struct pci_dev *dev) +static void +pci_free_resources(struct pci_dev *dev) { int i; @@ -385,6 +434,9 @@ #ifdef CONFIG_PROC_FS pci_proc_detach_device(dev); #endif + + /* notify userspace of hotplug device removal */ + run_sbin_hotplug(dev, FALSE); } #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids --- v2.4.0-test10/linux/drivers/pci/pci.ids Tue Oct 31 12:42:26 2000 +++ linux/drivers/pci/pci.ids Tue Nov 7 11:15:52 2000 @@ -1472,7 +1472,8 @@ 10b7 3590 TokenLink Velocity XL Adapter 4500 3c450 Cyclone/unknown 5055 3c555 Laptop Hurricane - 6055 3c556 Laptop Hurricane + 6055 3c556 Laptop Tornado + 6056 3c556B Laptop Hurricane 5057 3c575 [Megahertz] 10/100 LAN CardBus 10b7 5a57 3C575 Megahertz 10/100 LAN Cardbus PC Card 5157 3CCFE575BT Cyclone CardBus diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pci/proc.c linux/drivers/pci/proc.c --- v2.4.0-test10/linux/drivers/pci/proc.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/pci/proc.c Fri Nov 17 16:51:47 2000 @@ -279,7 +279,7 @@ struct proc_dir_entry *e; if ((e = dev->procent)) { - if (e->count) + if (atomic_read(&e->count)) return -EBUSY; remove_proc_entry(e->name, dev->bus->procdir); dev->procent = NULL; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/Config.in linux/drivers/pcmcia/Config.in --- v2.4.0-test10/linux/drivers/pcmcia/Config.in Fri Jul 21 23:41:24 2000 +++ linux/drivers/pcmcia/Config.in Thu Nov 16 16:38:16 2000 @@ -7,18 +7,18 @@ mainmenu_option next_comment comment 'PCMCIA/CardBus support' -dep_tristate 'CardBus support' CONFIG_PCMCIA $CONFIG_PCI -if [ "$CONFIG_PCMCIA" != "n" ]; then - define_bool CONFIG_CARDBUS y -fi - -#tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA +#dep_tristate 'CardBus support' CONFIG_PCMCIA $CONFIG_PCI #if [ "$CONFIG_PCMCIA" != "n" ]; then -# if [ "$CONFIG_PCI" != "n" ]; then -# bool ' CardBus support' CONFIG_CARDBUS -# fi -# bool ' i82365 compatible bridge support' CONFIG_I82365 -# bool ' Databook TCIC host bridge support' CONFIG_TCIC +# define_bool CONFIG_CARDBUS y #fi + +tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA +if [ "$CONFIG_PCMCIA" != "n" ]; then + if [ "$CONFIG_PCI" != "n" ]; then + bool ' CardBus support' CONFIG_CARDBUS + fi + bool ' i82365 compatible bridge support' CONFIG_I82365 + bool ' Databook TCIC host bridge support' CONFIG_TCIC +fi endmenu diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c --- v2.4.0-test10/linux/drivers/pcmcia/cardbus.c Sun Oct 8 10:50:20 2000 +++ linux/drivers/pcmcia/cardbus.c Wed Nov 8 17:03:09 2000 @@ -383,7 +383,7 @@ dev = &s->cb_config[i].dev; pci_writeb(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY); - pci_writeb(dev, PCI_CACHE_LINE_SIZE, 8); + pci_writeb(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4); } if (s->irq.AssignedIRQ) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c --- v2.4.0-test10/linux/drivers/pcmcia/cs.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/pcmcia/cs.c Tue Nov 7 11:08:09 2000 @@ -319,6 +319,8 @@ DEBUG(0, "cs: pcmcia_register_socket(0x%p)\n", ss_entry); s = kmalloc(sizeof(struct socket_info_t), GFP_KERNEL); + if (!s) + return NULL; memset(s, 0, sizeof(socket_info_t)); s->ss_entry = ss_entry; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c --- v2.4.0-test10/linux/drivers/pcmcia/i82365.c Wed May 3 01:45:17 2000 +++ linux/drivers/pcmcia/i82365.c Thu Nov 16 16:38:16 2000 @@ -859,6 +859,28 @@ /*====================================================================*/ +static u_int pending_events[8]; +static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED; + +static void pcic_bh(void *dummy) +{ + u_int events; + int i; + + for (i=0; i < sockets; i++) { + spin_lock_irq(&pending_event_lock); + events = pending_events[i]; + pending_events[i] = 0; + spin_unlock_irq(&pending_event_lock); + if (socket[i].handler) + socket[i].handler(socket[i].info, events); + } +} + +static struct tq_struct pcic_task = { + routine: pcic_bh +}; + static void pcic_interrupt(int irq, void *dev, struct pt_regs *regs) { @@ -893,8 +915,13 @@ } ISA_UNLOCK(i, flags); DEBUG(2, "i82365: socket %d event 0x%02x\n", i, events); - if (events) - socket[i].handler(socket[i].info, events); + + if (events) { + spin_lock(&pending_event_lock); + pending_events[i] |= events; + spin_unlock(&pending_event_lock); + schedule_task(&pcic_task); + } active |= events; } if (!active) break; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/pci_socket.c linux/drivers/pcmcia/pci_socket.c --- v2.4.0-test10/linux/drivers/pcmcia/pci_socket.c Wed Jul 26 14:21:16 2000 +++ linux/drivers/pcmcia/pci_socket.c Thu Nov 16 16:38:16 2000 @@ -177,7 +177,7 @@ socket->dev = dev; socket->op = ops; dev->driver_data = socket; - init_waitqueue_head(&socket->wait); + spin_lock_init(&socket->event_lock); return socket->op->open(socket); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/pci_socket.h linux/drivers/pcmcia/pci_socket.h --- v2.4.0-test10/linux/drivers/pcmcia/pci_socket.h Wed Jul 5 13:14:49 2000 +++ linux/drivers/pcmcia/pci_socket.h Thu Nov 16 16:38:16 2000 @@ -18,9 +18,11 @@ void *info; struct pci_socket_ops *op; socket_cap_t cap; - wait_queue_head_t wait; + spinlock_t event_lock; unsigned int events; struct socket_info_t *pcmcia_socket; + struct tq_struct tq_task; + struct timer_list poll_timer; /* A few words of private data for the low-level driver.. */ unsigned int private[8]; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c --- v2.4.0-test10/linux/drivers/pcmcia/tcic.c Tue May 2 17:38:58 2000 +++ linux/drivers/pcmcia/tcic.c Thu Nov 16 16:38:16 2000 @@ -530,6 +530,28 @@ /*====================================================================*/ +static u_int pending_events[2]; +static spinlock_t pending_event_lock = SPIN_LOCK_UNLOCKED; + +static void tcic_bh(void *dummy) +{ + u_int events; + int i; + + for (i=0; i < sockets; i++) { + spin_lock_irq(&pending_event_lock); + events = pending_events[i]; + pending_events[i] = 0; + spin_unlock_irq(&pending_event_lock); + if (socket_table[i].handler) + socket_table[i].handler(socket_table[i].info, events); + } +} + +static struct tq_struct tcic_task = { + routine: tcic_bh +}; + static void tcic_interrupt(int irq, void *dev, struct pt_regs *regs) { int i, quick = 0; @@ -568,8 +590,12 @@ events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0; events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0; } - if (events) - socket_table[i].handler(socket_table[i].info, events); + if (events) { + spin_lock(&pending_event_lock); + pending_events[i] |= events; + spin_unlock(&pending_event_lock); + schedule_task(&tcic_task); + } } /* Schedule next poll, if needed */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c --- v2.4.0-test10/linux/drivers/pcmcia/yenta.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/pcmcia/yenta.c Thu Nov 16 18:25:16 2000 @@ -10,7 +10,10 @@ #include #include +#include +#include #include +#include #include @@ -464,6 +467,20 @@ return events; } + +static void yenta_bh(void *data) +{ + pci_socket_t *socket = data; + unsigned int events; + + spin_lock_irq(&socket->event_lock); + events = socket->events; + socket->events = 0; + spin_unlock_irq(&socket->event_lock); + if (socket->handler) + socket->handler(socket->info, events); +} + static void yenta_interrupt(int irq, void *dev_id, struct pt_regs *regs) { unsigned int events; @@ -471,11 +488,22 @@ events = yenta_events(socket); if (events) { + spin_lock(&socket->event_lock); socket->events |= events; - wake_up_interruptible(&socket->wait); + spin_unlock(&socket->event_lock); + schedule_task(&socket->tq_task); } } +static void yenta_interrupt_wrapper(unsigned long data) +{ + pci_socket_t *socket = (pci_socket_t *) data; + + yenta_interrupt(0, (void *)socket, NULL); + socket->poll_timer.expires = jiffies + HZ; + add_timer(&socket->poll_timer); +} + /* * Only probe "regular" interrupts, don't * touch dangerous spots like the mouse irq, @@ -546,23 +574,23 @@ extern void cardbus_register(pci_socket_t *socket); /* - * Watch a socket every second (and possibly in a - * more timely manner if the state change interrupt - * works..) + * 'Bottom half' for the yenta_open routine. Allocate the interrupt line + * and register the socket with the upper layers. */ -static int yenta_socket_thread(void * data) +static void yenta_open_bh(void * data) { pci_socket_t * socket = (pci_socket_t *) data; - DECLARE_WAITQUEUE(wait, current); - MOD_INC_USE_COUNT; - daemonize(); - strcpy(current->comm, "CardBus Watcher"); + /* It's OK to overwrite this now */ + socket->tq_task.routine = yenta_bh; - if (request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) { - printk ("Yenta: unable to register irq %d\n", socket->cb_irq); - MOD_DEC_USE_COUNT; - return (1); + if (!socket->cb_irq || request_irq(socket->cb_irq, yenta_interrupt, SA_SHIRQ, socket->dev->name, socket)) { + /* No IRQ or request_irq failed. Poll */ + socket->cb_irq = 0; /* But zero is a valid IRQ number. */ + socket->poll_timer.function = yenta_interrupt_wrapper; + socket->poll_timer.data = (unsigned long)socket; + socket->poll_timer.expires = jiffies + HZ; + add_timer(&socket->poll_timer); } /* Figure out what the dang thing can do for the PCMCIA layer... */ @@ -572,23 +600,7 @@ /* Register it with the pcmcia layer.. */ cardbus_register(socket); - do { - unsigned int events = socket->events | yenta_events(socket); - - if (events) { - socket->events = 0; - if (socket->handler) - socket->handler(socket->info, events); - } - - current->state = TASK_INTERRUPTIBLE; - add_wait_queue(&socket->wait, &wait); - if (!socket->events) - schedule_timeout(HZ); - remove_wait_queue(&socket->wait, &wait); - } while (!signal_pending(current)); MOD_DEC_USE_COUNT; - return 0; } static void yenta_clear_maps(pci_socket_t *socket) @@ -745,6 +757,9 @@ { if (sock->cb_irq) free_irq(sock->cb_irq, sock); + else + del_timer_sync(&sock->poll_timer); + if (sock->base) iounmap(sock->base); } @@ -836,7 +851,16 @@ } } - kernel_thread(yenta_socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); + /* Get the PCMCIA kernel thread to complete the + initialisation later. We can't do this here, + because, er, because Linus says so :) + */ + socket->tq_task.routine = yenta_open_bh; + socket->tq_task.data = socket; + + MOD_INC_USE_COUNT; + schedule_task(&socket->tq_task); + return 0; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/s390/char/con3215.c linux/drivers/s390/char/con3215.c --- v2.4.0-test10/linux/drivers/s390/char/con3215.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/s390/char/con3215.c Wed Nov 15 00:41:03 2000 @@ -696,6 +696,7 @@ s390irq_spin_unlock_irqrestore(raw->irq, flags); schedule(); s390irq_spin_lock_irqsave(raw->irq, flags); + remove_wait_queue(&raw->empty_wait, &wait); current->state = TASK_RUNNING; raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c --- v2.4.0-test10/linux/drivers/sbus/char/aurora.c Mon Dec 20 22:06:42 1999 +++ linux/drivers/sbus/char/aurora.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: aurora.c,v 1.7 1999/09/21 14:37:46 davem Exp $ +/* $Id: aurora.c,v 1.9 2000/11/08 05:33:03 davem Exp $ * linux/drivers/sbus/char/aurora.c -- Aurora multiport driver * * Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro) @@ -2387,7 +2387,6 @@ #endif } -#ifndef MODULE /* * Called at boot time. * @@ -2406,10 +2405,7 @@ } } -int __init aurora_init(void) -#else -int aurora_init(void) -#endif +static int __init aurora_real_init(void) { int found; int i; @@ -2439,7 +2435,6 @@ return 0; } -#ifdef MODULE int irq = 0; int irq1 = 0; int irq2 = 0; @@ -2449,16 +2444,16 @@ MODULE_PARM(irq2, "i"); MODULE_PARM(irq3, "i"); -int init_module(void) +static int __init aurora_init(void) { if (irq ) irqs[0]=irq ; if (irq1) irqs[1]=irq1; if (irq2) irqs[2]=irq2; if (irq3) irqs[3]=irq3; - return aurora_init(); + return aurora_real_init(); } -void cleanup_module(void) +static void __exit aurora_cleanup(void) { int i; @@ -2473,4 +2468,6 @@ aurora_release_io_range(&aurora_board[i]); } } -#endif /* MODULE */ + +module_init(aurora_init); +module_exit(aurora_cleanup); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/bpp.c linux/drivers/sbus/char/bpp.c --- v2.4.0-test10/linux/drivers/sbus/char/bpp.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/sbus/char/bpp.c Thu Nov 9 15:57:41 2000 @@ -1017,11 +1017,7 @@ static devfs_handle_t devfs_handle; -#ifdef MODULE -int init_module(void) -#else -int __init bpp_init(void) -#endif +static int __init bpp_init(void) { int rc; unsigned idx; @@ -1046,8 +1042,7 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit bpp_cleanup(void) { unsigned idx; @@ -1059,4 +1054,6 @@ freeLptPort(idx); } } -#endif + +module_init(bpp_init); +module_exit(bpp_cleanup); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/display7seg.c linux/drivers/sbus/char/display7seg.c --- v2.4.0-test10/linux/drivers/sbus/char/display7seg.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sbus/char/display7seg.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: display7seg.c,v 1.3 2000/08/29 07:01:55 davem Exp $ +/* $Id: display7seg.c,v 1.4 2000/11/08 05:08:23 davem Exp $ * * display7seg - Driver implementation for the 7-segment display * present on Sun Microsystems CP1400 and CP1500 @@ -172,11 +172,7 @@ static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; -#ifdef MODULE -int init_module(void) -#else -int __init d7s_init(void) -#endif +static int __init d7s_init(void) { struct linux_ebus *ebus = NULL; struct linux_ebus_device *edev = NULL; @@ -222,8 +218,7 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit d7s_cleanup(void) { int regs = readb(d7s_regs); @@ -237,4 +232,6 @@ misc_deregister(&d7s_miscdev); d7s_free(); } -#endif + +module_init(d7s_init); +module_exit(d7s_cleanup); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c --- v2.4.0-test10/linux/drivers/sbus/char/envctrl.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/sbus/char/envctrl.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: envctrl.c,v 1.18 2000/10/17 16:20:35 davem Exp $ +/* $Id: envctrl.c,v 1.19 2000/11/03 00:37:40 davem Exp $ * envctrl.c: Temperature and Fan monitoring on Machines providing it. * * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) @@ -11,7 +11,9 @@ * http://www-eu2.semiconductors.com/pip/PCF8584P * http://www-eu2.semiconductors.com/pip/PCF8574AP * http://www-eu2.semiconductors.com/pip/PCF8591P - * + * + * EB - Added support for CP1500 Global Address and PS/Voltage monitoring. + * Eric Brower */ #include @@ -72,15 +74,16 @@ * Firmware definitions. */ #define PCF8584_MAX_CHANNELS 8 +#define PCF8584_GLOBALADDR_TYPE 6 /* global address monitor */ #define PCF8584_FANSTAT_TYPE 3 /* fan status monitor */ #define PCF8584_VOLTAGE_TYPE 2 /* voltage monitor */ -#define PCF8584_TEMP_TYPE 1 /* temperature monitor*/ +#define PCF8584_TEMP_TYPE 1 /* temperature monitor*/ /* Monitor type of i2c child device. * Driver definitions. */ -#define ENVCTRL_NOMON 0 -#define ENVCTRL_CPUTEMP_MON 1 /* cpu temperature monitor */ +#define ENVCTRL_NOMON 0 +#define ENVCTRL_CPUTEMP_MON 1 /* cpu temperature monitor */ #define ENVCTRL_CPUVOLTAGE_MON 2 /* voltage monitor */ #define ENVCTRL_FANSTAT_MON 3 /* fan status monitor */ #define ENVCTRL_ETHERTEMP_MON 4 /* ethernet temperarture */ @@ -88,6 +91,7 @@ #define ENVCTRL_VOLTAGESTAT_MON 5 /* voltage status monitor */ #define ENVCTRL_MTHRBDTEMP_MON 6 /* motherboard temperature */ #define ENVCTRL_SCSITEMP_MON 7 /* scsi temperarture */ +#define ENVCTRL_GLOBALADDR_MON 8 /* global address */ /* Child device type. * Driver definitions. @@ -109,6 +113,15 @@ #define ENVCTRL_MAX_CPU 4 #define CHANNEL_DESC_SZ 256 +/* Mask values for combined GlobalAddress/PowerStatus node */ +#define ENVCTRL_GLOBALADDR_ADDR_MASK 0x1F +#define ENVCTRL_GLOBALADDR_PSTAT_MASK 0x60 + +/* Node 0x70 ignored on CompactPCI CP1400/1500 platforms + * (see envctrl_init_i2c_child) + */ +#define ENVCTRL_CPCI_IGNORED_NODE 0x70 + struct pcf8584_reg { unsigned char data; unsigned char csr; @@ -317,7 +330,6 @@ /* Do a single byte read and send stop. */ rd = envctrl_i2c_read_data(); envctrl_i2c_stop(); - return rd; } @@ -462,7 +474,32 @@ return 1; } -/* Function Description: Read voltage and power supply status. +/* Function Description: Read global addressing line. + * Return : Always 1 byte. Status stored in bufdata. + */ +static int envctrl_i2c_globaladdr(struct i2c_child_t *pchild, + unsigned char data, + char *bufdata) +{ + /* Translatation table is not necessary, as global + * addr is the integer value of the GA# bits. + * + * NOTE: MSB is documented as zero, but I see it as '1' always.... + * + * ----------------------------------------------- + * | 0 | FAL | DEG | GA4 | GA3 | GA2 | GA1 | GA0 | + * ----------------------------------------------- + * GA0 - GA4 integer value of Global Address (backplane slot#) + * DEG 0 = cPCI Power supply output is starting to degrade + * 1 = cPCI Power supply output is OK + * FAL 0 = cPCI Power supply has failed + * 1 = cPCI Power supply output is OK + */ + bufdata[0] = (data & ENVCTRL_GLOBALADDR_ADDR_MASK); + return 1; +} + +/* Function Description: Read standard voltage and power supply status. * Return : Always 1 byte. Status stored in bufdata. */ static unsigned char envctrl_i2c_voltage_status(struct i2c_child_t *pchild, @@ -587,10 +624,20 @@ ret = envctrl_i2c_fan_status(pchild,data[0], data); copy_to_user((unsigned char *)buf, data, ret); break; + + case ENVCTRL_RD_GLOBALADDRESS: + if (!(pchild = envctrl_get_i2c_child(ENVCTRL_GLOBALADDR_MON))) + return 0; + data[0] = envctrl_i2c_read_8574(pchild->addr); + ret = envctrl_i2c_globaladdr(pchild, data[0], data); + copy_to_user((unsigned char *)buf, data, ret); + break; case ENVCTRL_RD_VOLTAGE_STATUS: if (!(pchild = envctrl_get_i2c_child(ENVCTRL_VOLTAGESTAT_MON))) - return 0; + /* If voltage monitor not present, check for CPCI equivalent */ + if (!(pchild = envctrl_get_i2c_child(ENVCTRL_GLOBALADDR_MON))) + return 0; data[0] = envctrl_i2c_read_8574(pchild->addr); ret = envctrl_i2c_voltage_status(pchild, data[0], data); copy_to_user((unsigned char *)buf, data, ret); @@ -621,6 +668,7 @@ case ENVCTRL_RD_VOLTAGE_STATUS: case ENVCTRL_RD_ETHERNET_TEMPERATURE: case ENVCTRL_RD_SCSI_TEMPERATURE: + case ENVCTRL_RD_GLOBALADDRESS: file->private_data = (void *)(long)cmd; break; @@ -714,9 +762,6 @@ if (!(strcmp(chnl_desc,"temp,ethernet"))) pchild->mon_type[chnl_no] = ENVCTRL_ETHERTEMP_MON; - - if (!(strcmp(chnl_desc,"temp,ethernet"))) - pchild->mon_type[chnl_no] = ENVCTRL_ETHERTEMP_MON; } /* Function Description: Initialize monitor channel with channel desc, @@ -770,6 +815,39 @@ pchild->mon_type[0] = ENVCTRL_FANSTAT_MON; } +/* Function Description: Initialize child device for global addressing line. + * Return: None. + */ +static void envctrl_init_globaladdr(struct i2c_child_t *pchild) +{ + int i; + + /* Voltage/PowerSupply monitoring is piggybacked + * with Global Address on CompactPCI. See comments + * within envctrl_i2c_globaladdr for bit assignments. + * + * The mask is created here by assigning mask bits to each + * bit position that represents PCF8584_VOLTAGE_TYPE data. + * Channel numbers are not consecutive within the globaladdr + * node (why?), so we use the actual counter value as chnls_mask + * index instead of the chnl_array[x].chnl_no value. + * + * NOTE: This loop could be replaced with a constant representing + * a mask of bits 5&6 (ENVCTRL_GLOBALADDR_PSTAT_MASK). + */ + for (i = 0; i < pchild->total_chnls; i++) { + if (PCF8584_VOLTAGE_TYPE == pchild->chnl_array[i].type) { + pchild->voltage_mask |= chnls_mask[i]; + } + } + + /* We only need to know if this child has global addressing + * line monitored. We dont care which channels since we know + * the mask already (ENVCTRL_GLOBALADDR_ADDR_MASK). + */ + pchild->mon_type[0] = ENVCTRL_GLOBALADDR_MON; +} + /* Initialize child device monitoring voltage status. */ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) { @@ -822,6 +900,27 @@ } } + /* SPARCengine ASM Reference Manual (ref. SMI doc 805-7581-04) + * sections 2.5, 3.5, 4.5 state node 0x70 for CP1400/1500 is + * "For Factory Use Only." + * + * We ignore the node on these platforms by assigning the + * 'NULL' monitor type. + */ + if (ENVCTRL_CPCI_IGNORED_NODE == pchild->addr) { + int len; + char prop[56]; + + len = prom_getproperty(prom_root_node, "name", prop, sizeof(prop)); + if (0 < len && (0 == strncmp(prop, "SUNW,UltraSPARC-IIi-cEngine", len))) + { + for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) { + pchild->mon_type[len] = ENVCTRL_NOMON; + } + return; + } + } + /* Get the monitor channels. */ len = prom_getproperty(node, "channels-in-use", (char *) pchild->chnl_array, @@ -835,6 +934,11 @@ envctrl_init_adc(pchild, node); break; + case PCF8584_GLOBALADDR_TYPE: + envctrl_init_globaladdr(pchild); + i = pchild->total_chnls; + break; + case PCF8584_FANSTAT_TYPE: envctrl_init_fanstat(pchild); i = pchild->total_chnls; @@ -865,7 +969,7 @@ for (i = 0; i < ENVCTRL_MAX_CPU*2; i++) { for (j = 0; j < PCF8584_MAX_CHANNELS; j++) { if (i2c_childlist[i].mon_type[j] == mon_type) { - return (struct i2c_child_t*)(&(i2c_childlist[i])); + return (struct i2c_child_t *)(&(i2c_childlist[i])); } } } @@ -932,8 +1036,7 @@ * child devices. */ printk("envctrl: initialized "); - for(--i; i >= 0; --i) - { + for (--i; i >= 0; --i) { printk("[%s 0x%lx]%s", (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") : ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")), diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c --- v2.4.0-test10/linux/drivers/sbus/char/flash.c Tue Jul 18 12:29:47 2000 +++ linux/drivers/sbus/char/flash.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: flash.c,v 1.19 2000/07/13 08:06:40 davem Exp $ +/* $Id: flash.c,v 1.20 2000/11/08 04:57:49 davem Exp $ * flash.c: Allow mmap access to the OBP Flash, for OBP updates. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -149,11 +149,7 @@ EXPORT_NO_SYMBOLS; -#ifdef MODULE -int init_module(void) -#else -int __init flash_init(void) -#endif +static int __init flash_init(void) { struct sbus_bus *sbus; struct sbus_dev *sdev = 0; @@ -236,9 +232,10 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit flash_cleanup(void) { misc_deregister(&flash_dev); } -#endif + +module_init(flash_init); +module_exit(flash_cleanup); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c --- v2.4.0-test10/linux/drivers/sbus/char/openprom.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sbus/char/openprom.c Thu Nov 9 15:57:41 2000 @@ -626,11 +626,7 @@ EXPORT_NO_SYMBOLS; -#ifdef MODULE -int init_module(void) -#else -int __init openprom_init(void) -#endif +static int __init openprom_init(void) { unsigned long flags; int error; @@ -655,9 +651,10 @@ return 0; } -#ifdef MODULE -void cleanup_module(void) +static void __exit openprom_cleanup(void) { misc_deregister(&openprom_dev); } -#endif + +module_init(openprom_init); +module_exit(openprom_cleanup); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c --- v2.4.0-test10/linux/drivers/sbus/char/sab82532.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/sbus/char/sab82532.c Tue Nov 14 23:36:01 2000 @@ -1,4 +1,4 @@ -/* $Id: sab82532.c,v 1.52 2000/10/14 10:09:04 davem Exp $ +/* $Id: sab82532.c,v 1.53 2000/11/15 07:28:09 davem Exp $ * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC. * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -1833,6 +1833,7 @@ #endif schedule(); } + current->state = TASK_RUNNING; remove_wait_queue(&info->open_wait, &wait); if (!tty_hung_up_p(filp)) info->count++; @@ -2133,7 +2134,7 @@ static inline void __init show_serial_version(void) { - char *revision = "$Revision: 1.52 $"; + char *revision = "$Revision: 1.53 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c --- v2.4.0-test10/linux/drivers/sbus/char/su.c Tue Oct 31 12:42:26 2000 +++ linux/drivers/sbus/char/su.c Tue Nov 14 23:36:01 2000 @@ -1,4 +1,4 @@ -/* $Id: su.c,v 1.42 2000/10/14 10:09:04 davem Exp $ +/* $Id: su.c,v 1.43 2000/11/15 07:28:09 davem Exp $ * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI * * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) @@ -2001,6 +2001,7 @@ #endif schedule(); } + current->state = TASK_RUNNING; remove_wait_queue(&info->open_wait, &wait); if (extra_count) info->count++; @@ -2219,7 +2220,7 @@ */ static __inline__ void __init show_su_version(void) { - char *revision = "$Revision: 1.42 $"; + char *revision = "$Revision: 1.43 $"; char *version, *p; version = strchr(revision, ' '); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/char/uctrl.c linux/drivers/sbus/char/uctrl.c --- v2.4.0-test10/linux/drivers/sbus/char/uctrl.c Mon Jun 19 17:59:41 2000 +++ linux/drivers/sbus/char/uctrl.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: uctrl.c,v 1.8 2000/06/19 06:24:47 davem Exp $ +/* $Id: uctrl.c,v 1.9 2000/11/08 05:04:06 davem Exp $ * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 * * Copyright 1999 Derrick J Brashear (shadow@dementia.org) @@ -363,11 +363,7 @@ } -#ifdef MODULE -int init_module(void) -#else -int __init ts102_uctrl_init(void) -#endif +static int __init ts102_uctrl_init(void) { struct uctrl_driver *driver = &drv; int len, i; @@ -419,9 +415,7 @@ return 0; } - -#ifdef MODULE -void cleanup_module(void) +static void __exit ts102_uctrl_cleanup(void) { struct uctrl_driver *driver = &drv; @@ -433,4 +427,6 @@ if (driver->regs) driver->regs = 0; } -#endif + +module_init(ts102_uctrl_init); +module_exit(ts102_uctrl_cleanup); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c --- v2.4.0-test10/linux/drivers/sbus/sbus.c Thu Mar 16 11:40:17 2000 +++ linux/drivers/sbus/sbus.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: sbus.c,v 1.86 2000/03/16 09:23:57 jj Exp $ +/* $Id: sbus.c,v 1.91 2000/11/08 05:04:06 davem Exp $ * sbus.c: SBus support routines. * * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) @@ -165,21 +165,9 @@ extern void iommu_init(int iommu_node, struct sbus_bus *sbus); extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus); void sun4_init(void); -#ifdef CONFIG_SUN_OPENPROMIO -extern int openprom_init(void); -#endif #ifdef CONFIG_SUN_AUXIO extern void auxio_probe(void); #endif -#ifdef CONFIG_OBP_FLASH -extern int flash_init(void); -#endif -#ifdef CONFIG_SUN_AURORA -extern int aurora_init(void); -#endif -#ifdef CONFIG_TADPOLE_TS102_UCTRL -extern int ts102_uctrl_init(void); -#endif static void __init sbus_do_child_siblings(int start_node, struct sbus_dev *child, @@ -520,24 +508,9 @@ firetruck_init(); } #endif -#ifdef CONFIG_SUN_OPENPROMIO - openprom_init(); -#endif -#ifdef CONFIG_SUN_BPP - bpp_init(); -#endif #ifdef CONFIG_SUN_AUXIO if (sparc_cpu_model == sun4u) auxio_probe (); -#endif -#ifdef CONFIG_OBP_FLASH - flash_init(); -#endif -#ifdef CONFIG_SUN_AURORA - aurora_init(); -#endif -#ifdef CONFIG_TADPOLE_TS102_UCTRL - ts102_uctrl_init(); #endif #ifdef __sparc_v9__ if (sparc_cpu_model == sun4u) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/3w-xxxx.c linux/drivers/scsi/3w-xxxx.c --- v2.4.0-test10/linux/drivers/scsi/3w-xxxx.c Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/3w-xxxx.c Wed Nov 8 17:09:50 2000 @@ -696,8 +696,13 @@ /* Register the card with the kernel SCSI layer */ host = scsi_register(tw_host, sizeof(TW_Device_Extension)); - - /* FIXME - check for NULL */ + if( host == NULL) + { + release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); + tw_free_device_extension(tw_dev); + kfree(tw_dev); + continue; + } status_reg_value = inl(tw_dev->registers.status_reg_addr); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c --- v2.4.0-test10/linux/drivers/scsi/53c7xx.c Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/53c7xx.c Sat Nov 11 19:01:11 2000 @@ -1125,6 +1125,7 @@ int script_len = 0, dsa_len = 0, size = 0, max_cmd_size = 0, schedule_size = 0, ok = 0; void *tmp; + unsigned long page; switch (chip) { case 710: @@ -1191,6 +1192,12 @@ */ (sizeof(void *) - sizeof(u32)) + max_cmd_size + schedule_size; + page = __get_free_pages(GFP_ATOMIC,1); + if(page==0) + { + printk(KERN_ERR "53c7xx: out of memory.\n"); + return -ENOMEM; + } #ifdef FORCE_DSA_ALIGNMENT /* * 53c710 rev.0 doesn't have an add-with-carry instruction. @@ -1203,10 +1210,11 @@ panic("53c7xx: hostdata > 8K"); instance = scsi_register (tpnt, 4); if (!instance) + { + free_page(page); return -1; - instance->hostdata[0] = __get_free_pages(GFP_ATOMIC, 1); - if (instance->hostdata[0] == 0) - panic ("53c7xx: Couldn't get hostdata memory"); + } + instance->hostdata[0] = page; memset((void *)instance->hostdata[0], 0, 8192); cache_push(virt_to_phys((void *)(instance->hostdata[0])), 8192); cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 8192); @@ -3087,7 +3095,7 @@ panic ("53c7xx: allocate_cmd size > 4K"); real = get_free_page(GFP_ATOMIC); if (real == 0) - panic ("53c7xx: Couldn't get memory for allocate_cmd"); + return NULL; memset((void *)real, 0, 4096); cache_push(virt_to_phys((void *)real), 4096); cache_clear(virt_to_phys((void *)real), 4096); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/AM53C974.c linux/drivers/scsi/AM53C974.c --- v2.4.0-test10/linux/drivers/scsi/AM53C974.c Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/AM53C974.c Sun Nov 12 20:40:42 2000 @@ -1,4 +1,3 @@ -#include #include #include #include @@ -381,11 +380,11 @@ unsigned char statreg); static void AM53C974_intr_bus_reset(struct Scsi_Host *instance); -static struct Scsi_Host *first_instance = NULL; -static Scsi_Host_Template *the_template = NULL; -static struct Scsi_Host *first_host = NULL; /* Head of list of AMD boards */ -static volatile int main_running = 0; -static int commandline_current = 0; +static struct Scsi_Host *first_instance; +static Scsi_Host_Template *the_template; +static struct Scsi_Host *first_host; /* Head of list of AMD boards */ +static volatile int main_running; +static int commandline_current; override_t overrides[7] = { {-1, 0, 0, 0},}; /* LILO overrides */ @@ -571,19 +570,25 @@ restore_flags(flags); } +#ifndef MODULE /************************************************************************** -* Function : AM53C974_setup(char *str, int *ints) +* Function : AM53C974_setup(char *str) * * Purpose : LILO command line initialization of the overrides array, * -* Inputs : str - unused, ints - array of integer parameters with ints[0] -* equal to the number of ints. +* Input : str - parameter string. +* +* Returns : 1. * * NOTE : this function needs to be declared as an external function * in init/main.c and included there in the bootsetups list ***************************************************************************/ -void AM53C974_setup(char *str, int *ints) +static int AM53C974_setup(char *str) { + int ints[5]; + + get_options(str, ARRAY_SIZE(ints), ints); + if (ints[0] < 4) printk("AM53C974_setup: wrong number of parameters;\n correct syntax is: AM53C974=host-scsi-id, target-scsi-id, max-rate, max-offset\n"); else { @@ -604,9 +609,13 @@ } else printk("AM53C974_setup: too many overrides\n"); } + + return 1; } +__setup("AM53C974=", AM53C974_setup); + +#endif /* !MODULE */ -#if defined (CONFIG_PCI) /************************************************************************** * Function : int AM53C974_pci_detect(Scsi_Host_Template *tpnt) * @@ -616,7 +625,7 @@ * * Returns : number of host adapters detected **************************************************************************/ -static inline int AM53C974_pci_detect(Scsi_Host_Template * tpnt) +static int __init AM53C974_pci_detect(Scsi_Host_Template * tpnt) { int count = 0; /* number of boards detected */ struct pci_dev *pdev = NULL; @@ -639,29 +648,6 @@ } return (count); } -#endif - -/************************************************************************** -* Function : int AM53C974_detect(Scsi_Host_Template *tpnt) -* -* Purpose : detects and initializes AM53C974 SCSI chips -* -* Inputs : tpnt - host template -* -* Returns : number of host adapters detected -**************************************************************************/ -int __init AM53C974_detect(Scsi_Host_Template * tpnt) -{ - int count = 0; /* number of boards detected */ - - tpnt->proc_name = "am53c974"; - -#if defined (CONFIG_PCI) - if (pci_present()) - count = AM53C974_pci_detect(tpnt); -#endif - return (count); -} /************************************************************************** * Function : int AM53C974_init(Scsi_Host_Template *tpnt, struct pci_dev *pdev) @@ -810,7 +796,7 @@ * * * Returns : info string * ************************************************************************/ -const char *AM53C974_info(struct Scsi_Host *instance) +static const char *AM53C974_info(struct Scsi_Host *instance) { static char info[100]; @@ -830,7 +816,7 @@ * * * Returns :status, see hosts.h for details * ***************************************************************************/ -int AM53C974_command(Scsi_Cmnd * SCpnt) +static int AM53C974_command(Scsi_Cmnd * SCpnt) { DEB(printk("AM53C974_command called\n")); return 0; @@ -903,7 +889,7 @@ * twiddling done to the host specific fields of cmd. If the * main coroutine is not running, it is restarted. **************************************************************************/ -int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) +static int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) { unsigned long flags; struct Scsi_Host *instance = cmd->host; @@ -2283,7 +2269,7 @@ * * Returns : 0 - success, -1 on failure. **************************************************************************/ -int AM53C974_abort(Scsi_Cmnd * cmd) +static int AM53C974_abort(Scsi_Cmnd * cmd) { AM53C974_local_declare(); unsigned long flags; @@ -2391,7 +2377,7 @@ * * FIXME(eric) the reset_flags are ignored. **************************************************************************/ -int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int reset_flags) +static int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int reset_flags) { AM53C974_local_declare(); unsigned long flags; @@ -2447,7 +2433,7 @@ * * Release resources allocated for a single AM53C974 adapter. */ -int AM53C974_release(struct Scsi_Host *shp) +static int AM53C974_release(struct Scsi_Host *shp) { free_irq(shp->irq, shp); scsi_unregister(shp); @@ -2455,11 +2441,9 @@ } -#ifdef MODULE /* You can specify overrides=a,b,c,d in the same format at AM53C974=a,b,c,d on boot up */ MODULE_PARM(overrides, "1-32i"); -#endif static Scsi_Host_Template driver_template = AM53C974; #include "scsi_module.c" diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/AM53C974.h linux/drivers/scsi/AM53C974.h --- v2.4.0-test10/linux/drivers/scsi/AM53C974.h Tue Jan 25 13:01:14 2000 +++ linux/drivers/scsi/AM53C974.h Tue Nov 7 10:59:43 2000 @@ -53,7 +53,7 @@ #define AM53C974 { \ proc_name: "am53c974", \ name: "AM53C974", \ - detect: AM53C974_detect, \ + detect: AM53C974_pci_detect, \ release: AM53C974_release, \ info: AM53C974_info, \ command: AM53C974_command, \ @@ -68,14 +68,12 @@ use_clustering: DISABLE_CLUSTERING \ } -void AM53C974_setup(char *str, int *ints); -int AM53C974_detect(Scsi_Host_Template * tpnt); -int AM53C974_release(struct Scsi_Host *shp); -int AM53C974_biosparm(Disk * disk, int dev, int *info_array); -const char *AM53C974_info(struct Scsi_Host *); -int AM53C974_command(Scsi_Cmnd * SCpnt); -int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); -int AM53C974_abort(Scsi_Cmnd * cmd); -int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int); +static int AM53C974_pci_detect(Scsi_Host_Template * tpnt); +static int AM53C974_release(struct Scsi_Host *shp); +static const char *AM53C974_info(struct Scsi_Host *); +static int AM53C974_command(Scsi_Cmnd * SCpnt); +static int AM53C974_queue_command(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)); +static int AM53C974_abort(Scsi_Cmnd * cmd); +static int AM53C974_reset(Scsi_Cmnd * cmd, unsigned int); #endif /* AM53C974_H */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c --- v2.4.0-test10/linux/drivers/scsi/BusLogic.c Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/BusLogic.c Sat Nov 11 19:01:11 2000 @@ -2793,6 +2793,11 @@ Register the SCSI Host structure. */ Host = scsi_register(HostTemplate, sizeof(BusLogic_HostAdapter_T)); + if(Host==NULL) + { + release_region(HostAdapter->IO_Address, HostAdapter->AddressCount); + continue; + } HostAdapter = (BusLogic_HostAdapter_T *) Host->hostdata; memcpy(HostAdapter, PrototypeHostAdapter, sizeof(BusLogic_HostAdapter_T)); HostAdapter->SCSI_Host = Host; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in --- v2.4.0-test10/linux/drivers/scsi/Config.in Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/Config.in Tue Nov 7 10:59:43 2000 @@ -57,7 +57,7 @@ fi dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI -dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI +dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI $CONFIG_PCI dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/a2091.c linux/drivers/scsi/a2091.c --- v2.4.0-test10/linux/drivers/scsi/a2091.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/a2091.c Sun Nov 12 09:41:36 2000 @@ -207,6 +207,10 @@ continue; instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata)); + if (instance == NULL) { + release_mem_region(address, 256); + continue; + } instance->base = ZTWO_VADDR(address); instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/a3000.c linux/drivers/scsi/a3000.c --- v2.4.0-test10/linux/drivers/scsi/a3000.c Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/a3000.c Sat Nov 11 19:01:11 2000 @@ -175,6 +175,8 @@ tpnt->proc_info = &wd33c93_proc_info; a3000_host = scsi_register (tpnt, sizeof(struct WD33C93_hostdata)); + if(a3000_host == NULL) + return 0; a3000_host->base = ZTWO_VADDR(0xDD0000); a3000_host->irq = IRQ_AMIGA_PORTS; DMA(a3000_host)->DAWR = DAWR_A3000; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c --- v2.4.0-test10/linux/drivers/scsi/advansys.c Sun Oct 8 10:50:21 2000 +++ linux/drivers/scsi/advansys.c Sat Nov 11 19:01:11 2000 @@ -4774,6 +4774,9 @@ */ ASC_DBG(2, "advansys_detect: scsi_register()\n"); shp = scsi_register(tpnt, sizeof(asc_board_t)); + + if(shp==NULL) + continue; /* Save a pointer to the Scsi_host of each board found. */ asc_host[asc_board_count++] = shp; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c --- v2.4.0-test10/linux/drivers/scsi/aha152x.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/aha152x.c Wed Nov 8 17:09:50 2000 @@ -13,9 +13,16 @@ * General Public License for more details. * * - * $Id: aha152x.c,v 2.1 2000/05/17 16:23:17 fischer Exp fischer $ + * $Id: aha152x.c,v 2.3 2000/11/04 16:40:26 fischer Exp $ * * $Log: aha152x.c,v $ + * Revision 2.3 2000/11/04 16:40:26 fischer + * - handle data overruns + * - extend timeout for data phases + * + * Revision 2.2 2000/08/08 19:54:53 fischer + * - minor changes + * * Revision 2.1 2000/05/17 16:23:17 fischer * - signature update * - fix for data out w/o scatter gather @@ -256,7 +263,7 @@ #define DO_LOCK(flags) \ do { \ - if(QLOCK.lock) { \ + if(spin_is_locked(&QLOCK)) { \ DPRINTK(debug_intr, DEBUG_LEAD "(%s:%d) already locked at %s:%d\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__, QLOCKER, QLOCKERL); \ } \ DPRINTK(debug_locks, DEBUG_LEAD "(%s:%d) locking\n", CMDINFO(CURRENT_SC), __FUNCTION__, __LINE__); \ @@ -293,7 +300,6 @@ (cmd) ? ((cmd)->lun & 0x07) : -1 #define DELAY_DEFAULT 100 -#define DEBUG_DEFAULT 0 /* possible irq range */ #if defined(PCMCIA) @@ -357,11 +363,11 @@ #if !defined(AHA152X_DEBUG) MODULE_PARM(aha152x, "1-8i"); MODULE_PARM_DESC(aha152x, "parameters for first controller"); -static int aha152x[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; +static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; MODULE_PARM(aha152x1, "1-8i"); MODULE_PARM_DESC(aha152x1, "parameters for second controller"); -static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; +static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; #else MODULE_PARM(debug, "1-2i"); MODULE_PARM_DESC(debug, "flags for driver debugging"); @@ -369,11 +375,11 @@ MODULE_PARM(aha152x, "1-9i"); MODULE_PARM_DESC(aha152x, "parameters for first controller"); -static int aha152x[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; +static int aha152x[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; MODULE_PARM(aha152x1, "1-9i"); MODULE_PARM_DESC(aha152x1, "parameters for second controller"); -static int aha152x1[] = {0, 11, 7, 1, 1, 0, DELAY_DEFAULT, 0}; +static int aha152x1[] = {0, 11, 7, 1, 1, 1, DELAY_DEFAULT, 0, DEBUG_DEFAULT}; #endif /* !defined(AHA152X_DEBUG) */ #endif /* MODULE */ @@ -954,7 +960,7 @@ if (setup_count < 2) { struct aha152x_setup override = SETUP0; - if (setup_count == 0 || (override.io_port != setup[0].io_port)) + if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if (!checksetup(&override)) { printk(KERN_ERR "\naha152x: invalid override SETUP0={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", override.io_port, @@ -967,6 +973,7 @@ override.ext_trans); } else setup[setup_count++] = override; + } } #endif @@ -974,7 +981,7 @@ if (setup_count < 2) { struct aha152x_setup override = SETUP1; - if (setup_count == 0 || (override.io_port != setup[0].io_port)) + if (setup_count == 0 || (override.io_port != setup[0].io_port)) { if (!checksetup(&override)) { printk(KERN_ERR "\naha152x: invalid override SETUP1={0x%x,%d,%d,%d,%d,%d,%d,%d}\n", override.io_port, @@ -987,6 +994,7 @@ override.ext_trans); } else setup[setup_count++] = override; + } } #endif @@ -2436,8 +2444,13 @@ static void msgo_end(struct Scsi_Host *shpnt) { - if(MSGO_I0 && CURRENT_SC->SCp.this_residual>0) { - data_count = fifodata>CURRENT_SC->SCp.this_residual ? - CURRENT_SC->SCp.this_residual : - fifodata; - fifodata -= data_count; - - if(data_count & 1) { - DPRINTK(debug_datai, DEBUG_LEAD "8bit\n", CMDINFO(CURRENT_SC)); - SETPORT(DMACNTRL0, ENDMA|_8BIT); - *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); - CURRENT_SC->SCp.this_residual--; - DATA_LEN++; - SETPORT(DMACNTRL0, ENDMA); - } - - if(data_count > 1) { - DPRINTK(debug_datai, DEBUG_LEAD "16bit(%d)\n", CMDINFO(CURRENT_SC), data_count); - data_count >>= 1; - insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); - CURRENT_SC->SCp.ptr += 2 * data_count; - CURRENT_SC->SCp.this_residual -= 2 * data_count; - DATA_LEN += 2 * data_count; - } - - if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { - /* advance to next buffer */ - CURRENT_SC->SCp.buffers_residual--; - CURRENT_SC->SCp.buffer++; - CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; - CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; - } - } - - if(fifodata>0 && CURRENT_SC->SCp.this_residual==0) { + if(CURRENT_SC->SCp.this_residual>0) { + while(fifodata>0 && CURRENT_SC->SCp.this_residual>0) { + data_count = fifodata>CURRENT_SC->SCp.this_residual ? + CURRENT_SC->SCp.this_residual : + fifodata; + fifodata -= data_count; + + if(data_count & 1) { + DPRINTK(debug_datai, DEBUG_LEAD "8bit\n", CMDINFO(CURRENT_SC)); + SETPORT(DMACNTRL0, ENDMA|_8BIT); + *CURRENT_SC->SCp.ptr++ = GETPORT(DATAPORT); + CURRENT_SC->SCp.this_residual--; + DATA_LEN++; + SETPORT(DMACNTRL0, ENDMA); + } + + if(data_count > 1) { + DPRINTK(debug_datai, DEBUG_LEAD "16bit(%d)\n", CMDINFO(CURRENT_SC), data_count); + data_count >>= 1; + insw(DATAPORT, CURRENT_SC->SCp.ptr, data_count); + CURRENT_SC->SCp.ptr += 2 * data_count; + CURRENT_SC->SCp.this_residual -= 2 * data_count; + DATA_LEN += 2 * data_count; + } + + if(CURRENT_SC->SCp.this_residual==0 && CURRENT_SC->SCp.buffers_residual>0) { + /* advance to next buffer */ + CURRENT_SC->SCp.buffers_residual--; + CURRENT_SC->SCp.buffer++; + CURRENT_SC->SCp.ptr = CURRENT_SC->SCp.buffer->address; + CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; + } + } + } else if(fifodata>0) { printk(ERR_LEAD "no buffers left for %d(%d) bytes (data overrun!?)\n", CMDINFO(CURRENT_SC), fifodata, GETPORT(FIFOSTAT)); - break; + SETPORT(DMACNTRL0, ENDMA|_8BIT); + while(fifodata>0) { + int data; + data=GETPORT(DATAPORT); + DPRINTK(debug_datai, DEBUG_LEAD "data=%02x\n", CMDINFO(CURRENT_SC), data); + fifodata--; + DATA_LEN++; + } + SETPORT(DMACNTRL0, ENDMA|_8BIT); } } @@ -2714,7 +2735,7 @@ CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length; } - the_time=jiffies+100; + the_time=jiffies+10*HZ; while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time)) barrier(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h --- v2.4.0-test10/linux/drivers/scsi/aha152x.h Fri Sep 8 12:54:34 2000 +++ linux/drivers/scsi/aha152x.h Sat Nov 4 09:28:11 2000 @@ -2,7 +2,7 @@ #define _AHA152X_H /* - * $Id: aha152x.h,v 2.0 1999/12/25 15:08:35 fischer Exp fischer $ + * $Id: aha152x.h,v 2.3 2000/11/04 16:41:37 fischer Exp $ */ #if defined(__KERNEL__) @@ -27,7 +27,7 @@ (unless we support more than 1 cmd_per_lun this should do) */ #define AHA152X_MAXQUEUE 7 -#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.0 $" +#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.3 $" /* Initial value of Scsi_Host entry */ #define AHA152X { proc_name: "aha152x", \ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c --- v2.4.0-test10/linux/drivers/scsi/aha1542.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/aha1542.c Sat Nov 11 19:01:11 2000 @@ -1154,6 +1154,8 @@ shpnt = scsi_register(tpnt, sizeof(struct aha1542_hostdata)); + if(shpnt==NULL) + continue; /* For now we do this - until kmalloc is more intelligent we are resigned to stupid hacks like this */ if (SCSI_PA(shpnt) >= ISA_DMA_THRESHOLD) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/aha1740.c linux/drivers/scsi/aha1740.c --- v2.4.0-test10/linux/drivers/scsi/aha1740.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/aha1740.c Sat Nov 11 19:01:11 2000 @@ -541,6 +541,11 @@ continue; } shpnt = scsi_register(tpnt, sizeof(struct aha1740_hostdata)); + if(shpnt == NULL) + { + free_irq(irq_level, NULL); + continue; + } request_region(slotbase, SLOTSIZE, "aha1740"); shpnt->base = 0; shpnt->io_port = slotbase; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/atari_scsi.c linux/drivers/scsi/atari_scsi.c --- v2.4.0-test10/linux/drivers/scsi/atari_scsi.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/atari_scsi.c Sat Nov 11 19:01:11 2000 @@ -667,6 +667,12 @@ } #endif instance = scsi_register (host, sizeof (struct NCR5380_hostdata)); + if(instance == NULL) + { + atari_stram_free(atari_dma_buffer); + atari_dma_buffer = 0; + return 0; + } atari_scsi_host = instance; /* Set irq to 0, to avoid that the mid-level code disables our interrupt * during queue_command calls. This is completely unnecessary, and even diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c --- v2.4.0-test10/linux/drivers/scsi/atp870u.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/atp870u.c Sat Nov 11 19:01:11 2000 @@ -1734,6 +1734,8 @@ dev->ultra_map = 0xffff; } shpnt = scsi_register(tpnt, 4); + if(shpnt==NULL) + return count; save_flags(flags); cli(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c --- v2.4.0-test10/linux/drivers/scsi/cpqfcTSinit.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/cpqfcTSinit.c Sat Nov 11 19:01:11 2000 @@ -290,6 +290,9 @@ (ULONG)sizeof(CPQFCHBA)); HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) ); + + if(HostAdapter == NULL) + continue; DEBUG_PCI( printk(" HBA found!\n")); DEBUG_PCI( printk(" HostAdapter->PciDev->irq = %u\n", PciDev->irq) ); DEBUG_PCI(printk(" PciDev->baseaddress[]= %lx\n", PciDev->base_address[0])); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/dmx3191d.c linux/drivers/scsi/dmx3191d.c --- v2.4.0-test10/linux/drivers/scsi/dmx3191d.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/dmx3191d.c Sat Nov 11 19:01:11 2000 @@ -82,6 +82,11 @@ request_region(port, DMX3191D_REGION, DMX3191D_DRIVER_NAME); instance = scsi_register(tmpl, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + { + release_region(port, DMX3191D_REGION); + continue; + } instance->io_port = port; instance->irq = pdev->irq; NCR5380_init(instance, FLAG_NO_PSEUDO_DMA | FLAG_DTC3181E); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/dtc.c linux/drivers/scsi/dtc.c --- v2.4.0-test10/linux/drivers/scsi/dtc.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/dtc.c Sat Nov 11 19:01:11 2000 @@ -241,6 +241,9 @@ break; instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + break; + instance->base = base; NCR5380_init(instance, 0); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c --- v2.4.0-test10/linux/drivers/scsi/eata_dma.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/eata_dma.c Sat Nov 11 19:01:11 2000 @@ -554,7 +554,17 @@ GFP_ATOMIC | GFP_DMA); } if (ccb->sg_list == NULL) - panic("eata_dma: Run out of DMA memory for SG lists !\n"); + { + /* + * Claim the bus was busy. Actually we are the problem but this + * will do a deferred retry for us ;) + */ + printk(KERN_ERR "eata_dma: Run out of DMA memory for SG lists !\n"); + cmd->result = DID_BUS_BUSY << 16; + ccb->status = FREE; + done(cmd); + return(0); + } ccb->cp_dataDMA = htonl(virt_to_bus(ccb->sg_list)); ccb->cp_datalen = htonl(cmd->use_sg * sizeof(struct eata_sg_list)); @@ -909,8 +919,17 @@ cp = (struct eata_ccb *) kmalloc(sizeof(struct eata_ccb), GFP_ATOMIC | GFP_DMA); + + if(cp==NULL) + return NULL; + sp = (struct eata_sp *) kmalloc(sizeof(struct eata_sp), GFP_ATOMIC | GFP_DMA); + if(sp==NULL) + { + kfree(cp); + return NULL; + } buff = dma_scratch; @@ -1463,6 +1482,10 @@ if(status == NULL || dma_scratch == NULL) { printk("eata_dma: can't allocate enough memory to probe for hosts !\n"); + if(status) + kfree(status); + if(dma_scratch) + kfree(dma_scratch); return(0); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/eata_dma_proc.c linux/drivers/scsi/eata_dma_proc.c --- v2.4.0-test10/linux/drivers/scsi/eata_dma_proc.c Mon Mar 13 22:15:03 2000 +++ linux/drivers/scsi/eata_dma_proc.c Sat Nov 11 19:01:11 2000 @@ -153,7 +153,18 @@ } else { SDev = scsi_get_host_dev(HBA_ptr); + + if(SDev == NULL) + return -ENOMEM; + scmd = scsi_allocate_request(SDev); + + if(scmd == NULL) + { + scsi_free_host_dev(SDev); + return -ENOMEM; + } + cmnd[0] = LOG_SENSE; cmnd[1] = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c --- v2.4.0-test10/linux/drivers/scsi/eata_pio.c Sun Oct 8 10:50:22 2000 +++ linux/drivers/scsi/eata_pio.c Sat Nov 11 19:01:11 2000 @@ -728,6 +728,12 @@ size = sizeof(hostdata) + (sizeof(struct eata_ccb) * ntohs(gc->queuesiz)); sh = scsi_register(tpnt, size); + if(sh == NULL) + { + release_region(base, 8); + return FALSE; + } + hd = SD(sh); memset(hd->ccb, 0, (sizeof(struct eata_ccb) * ntohs(gc->queuesiz))); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c --- v2.4.0-test10/linux/drivers/scsi/esp.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/esp.c Thu Nov 9 15:57:41 2000 @@ -1,4 +1,4 @@ -/* $Id: esp.c,v 1.97 2000/09/19 01:29:27 davem Exp $ +/* $Id: esp.c,v 1.98 2000/11/02 22:34:16 davem Exp $ * esp.c: EnhancedScsiProcessor Sun SCSI driver code. * * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu) @@ -400,7 +400,7 @@ * * struct scsi_cmnd: * - * We keep track of the syncronous capabilities of a target + * We keep track of the synchronous capabilities of a target * in the device member, using sync_min_period and * sync_max_offset. These are the values we directly write * into the ESP registers while running a command. If offset @@ -2661,7 +2661,7 @@ * on HME broken adapters because we skip the HME fifo * workaround code in esp_handle() if we are doing data * phase things. We don't want to fuck directly with - * the fifo like that, especially if doing syncronous + * the fifo like that, especially if doing synchronous * transfers! Also, will need to double the count on * HME if we are doing wide transfers, as the HME fifo * will move and count 16-bit quantities during wide data. diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/fcal.c linux/drivers/scsi/fcal.c --- v2.4.0-test10/linux/drivers/scsi/fcal.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/fcal.c Sat Nov 11 19:01:11 2000 @@ -128,7 +128,11 @@ if (!ages) continue; host = scsi_register (tpnt, sizeof (struct fcal)); - if (!host) panic ("Cannot register FCAL host\n"); + if (!host) + { + kfree(ages); + continue; + } nfcals++; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c --- v2.4.0-test10/linux/drivers/scsi/fdomain.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/fdomain.c Sat Nov 11 19:01:11 2000 @@ -965,6 +965,8 @@ get resources. */ shpnt = scsi_register( tpnt, 0 ); + if(shpnt == NULL) + return 0; shpnt->irq = interrupt_level; shpnt->io_port = port_base; shpnt->n_io_port = 0x10; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/g_NCR5380.c linux/drivers/scsi/g_NCR5380.c --- v2.4.0-test10/linux/drivers/scsi/g_NCR5380.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/g_NCR5380.c Sat Nov 11 19:01:11 2000 @@ -390,6 +390,17 @@ NCR5380_region_size, "ncr5380"); #endif instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + { +#ifdef CONFIG_SCSI_G_NCR5380_PORT + release_region(overrides[current_override].NCR5380_map_name, + NCR5380_region_size); +#else + release_mem_region(overrides[current_override].NCR5380_map_name, + NCR5380_region_size); +#endif + } + instance->NCR5380_instance_name = overrides[current_override].NCR5380_map_name; NCR5380_init(instance, flags); @@ -902,3 +913,4 @@ MODULE_PARM(dtc_3181e, "i"); #endif + diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/gdth.c linux/drivers/scsi/gdth.c --- v2.4.0-test10/linux/drivers/scsi/gdth.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/gdth.c Thu Nov 16 14:08:25 2000 @@ -3125,6 +3125,8 @@ break; if (gdth_search_isa(isa_bios)) { /* controller found */ shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if(shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_isa(isa_bios,ha)) { scsi_unregister(shp); @@ -3197,6 +3199,8 @@ break; if (gdth_search_eisa(eisa_slot)) { /* controller found */ shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if(shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_eisa(eisa_slot,ha)) { scsi_unregister(shp); @@ -3268,6 +3272,8 @@ if (gdth_ctr_count >= MAXHA) break; shp = scsi_register(shtp,sizeof(gdth_ext_str)); + if(shp == NULL) + continue; ha = HADATA(shp); if (!gdth_init_pci(&pcistr[ctr],ha)) { scsi_unregister(shp); @@ -3571,24 +3577,29 @@ ha = HADATA(gdth_ctr_tab[hanum]); sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]); - scp = scsi_allocate_device(sdev, 1, FALSE); + if (!sdev) + return; - scp->cmd_len = 12; - scp->use_sg = 0; + scp = scsi_allocate_device(sdev, 1, FALSE); - for (i = 0; i < MAX_HDRIVES; ++i) { - if (ha->hdr[i].present) { - gdtcmd.BoardNode = LOCALBOARD; - gdtcmd.Service = CACHESERVICE; - gdtcmd.OpCode = GDT_FLUSH; - gdtcmd.u.cache.DeviceNo = i; - gdtcmd.u.cache.BlockNo = 1; - gdtcmd.u.cache.sg_canz = 0; - TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); - gdth_do_cmd(scp, &gdtcmd, 30); + if (scp) { + scp->cmd_len = 12; + scp->use_sg = 0; + + for (i = 0; i < MAX_HDRIVES; ++i) { + if (ha->hdr[i].present) { + gdtcmd.BoardNode = LOCALBOARD; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_FLUSH; + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 1; + gdtcmd.u.cache.sg_canz = 0; + TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); + gdth_do_cmd(scp, &gdtcmd, 30); + } } + scsi_release_command(scp); } - scsi_release_command(scp); scsi_free_host_dev(sdev); } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/gdth_proc.c linux/drivers/scsi/gdth_proc.c --- v2.4.0-test10/linux/drivers/scsi/gdth_proc.c Wed Jul 5 11:24:41 2000 +++ linux/drivers/scsi/gdth_proc.c Sat Nov 11 19:01:11 2000 @@ -39,7 +39,17 @@ piowr = (gdth_iowr_str *)buffer; sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]); + + if(sdev==NULL) + return -ENOMEM; + scp = scsi_allocate_device(sdev, 1, FALSE); + + if(scp==NULL) + { + scsi_free_host_dev(sdev); + return -ENOMEM; + } scp->cmd_len = 12; scp->use_sg = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/gvp11.c linux/drivers/scsi/gvp11.c --- v2.4.0-test10/linux/drivers/scsi/gvp11.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/gvp11.c Sat Nov 11 19:01:11 2000 @@ -304,6 +304,8 @@ #endif instance = scsi_register (tpnt, sizeof (struct WD33C93_hostdata)); + if(instance == NULL) + goto release; instance->base = ZTWO_VADDR(address); instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/ibmmca.c linux/drivers/scsi/ibmmca.c --- v2.4.0-test10/linux/drivers/scsi/ibmmca.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/ibmmca.c Tue Oct 31 16:10:44 2000 @@ -1796,8 +1796,6 @@ /*--------------------------------------------------------------------*/ -#ifdef CONFIG_SCSI_IBMMCA - void internal_ibmmca_scsi_setup (char *str, int *ints) { int i, j, io_base, id_base; @@ -1851,8 +1849,6 @@ } return; } - -#endif /*--------------------------------------------------------------------*/ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c --- v2.4.0-test10/linux/drivers/scsi/imm.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/imm.c Sat Nov 11 19:01:11 2000 @@ -198,6 +198,8 @@ host->can_queue = IMM_CAN_QUEUE; host->sg_tablesize = imm_sg; hreg = scsi_register(host, 0); + if(hreg == NULL) + continue; hreg->io_port = pb->base; hreg->n_io_port = ports; hreg->dma_channel = -1; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/in2000.c linux/drivers/scsi/in2000.c --- v2.4.0-test10/linux/drivers/scsi/in2000.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/in2000.c Sat Nov 11 19:01:11 2000 @@ -2024,8 +2024,10 @@ */ tpnt->proc_name = "in2000"; - detect_count++; instance = scsi_register(tpnt, sizeof(struct IN2000_hostdata)); + if(instance == NULL) + continue; + detect_count++; if (!instance_list) instance_list = instance; hostdata = (struct IN2000_hostdata *)instance->hostdata; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c --- v2.4.0-test10/linux/drivers/scsi/ini9100u.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/ini9100u.c Sat Nov 11 19:01:11 2000 @@ -389,6 +389,11 @@ pHCB->HCS_Index = i; /* 7/29/98 */ hreg = scsi_register(tpnt, sizeof(HCS)); + if(hreg == NULL) + { + release_region(pHCB->HCS_Base, 256); + return 0; + } hreg->io_port = pHCB->HCS_Base; hreg->n_io_port = 0xff; hreg->can_queue = tul_num_scb; /* 03/05/98 */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c --- v2.4.0-test10/linux/drivers/scsi/inia100.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/inia100.c Sat Nov 11 19:01:11 2000 @@ -363,6 +363,7 @@ sz = orc_num_scb * sizeof(ESCB); if ((pHCB->HCS_virEscbArray = (PVOID) kmalloc(sz, GFP_ATOMIC | GFP_DMA)) == NULL) { printk("inia100: ESCB memory allocation error\n"); + /* ?? does pHCB->HCS_virtScbArray leak ??*/ return (0); } memset((unsigned char *) pHCB->HCS_virEscbArray, 0, sz); @@ -383,7 +384,8 @@ hreg = scsi_register(tpnt, sizeof(ORC_HCS)); if (hreg == NULL) { - printk("Invalid scsi_register pointer.\n"); + release_region(pHCB->HCS_Base, 256); /* Register */ + return 0; } hreg->io_port = pHCB->HCS_Base; hreg->n_io_port = 0xff; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c --- v2.4.0-test10/linux/drivers/scsi/ips.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/ips.c Wed Nov 8 17:09:50 2000 @@ -4552,6 +4552,8 @@ /* Allocate memory for the CCBs */ ha->scbs = (ips_scb_t *) kmalloc(ha->max_cmds * sizeof(ips_scb_t), GFP_ATOMIC|GFP_DMA); + if(ha->scbs == NULL) + return 0; memset(ha->scbs, 0, ha->max_cmds * sizeof(ips_scb_t)); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c --- v2.4.0-test10/linux/drivers/scsi/mac53c94.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/mac53c94.c Sat Nov 11 19:01:11 2000 @@ -78,8 +78,8 @@ panic("53c94: expected 2 addrs and intrs (got %d/%d)", node->n_addrs, node->n_intrs); host = scsi_register(tp, sizeof(struct fsc_state)); - if (host == 0) - panic("couldn't register 53c94 host"); + if (host == NULL) + break; host->unique_id = nfscs; #ifndef MODULE note_scsi_host(node, host); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/mac_scsi.c linux/drivers/scsi/mac_scsi.c --- v2.4.0-test10/linux/drivers/scsi/mac_scsi.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/mac_scsi.c Sat Nov 11 19:01:11 2000 @@ -258,6 +258,8 @@ for (count = 0; count < mac_num_scsi; count++) { #endif instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + continue; default_instance = instance; if (macintosh_config->ident == MAC_MODEL_IIFX) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c --- v2.4.0-test10/linux/drivers/scsi/megaraid.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/megaraid.c Wed Nov 8 17:09:50 2000 @@ -1491,21 +1491,6 @@ pciDev, pdev->slot_name); - /* - * Dont crash on boot with AMI cards configured for I2O. - * (our I2O code will find them then they will fail oddly until - * we figure why they upset our I2O code). This driver will die - * if it tries to boot an I2O mode board and we dont stop it now. - * - Alan Cox , Red Hat Software, Jan 2000 - */ - - if((pdev->class >> 8) == PCI_CLASS_INTELLIGENT_I2O) - { - printk( KERN_INFO "megaraid: Board configured for I2O, ignoring this card. Reconfigure the card\n" - KERN_INFO "megaraid: in the BIOS for \"mass storage\" to use it with this driver.\n"); - continue; - } - /* Read the base port and IRQ from PCI */ megaBase = pci_resource_start (pdev, 0); megaIrq = pdev->irq; @@ -1517,6 +1502,8 @@ /* Initialize SCSI Host structure */ host = scsi_register (pHostTmpl, sizeof (mega_host_config)); + if(host == NULL) + continue; megaCfg = (mega_host_config *) host->hostdata; memset (megaCfg, 0, sizeof (mega_host_config)); @@ -1543,12 +1530,11 @@ megaCtlrs[numCtlrs++] = megaCfg; if (flag != BOARD_QUARTZ) { /* Request our IO Range */ - if (check_region (megaBase, 16)) { + if (request_region (megaBase, 16, "megaraid")) { printk (KERN_WARNING "megaraid: Couldn't register I/O range!" CRLFSTR); scsi_unregister (host); continue; } - request_region (megaBase, 16, "megaraid"); } /* Request our IRQ */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c --- v2.4.0-test10/linux/drivers/scsi/pas16.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/pas16.c Sat Nov 11 19:01:11 2000 @@ -440,6 +440,9 @@ break; instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + break; + instance->io_port = io_port; NCR5380_init(instance, 0); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c --- v2.4.0-test10/linux/drivers/scsi/pci2000.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/pci2000.c Sat Nov 11 19:01:11 2000 @@ -682,6 +682,8 @@ if (pci_enable_device(pdev)) continue; pshost = scsi_register (tpnt, sizeof(ADAPTER2000)); + if(pshost == NULL) + continue; padapter = HOSTDATA(pshost); padapter->basePort = pci_resource_start (pdev, 1); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c --- v2.4.0-test10/linux/drivers/scsi/pci2220i.c Sun Oct 8 10:50:24 2000 +++ linux/drivers/scsi/pci2220i.c Sat Nov 11 19:01:11 2000 @@ -2545,6 +2545,9 @@ if (pci_enable_device(pcidev)) continue; pshost = scsi_register (tpnt, sizeof(ADAPTER2220I)); + if(pshost==NULL) + continue; + padapter = HOSTDATA(pshost); if ( GetRegs (pshost, FALSE, pcidev) ) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c --- v2.4.0-test10/linux/drivers/scsi/pluto.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/pluto.c Sat Nov 11 19:01:11 2000 @@ -221,7 +221,11 @@ if (!ages) continue; host = scsi_register (tpnt, sizeof (struct pluto)); - if (!host) panic ("Cannot register PLUTO host\n"); + if(!host) + { + kfree(ages); + continue; + } nplutos++; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c --- v2.4.0-test10/linux/drivers/scsi/ppa.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/ppa.c Sat Nov 11 19:01:11 2000 @@ -194,6 +194,8 @@ host->can_queue = PPA_CAN_QUEUE; host->sg_tablesize = ppa_sg; hreg = scsi_register(host, 0); + if(hreg == NULL) + continue; hreg->io_port = pb->base; hreg->n_io_port = ports; hreg->dma_channel = -1; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/psi240i.c linux/drivers/scsi/psi240i.c --- v2.4.0-test10/linux/drivers/scsi/psi240i.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/psi240i.c Sat Nov 11 19:01:11 2000 @@ -597,6 +597,8 @@ continue; pshost = scsi_register (tpnt, sizeof(ADAPTER240I)); + if(pshost == NULL) + continue; save_flags (flags); cli (); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/scsi_debug.c linux/drivers/scsi/scsi_debug.c --- v2.4.0-test10/linux/drivers/scsi/scsi_debug.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/scsi_debug.c Sat Nov 11 19:01:11 2000 @@ -554,9 +554,21 @@ printk("Allocating host dev\n"); sdev = scsi_get_host_dev(shpnt); + if(sdev==NULL) + { + printk("Out of memory.\n"); + return; + } + printk("Got %p. Allocating command block\n", sdev); scp = scsi_allocate_request(sdev); printk("Got %p\n", scp); + + if(scp==NULL) + { + printk("Out of memory.\n"); + goto bail; + } scp->sr_cmd_len = 6; scp->sr_use_sg = 0; @@ -567,7 +579,8 @@ printk("Releasing command\n"); scsi_release_request(scp); - printk("Freeing device\n"); +bail: + printk("Freeing device\n"); scsi_free_host_dev(sdev); } @@ -762,6 +775,8 @@ static Scsi_Host_Template driver_copy = SCSI_DEBUG; void *rtn; rtn = kmalloc(sizeof(driver_copy), GFP_ATOMIC); + if(rtn==NULL) + return NULL; memcpy(rtn, (void *) &driver_copy, sizeof(driver_copy)); return rtn; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c --- v2.4.0-test10/linux/drivers/scsi/scsi_error.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/scsi_error.c Wed Nov 8 17:09:50 2000 @@ -1861,9 +1861,6 @@ * Flush resources */ - exit_files(current); - current->files = init_task.files; - atomic_inc(¤t->files->count); daemonize(); /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- v2.4.0-test10/linux/drivers/scsi/scsi_ioctl.c Mon Aug 21 09:20:16 2000 +++ linux/drivers/scsi/scsi_ioctl.c Thu Nov 16 12:51:28 2000 @@ -1,3 +1,9 @@ +/* + * Changes: + * Arnaldo Carvalho de Melo 08/23/2000 + * - get rid of some verify_areas and use __copy*user and __get/put_user + * for the ones that remain + */ #define __NO_VERSION__ #include @@ -39,16 +45,14 @@ static int ioctl_probe(struct Scsi_Host *host, void *buffer) { - int temp, result; unsigned int len, slen; const char *string; + int temp = host->hostt->present; - if ((temp = host->hostt->present) && buffer) { - result = verify_area(VERIFY_READ, buffer, sizeof(long)); - if (result) - return result; + if (temp && buffer) { + if (get_user(len, (unsigned int *) buffer)) + return -EFAULT; - get_user(len, (unsigned int *) buffer); if (host->hostt->info) string = host->hostt->info(host); else @@ -57,11 +61,8 @@ slen = strlen(string); if (len > slen) len = slen + 1; - result = verify_area(VERIFY_WRITE, buffer, len); - if (result) - return result; - - copy_to_user(buffer, string, len); + if (copy_to_user(buffer, string, len)) + return -EFAULT; } } return temp; @@ -202,12 +203,11 @@ /* * Verify that we can read at least this much. */ - result = verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command)); - if (result) - return result; + if (verify_area(VERIFY_READ, sic, sizeof(Scsi_Ioctl_Command))) + return -EFAULT; - get_user(inlen, &sic->inlen); - get_user(outlen, &sic->outlen); + __get_user(inlen, &sic->inlen); + __get_user(outlen, &sic->outlen); /* * We do not transfer more than MAX_BUF with this interface. @@ -220,7 +220,7 @@ return -EINVAL; cmd_in = sic->data; - get_user(opcode, cmd_in); + __get_user(opcode, cmd_in); needed = buf_needed = (inlen > outlen ? inlen : outlen); if (buf_needed) { @@ -252,16 +252,15 @@ */ cmdlen = COMMAND_SIZE(opcode); - result = verify_area(VERIFY_READ, cmd_in, cmdlen + inlen); - if (result) - return result; + if (verify_area(VERIFY_READ, cmd_in, cmdlen + inlen)) + return -EFAULT; - copy_from_user(cmd, cmd_in, cmdlen); + __copy_from_user(cmd, cmd_in, cmdlen); /* * Obtain the data to be sent to the device (if any). */ - copy_from_user(buf, cmd_in + cmdlen, inlen); + __copy_from_user(buf, cmd_in + cmdlen, inlen); /* * Set the lun field to the correct value. @@ -314,18 +313,13 @@ int sb_len = sizeof(SRpnt->sr_sense_buffer); sb_len = (sb_len > OMAX_SB_LEN) ? OMAX_SB_LEN : sb_len; - result = verify_area(VERIFY_WRITE, cmd_in, sb_len); - if (result) - return result; - copy_to_user(cmd_in, SRpnt->sr_sense_buffer, sb_len); - } else { - result = verify_area(VERIFY_WRITE, cmd_in, outlen); - if (result) - return result; - copy_to_user(cmd_in, buf, outlen); - } - result = SRpnt->sr_result; + if (copy_to_user(cmd_in, SRpnt->sr_sense_buffer, sb_len)) + return -EFAULT; + } else + if (copy_to_user(cmd_in, buf, outlen)) + return -EFAULT; + result = SRpnt->sr_result; SDpnt = SRpnt->sr_device; scsi_release_request(SRpnt); @@ -361,7 +355,6 @@ */ int scsi_ioctl(Scsi_Device * dev, int cmd, void *arg) { - int result; char scsi_cmd[MAX_COMMAND_SIZE]; /* No idea how this happens.... */ @@ -379,23 +372,18 @@ } switch (cmd) { case SCSI_IOCTL_GET_IDLUN: - result = verify_area(VERIFY_WRITE, arg, sizeof(Scsi_Idlun)); - if (result) - return result; + if (verify_area(VERIFY_WRITE, arg, sizeof(Scsi_Idlun))) + return -EFAULT; - put_user(dev->id + __put_user(dev->id + (dev->lun << 8) + (dev->channel << 16) + ((dev->host->host_no & 0xff) << 24), &((Scsi_Idlun *) arg)->dev_id); - put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id); + __put_user(dev->host->unique_id, &((Scsi_Idlun *) arg)->host_unique_id); return 0; case SCSI_IOCTL_GET_BUS_NUMBER: - result = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int)); - if (result) - return result; - put_user(dev->host->host_no, (int *) arg); - return 0; + return put_user(dev->host->host_no, (int *) arg); case SCSI_IOCTL_TAGGED_ENABLE: if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c --- v2.4.0-test10/linux/drivers/scsi/scsi_obsolete.c Wed Apr 12 09:47:26 2000 +++ linux/drivers/scsi/scsi_obsolete.c Thu Nov 9 15:57:41 2000 @@ -370,7 +370,7 @@ * crashing, all scsi_done() calls during sync resets are ignored. */ printk("scsi%d: device driver called scsi_done() " - "for a syncronous reset.\n", SCpnt->host->host_no); + "for a synchronous reset.\n", SCpnt->host->host_no); return; } if (SCpnt->flags & WAS_SENSE) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/seagate.c linux/drivers/scsi/seagate.c --- v2.4.0-test10/linux/drivers/scsi/seagate.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/seagate.c Sat Nov 11 19:01:11 2000 @@ -488,6 +488,9 @@ * loose our first interrupt. */ instance = scsi_register (tpnt, 0); + if(instance == NULL) + return 0; + hostno = instance->host_no; if (request_irq (irq, do_seagate_reconnect_intr, SA_INTERRUPT, (controller_type == SEAGATE) ? "seagate" : "tmc-8xx", NULL)) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/sgiwd93.c linux/drivers/scsi/sgiwd93.c --- v2.4.0-test10/linux/drivers/scsi/sgiwd93.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/sgiwd93.c Sat Nov 11 19:01:11 2000 @@ -275,6 +275,8 @@ SGIblows->proc_name = "SGIWD93"; sgiwd93_host = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); + if(sgiwd93_host == NULL) + return 0; sgiwd93_host->base = (unsigned long) hregs; sgiwd93_host->irq = SGI_WD93_0_IRQ; @@ -294,22 +296,25 @@ /* set up second controller on the Indigo2 */ if(!sgi_guiness) { sgiwd93_host1 = scsi_register(SGIblows, sizeof(struct WD33C93_hostdata)); - sgiwd93_host1->base = (unsigned long) hregs1; - sgiwd93_host1->irq = SGI_WD93_1_IRQ; - - buf = (uchar *) get_free_page(GFP_KERNEL); - init_hpc_chain(buf); - dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); - /* HPC_SCSI_REG1 | 0x03 | KSEG1 */ - wd33c93_init(sgiwd93_host1, (wd33c93_regs *) 0xbfbc8003, - dma_setup, dma_stop, WD33C93_FS_16_20); - - hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata; - hdata1->no_sync = 0; - hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); - dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); - - request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1); + if(sgiwd93_host1 != NULL) + { + sgiwd93_host1->base = (unsigned long) hregs1; + sgiwd93_host1->irq = SGI_WD93_1_IRQ; + + buf = (uchar *) get_free_page(GFP_KERNEL); + init_hpc_chain(buf); + dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); + /* HPC_SCSI_REG1 | 0x03 | KSEG1 */ + wd33c93_init(sgiwd93_host1, (wd33c93_regs *) 0xbfbc8003, + dma_setup, dma_stop, WD33C93_FS_16_20); + + hdata1 = (struct WD33C93_hostdata *)sgiwd93_host1->hostdata; + hdata1->no_sync = 0; + hdata1->dma_bounce_buffer = (uchar *) (KSEG1ADDR(buf)); + dma_cache_wback_inv((unsigned long) buf, PAGE_SIZE); + + request_irq(SGI_WD93_1_IRQ, sgiwd93_intr, 0, "SGI WD93", (void *) sgiwd93_host1); + } } called = 1; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/sr_ioctl.c linux/drivers/scsi/sr_ioctl.c --- v2.4.0-test10/linux/drivers/scsi/sr_ioctl.c Tue Sep 5 13:46:15 2000 +++ linux/drivers/scsi/sr_ioctl.c Thu Nov 9 15:59:14 2000 @@ -274,7 +274,7 @@ /* ----------------------------------------------------------------------- */ /* this is called by the generic cdrom driver. arg is a _kernel_ pointer, */ -/* becauce the generic cdrom driver does the user access stuff for us. */ +/* because the generic cdrom driver does the user access stuff for us. */ /* only cdromreadtochdr and cdromreadtocentry are left - for use with the */ /* sr_disk_status interface for the generic cdrom driver. */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/st.c linux/drivers/scsi/st.c --- v2.4.0-test10/linux/drivers/scsi/st.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/st.c Tue Nov 14 13:16:37 2000 @@ -12,7 +12,7 @@ Copyright 1992 - 2000 Kai Makisara email Kai.Makisara@metla.fi - Last modified: Tue Aug 15 16:56:35 2000 by makisara@kai.makisara.local + Last modified: Mon Nov 13 21:01:09 2000 by makisara@kai.makisara.local Some small formal changes - aeb, 950809 Last modified: 18-JAN-1998 Richard Gooch Devfs support @@ -976,7 +976,7 @@ ((SRpnt->sr_sense_buffer[0] & 0x80) != 0 && (SRpnt->sr_sense_buffer[3] | SRpnt->sr_sense_buffer[4] | SRpnt->sr_sense_buffer[5] | - SRpnt->sr_sense_buffer[6]) == 0))) { + SRpnt->sr_sense_buffer[6]) != 0))) { /* Filter out successful write at EOM */ scsi_release_request(SRpnt); SRpnt = NULL; @@ -2495,10 +2495,8 @@ STps->drv_block = 0; STps->eof = ST_NOEOF; } else if ((cmd_in == MTBSF) || (cmd_in == MTBSFM)) { - if (fileno >= 0) + if (STps->drv_file >= 0) STps->drv_file = fileno + undone; - else - STps->drv_file = fileno; STps->drv_block = 0; STps->eof = ST_NOEOF; } else if (cmd_in == MTFSR) { @@ -2519,10 +2517,8 @@ STps->drv_file--; STps->drv_block = (-1); } else { - if (blkno >= 0) + if (STps->drv_block >= 0) STps->drv_block = blkno + undone; - else - STps->drv_block = (-1); } STps->eof = ST_NOEOF; } else if (cmd_in == MTEOM) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/sun3_scsi.c linux/drivers/scsi/sun3_scsi.c --- v2.4.0-test10/linux/drivers/scsi/sun3_scsi.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/sun3_scsi.c Sat Nov 11 19:01:11 2000 @@ -250,6 +250,9 @@ #endif instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + return 0; + default_instance = instance; instance->io_port = (unsigned long) ioaddr; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/sym53c416.c linux/drivers/scsi/sym53c416.c --- v2.4.0-test10/linux/drivers/scsi/sym53c416.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/sym53c416.c Sat Nov 11 19:01:11 2000 @@ -677,6 +677,8 @@ if(hosts[i].irq && !check_region(hosts[i].base, IO_RANGE)) { shpnt = scsi_register(tpnt, 0); + if(shpnt==NULL) + continue; save_flags(flags); cli(); /* Request for specified IRQ */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/t128.c linux/drivers/scsi/t128.c --- v2.4.0-test10/linux/drivers/scsi/t128.c Sun Oct 8 10:50:25 2000 +++ linux/drivers/scsi/t128.c Sat Nov 11 19:01:11 2000 @@ -234,6 +234,9 @@ break; instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); + if(instance == NULL) + break; + instance->base = base; NCR5380_init(instance, 0); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c --- v2.4.0-test10/linux/drivers/scsi/wd7000.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/scsi/wd7000.c Sat Nov 11 19:01:11 2000 @@ -1626,6 +1626,8 @@ * array hostdata. */ sh = scsi_register (tpnt, sizeof (Adapter)); + if(sh==NULL) + continue; host = (Adapter *) sh->hostdata; #ifdef WD7000_DEBUG diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/724hwmcode.h linux/drivers/sound/724hwmcode.h --- v2.4.0-test10/linux/drivers/sound/724hwmcode.h Tue Jun 20 07:52:36 2000 +++ linux/drivers/sound/724hwmcode.h Sat Nov 11 18:33:13 2000 @@ -9,7 +9,7 @@ #ifndef _HWMCODE_ #define _HWMCODE_ -static unsigned long int DspInst[] = { +static unsigned long int DspInst[] __initdata = { 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, @@ -20,7 +20,7 @@ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; -static unsigned long int CntrlInst[] = { +static unsigned long int CntrlInst[] __initdata = { 0x000007, 0x240007, 0x0C0007, 0x1C0007, 0x060007, 0x700002, 0x000020, 0x030040, 0x007104, 0x004286, 0x030040, 0x000F0D, @@ -799,7 +799,7 @@ // 04/09?@creat // 04/12 stop nise fix // 06/21?@WorkingOff timming -static unsigned long int CntrlInst1E[] = { +static unsigned long int CntrlInst1E[] __initdata = { 0x000007, 0x240007, 0x0C0007, 0x1C0007, 0x060007, 0x700002, 0x000020, 0x030040, 0x007104, 0x004286, 0x030040, 0x000F0D, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/aci.c linux/drivers/sound/aci.c --- v2.4.0-test10/linux/drivers/sound/aci.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/aci.c Thu Nov 16 12:51:28 2000 @@ -441,7 +441,7 @@ } if (((cmd >> 8) & 0xff) == 'M') { - if (cmd & IOC_IN) + if (cmd & SIOC_IN) /* read and write */ switch (cmd & 0xff) { case SOUND_MIXER_VOLUME: diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c --- v2.4.0-test10/linux/drivers/sound/ad1816.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/ad1816.c Thu Nov 16 12:51:28 2000 @@ -916,7 +916,7 @@ if (((cmd >> 8) & 0xff) == 'M') { /* set ioctl */ - if (_IOC_DIR (cmd) & _IOC_WRITE) { + if (_SIOC_DIR (cmd) & _SIOC_WRITE) { switch (cmd & 0xff){ case SOUND_MIXER_RECSRC: diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/awe_wave.c linux/drivers/sound/awe_wave.c --- v2.4.0-test10/linux/drivers/sound/awe_wave.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/awe_wave.c Thu Nov 16 12:51:28 2000 @@ -4321,7 +4321,7 @@ level = ((level & 0xff) + (level >> 8)) / 2; DEBUG(0,printk("AWEMix: cmd=%x val=%d\n", cmd & 0xff, level)); - if (_SIOC_DIR(cmd) & _IOC_WRITE) { + if (_SIOC_DIR(cmd) & _SIOC_WRITE) { switch (cmd & 0xff) { case SOUND_MIXER_BASS: value = level * 12 / 100; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c --- v2.4.0-test10/linux/drivers/sound/cmpci.c Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/cmpci.c Thu Nov 16 12:51:28 2000 @@ -983,9 +983,9 @@ } if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); - if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { + if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ return put_user(mixer_recmask(s), (int *)arg); @@ -1033,7 +1033,7 @@ #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ } } - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { @@ -1197,9 +1197,9 @@ if (s->dma_dac.mapped || !s->dma_dac.ready) return 0; - current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac.wait, &wait); for (;;) { + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); @@ -1839,6 +1839,7 @@ ret = 0; add_wait_queue(&s->midi.iwait, &wait); while (count > 0) { + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); ptr = s->midi.ird; cnt = MIDIINBUF - ptr; @@ -1854,7 +1855,6 @@ ret = -EAGAIN; break; } - __set_current_state(TASK_INTERRUPTIBLE); schedule(); if (signal_pending(current)) { @@ -1903,6 +1903,7 @@ ret = 0; add_wait_queue(&s->midi.owait, &wait); while (count > 0) { + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); ptr = s->midi.owr; cnt = MIDIOUTBUF - ptr; @@ -1919,7 +1920,6 @@ ret = -EAGAIN; break; } - __set_current_state(TASK_INTERRUPTIBLE); schedule(); if (signal_pending(current)) { if (!ret) @@ -2041,9 +2041,9 @@ lock_kernel(); if (file->f_mode & FMODE_WRITE) { - __set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(&s->midi.owait, &wait); for (;;) { + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->midi.ocnt; spin_unlock_irqrestore(&s->lock, flags); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c --- v2.4.0-test10/linux/drivers/sound/cs4232.c Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/cs4232.c Sat Nov 11 18:33:13 2000 @@ -40,6 +40,8 @@ * Christoph Hellwig Adapted to module_init/module_exit, * simple cleanups * Arnaldo C. de Melo got rid of attach_uart401 + * Bartlomiej Zolnierkiewicz + * Added some __init/__initdata/__exit */ #include @@ -67,7 +69,7 @@ static int synth_base = 0, synth_irq = 0; static int mpu_detected = 0; -int probe_cs4232_mpu(struct address_info *hw_config) +int __init probe_cs4232_mpu(struct address_info *hw_config) { /* * Just write down the config values. @@ -79,7 +81,7 @@ return 1; } -static unsigned char crystal_key[] = /* A 32 byte magic key sequence */ +static unsigned char crystal_key[] __initdata = /* A 32 byte magic key sequence */ { 0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc, 0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2, @@ -93,7 +95,7 @@ schedule_timeout(howlong); } -int probe_cs4232(struct address_info *hw_config) +int __init probe_cs4232(struct address_info *hw_config) { int i, n; int base = hw_config->io_base, irq = hw_config->irq; @@ -209,7 +211,7 @@ return 0; } -void attach_cs4232(struct address_info *hw_config) +void __init attach_cs4232(struct address_info *hw_config) { int base = hw_config->io_base, irq = hw_config->irq, @@ -268,7 +270,7 @@ } } -void unload_cs4232(struct address_info *hw_config) +void __exit unload_cs4232(struct address_info *hw_config) { int base = hw_config->io_base, irq = hw_config->irq; int dma1 = hw_config->dma, dma2 = hw_config->dma2; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/cs4281.c linux/drivers/sound/cs4281.c --- v2.4.0-test10/linux/drivers/sound/cs4281.c Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/cs4281.c Thu Nov 16 12:51:28 2000 @@ -30,11 +30,22 @@ // /dev/mixer standard /dev/mixer device, (mostly) OSS compatible // /dev/midi simple MIDI UART interface, no ioctl // +// Modification History +// 08/20/00 trw - silence and no stopping DAC until release +// 08/23/00 trw - added CS_DBG statements, fix interrupt hang issue on DAC stop. +// 09/18/00 trw - added 16bit only record with conversion +// 09/24/00 trw - added Enhanced Full duplex (separate simultaneous +// capture/playback rates) +// 10/03/00 trw - fixed mmap (fixed GRECORD and the XMMS mmap test plugin +// libOSSm.so) +// 10/11/00 trw - modified for 2.4.0-test9 kernel enhancements (NR_MAP removal) +// 11/03/00 trw - fixed interrupt loss/stutter, added debug. +// 11/10/00 bkz - added __devinit to cs4281_hw_init() // -// - // ***************************************************************************** +#include +#include #include #include #include @@ -50,9 +61,11 @@ #include #include #include +#include +#include #include #include -#include +//#include #include "dm.h" #include "cs4281_hwdefs.h" @@ -71,10 +84,10 @@ #define CS4281_MAGIC ((PCI_DEVICE_ID_CRYSTAL_CS4281<<16) | PCI_VENDOR_ID_CIRRUS) -#define CSDEBUG 1 -// // Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG // +#define CSDEBUG_INTERFACE 1 +#define CSDEBUG 1 // // CSDEBUG is usual mode is set to 1, then use the // cs_debuglevel and cs_debugmask to turn on or off debugging. @@ -82,36 +95,39 @@ // that should be printed on any released driver. // #if CSDEBUG -extern unsigned cs_debugmask; -extern unsigned cs_debuglevel; -#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask)) {x;} +extern unsigned long cs_debugmask; +extern unsigned long cs_debuglevel; +#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask) ) {x;} #else -#define CS_DBGOUT(mask,level,x) +#define CS_DBGOUT(mask,level,x) #endif // // cs_debugmask areas // -#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_TMP 0x10000000 // tmp debug mask bit +#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 -unsigned cs_debuglevel=1; // levels range from 1-9 -unsigned cs_debugmask=CS_INIT | CS_ERROR; // use CS_DBGOUT with various mask values +#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 #if MODULE MODULE_PARM(cs_debuglevel, "i"); MODULE_PARM(cs_debugmask, "i"); #endif +#endif // MIDI buffer sizes #define MIDIINBUF 500 @@ -127,14 +143,17 @@ ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) #define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start) -#define CS4281_MAJOR_VERSION 0 -#define CS4281_MINOR_VERSION 4 +#define CS4281_MAJOR_VERSION 1 +#define CS4281_MINOR_VERSION 1 #ifdef __ia64__ -#define CS4281_ARCH 64 //architecture key +#define CS4281_ARCH 64 //architecture key #else -#define CS4281_ARCH 32 //architecture key +#define CS4281_ARCH 32 //architecture key #endif +#define CS_TYPE_ADC 0 +#define CS_TYPE_DAC 1 + struct cs4281_state { // magic unsigned int magic; @@ -152,9 +171,8 @@ // hardware resources unsigned int pBA0phys, pBA1phys; - char *pBA0, *pBA1; + char *pBA0, *pBA1; unsigned int irq; - int endofbuffer; // mixer registers struct { @@ -164,38 +182,50 @@ unsigned short micpreamp; } mix; - // wave stuff // Note that play & record formats must be the same *wb. - unsigned fmt; - unsigned channels; - unsigned rate; - unsigned char clkdiv; + // wave stuff + struct properties { + unsigned fmt; + unsigned fmt_original; // original requested format + unsigned channels; + unsigned rate; + unsigned char clkdiv; + } prop_dac, prop_adc; + unsigned conversion:1; // conversion from 16 to 8 bit in progress + void *tmpbuff; // tmp buffer for sample conversions unsigned ena; - spinlock_t lock; struct semaphore open_sem; + struct semaphore open_sem_adc; + struct semaphore open_sem_dac; mode_t open_mode; wait_queue_head_t open_wait; + wait_queue_head_t open_wait_adc; + wait_queue_head_t open_wait_dac; + dma_addr_t dmaaddr_tmpbuff; + unsigned buforder_tmpbuff; // Log base 2 of 'rawbuf' size in bytes.. struct dmabuf { - void *rawbuf; // Physical address of - dma_addr_t dmaaddr; - unsigned buforder; // Log base 2 of 'rawbuf' size in bytes.. - unsigned numfrag; // # of 'fragments' in the buffer. - unsigned fragshift; // Log base 2 of fragment size. + void *rawbuf; // Physical address of + dma_addr_t dmaaddr; + unsigned buforder; // Log base 2 of 'rawbuf' size in bytes.. + unsigned numfrag; // # of 'fragments' in the buffer. + unsigned fragshift; // Log base 2 of fragment size. unsigned hwptr, swptr; - unsigned total_bytes; // # bytes process since open. - unsigned blocks; // last returned blocks value GETOPTR + unsigned total_bytes; // # bytes process since open. + unsigned blocks; // last returned blocks value GETOPTR + unsigned wakeup; // interrupt occurred on block int count; - unsigned error; // over/underrun + unsigned error; // over/underrun wait_queue_head_t wait; // redundant, but makes calculations easier - unsigned fragsize; // 2**fragshift.. - unsigned dmasize; // 2**buforder. + unsigned fragsize; // 2**fragshift.. + unsigned dmasize; // 2**buforder. unsigned fragsamples; // OSS stuff - unsigned mapped:1; // Buffer mapped in cs4281_mmap()? - unsigned ready:1; // prog_dmabuf_dac()/adc() successful? + unsigned mapped:1; // Buffer mapped in cs4281_mmap()? + unsigned ready:1; // prog_dmabuf_dac()/adc() successful? unsigned endcleared:1; + unsigned type:1; // adc or dac buffer (CS_TYPE_XXX) unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; @@ -214,11 +244,250 @@ }; +#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) -struct cs4281_state *devs = NULL; +void printioctl(unsigned int x) +{ + unsigned int i; + unsigned char vidx; + // 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:\n")); + break; + case SOUND_MIXER_CS_GETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_GETDBGLEVEL:\n")); + break; + case SOUND_MIXER_CS_SETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_SETDBGMASK:\n")); + break; + case SOUND_MIXER_CS_SETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CS_SETDBGLEVEL:\n")); + break; + case OSS_GETVERSION: + CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION:\n")); + break; + case SNDCTL_DSP_SYNC: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC:\n")); + break; + case SNDCTL_DSP_SETDUPLEX: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX:\n")); + break; + case SNDCTL_DSP_GETCAPS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS:\n")); + break; + case SNDCTL_DSP_RESET: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET:\n")); + break; + case SNDCTL_DSP_SPEED: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED:\n")); + break; + case SNDCTL_DSP_STEREO: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO:\n")); + break; + case SNDCTL_DSP_CHANNELS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS:\n")); + break; + case SNDCTL_DSP_GETFMTS: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS:\n")); + break; + case SNDCTL_DSP_SETFMT: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT:\n")); + break; + case SNDCTL_DSP_POST: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST:\n")); + break; + case SNDCTL_DSP_GETTRIGGER: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER:\n")); + break; + case SNDCTL_DSP_SETTRIGGER: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER:\n")); + break; + case SNDCTL_DSP_GETOSPACE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE:\n")); + break; + case SNDCTL_DSP_GETISPACE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE:\n")); + break; + case SNDCTL_DSP_NONBLOCK: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK:\n")); + break; + case SNDCTL_DSP_GETODELAY: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY:\n")); + break; + case SNDCTL_DSP_GETIPTR: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR:\n")); + break; + case SNDCTL_DSP_GETOPTR: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR:\n")); + break; + case SNDCTL_DSP_GETBLKSIZE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE:\n")); + break; + case SNDCTL_DSP_SETFRAGMENT: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_SETFRAGMENT:\n")); + break; + case SNDCTL_DSP_SUBDIVIDE: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE:\n")); + break; + case SOUND_PCM_READ_RATE: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE:\n")); + break; + case SOUND_PCM_READ_CHANNELS: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_PCM_READ_CHANNELS:\n")); + break; + case SOUND_PCM_READ_BITS: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n")); + break; + case SOUND_PCM_WRITE_FILTER: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_PCM_WRITE_FILTER:\n")); + break; + case SNDCTL_DSP_SETSYNCRO: + CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n")); + break; + case SOUND_PCM_READ_FILTER: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n")); + break; + case SNDCTL_DSP_CS_GETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_GETDBGMASK:\n")); + break; + case SNDCTL_DSP_CS_GETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_GETDBGLEVEL:\n")); + break; + case SNDCTL_DSP_CS_SETDBGMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_SETDBGMASK:\n")); + break; + case SNDCTL_DSP_CS_SETDBGLEVEL: + CS_DBGOUT(CS_IOCTL, 4, + printk("SNDCTL_DSP_CS_SETDBGLEVEL:\n")); + break; + + case SOUND_MIXER_PRIVATE1: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n")); + break; + case SOUND_MIXER_PRIVATE2: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n")); + break; + case SOUND_MIXER_PRIVATE3: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n")); + break; + case SOUND_MIXER_PRIVATE4: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n")); + break; + case SOUND_MIXER_PRIVATE5: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n")); + break; + case SOUND_MIXER_INFO: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n")); + break; + case SOUND_OLD_MIXER_INFO: + CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n")); + break; + + default: + switch (_IOC_NR(x)) { + case SOUND_MIXER_VOLUME: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_VOLUME:\n")); + break; + case SOUND_MIXER_SPEAKER: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_SPEAKER:\n")); + break; + case SOUND_MIXER_RECLEV: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_RECLEV:\n")); + break; + case SOUND_MIXER_MIC: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_MIC:\n")); + break; + case SOUND_MIXER_SYNTH: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_SYNTH:\n")); + break; + case SOUND_MIXER_RECSRC: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_RECSRC:\n")); + break; + case SOUND_MIXER_DEVMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_DEVMASK:\n")); + break; + case SOUND_MIXER_RECMASK: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_RECMASK:\n")); + break; + case SOUND_MIXER_STEREODEVS: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_STEREODEVS:\n")); + break; + case SOUND_MIXER_CAPS: + CS_DBGOUT(CS_IOCTL, 4, + printk("SOUND_MIXER_CAPS:\n")); + 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\n", + x, i)); + } else { + CS_DBGOUT(CS_IOCTL, 4, + printk + ("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n", + x, i)); + } + break; + } + } +} +#endif +static int prog_dmabuf_adc(struct cs4281_state *s); +static void prog_codec(struct cs4281_state *s, unsigned type); + +static struct cs4281_state *devs = NULL; // --------------------------------------------------------------------- // -// Hardware Interfaces For the CS4281 +// Hardware Interfaces For the CS4281 // @@ -227,18 +496,16 @@ //****************************************************************************** static void delayus(u32 delay) { - u32 j; - if(delay > 9999) - { - j = (delay * HZ)/1000000; /* calculate delay in jiffies */ - if(j<1) - j=1; /* minimum one jiffy. */ - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout(j); - } - else + u32 j; + if (delay > 9999) { + j = (delay * HZ) / 1000000; /* calculate delay in jiffies */ + if (j < 1) + j = 1; /* minimum one jiffy. */ + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(j); + } else udelay(delay); - return; + return; } @@ -254,14 +521,15 @@ // 5. if DCV not cleared, break and return error // 6. Read ACSTS = Status Register = 464h, check VSTS bit //**************************************************************************** -static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, u32 *value) +static int cs4281_read_ac97(struct cs4281_state *card, u32 offset, + u32 * value) { u32 count, status; // Make sure that there is not data sitting // around from a previous uncompleted access. // ACSDA = Status Data Register = 47Ch - status = readl(card->pBA0+BA0_ACSDA); + status = readl(card->pBA0 + BA0_ACSDA); // Setup the AC97 control registers on the CS4281 to send the // appropriate command to the AC97 to perform the read. @@ -274,51 +542,50 @@ // bit ESYN - ASYNC generation enabled // Get the actual AC97 register from the offset - writel(offset - BA0_AC97_RESET, card->pBA0+BA0_ACCAD); - writel(0, card->pBA0+BA0_ACCDA); - writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL); + writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD); + writel(0, card->pBA0 + BA0_ACCDA); + writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN, + card->pBA0 + BA0_ACCTL); - // Wait for the read to occur. - for(count = 0; count < 10; count++) - { + // Wait for the read to occur. + for (count = 0; count < 10; count++) { // First, we want to wait for a short time. udelay(25); // Now, check to see if the read has completed. // ACCTL = 460h, DCV should be reset by now and 460h = 17h - if( !(readl(card->pBA0+BA0_ACCTL) & ACCTL_DCV)) + if (!(readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV)) break; } - // Make sure the read completed. - if(readl(card->pBA0+BA0_ACCTL) & ACCTL_DCV) - return 1; + // Make sure the read completed. + if (readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV) + return 1; - // Wait for the valid status bit to go active. - for(count = 0; count < 10; count++) - { + // Wait for the valid status bit to go active. + for (count = 0; count < 10; count++) { // Read the AC97 status register. // ACSTS = Status Register = 464h - status = readl(card->pBA0+BA0_ACSTS); + status = readl(card->pBA0 + BA0_ACSTS); // See if we have valid status. // VSTS - Valid Status - if(status & ACSTS_VSTS) + if (status & ACSTS_VSTS) break; // Wait for a short while. udelay(25); } - // Make sure we got valid status. - if(!(status & ACSTS_VSTS)) + // Make sure we got valid status. + if (!(status & ACSTS_VSTS)) return 1; // Read the data returned from the AC97 register. // ACSDA = Status Data Register = 474h - *value = readl(card->pBA0+BA0_ACSDA); + *value = readl(card->pBA0 + BA0_ACSDA); // Success. - return(0); + return (0); } @@ -334,49 +601,51 @@ // 5. if DCV not cleared, break and return error // //**************************************************************************** -static int cs4281_write_ac97(struct cs4281_state *card, u32 offset, u32 value) +static int cs4281_write_ac97(struct cs4281_state *card, u32 offset, + u32 value) { u32 count, status; - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n")); + + // Setup the AC97 control registers on the CS4281 to send the + // appropriate command to the AC97 to perform the read. + // ACCAD = Command Address Register = 46Ch + // ACCDA = Command Data Register = 470h + // ACCTL = Control Register = 460h + // set DCV - will clear when process completed + // reset CRW - Write command + // set VFRM - valid frame enabled + // set ESYN - ASYNC generation enabled + // set RSTN - ARST# inactive, AC97 codec not reset + + // Get the actual AC97 register from the offset - // Setup the AC97 control registers on the CS4281 to send the - // appropriate command to the AC97 to perform the read. - // ACCAD = Command Address Register = 46Ch - // ACCDA = Command Data Register = 470h - // ACCTL = Control Register = 460h - // set DCV - will clear when process completed - // reset CRW - Write command - // set VFRM - valid frame enabled - // set ESYN - ASYNC generation enabled - // set RSTN - ARST# inactive, AC97 codec not reset - - // Get the actual AC97 register from the offset - - writel(offset - BA0_AC97_RESET, card->pBA0+BA0_ACCAD); - writel(value, card->pBA0+BA0_ACCDA); - writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL); + writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD); + writel(value, card->pBA0 + BA0_ACCDA); + writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN, + card->pBA0 + BA0_ACCTL); - // Wait for the write to occur. - for(count = 0; count < 10; count++) - { + // Wait for the write to occur. + for (count = 0; count < 10; count++) { // First, we want to wait for a short time. udelay(25); // Now, check to see if the write has completed. // ACCTL = 460h, DCV should be reset by now and 460h = 07h - status = readl(card->pBA0+BA0_ACCTL); - if(!(status & ACCTL_DCV)) + status = readl(card->pBA0 + BA0_ACCTL); + if (!(status & ACCTL_DCV)) break; } // Make sure the write completed. - if(status & ACCTL_DCV) - { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO - "cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n") ); + if (status & ACCTL_DCV) { + CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO + "cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n")); return 1; } - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n")); // Success. return 0; } @@ -385,72 +654,71 @@ //****************************************************************************** // "Init4281()" -- Bring up the part. //****************************************************************************** -static int cs4281_hw_init(struct cs4281_state *card) +static int __devinit cs4281_hw_init(struct cs4281_state *card) { u32 ac97_slotid; u32 temp1, temp2; - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n")); //***************************************7 // Set up the Sound System Configuration //*************************************** - // Set the 'Configuration Write Protect' register - // to 4281h. Allows vendor-defined configuration - // space between 0e4h and 0ffh to be written. + // Set the 'Configuration Write Protect' register + // to 4281h. Allows vendor-defined configuration + // space between 0e4h and 0ffh to be written. - writel(0x4281, card->pBA0+BA0_CWPR); // (3e0h) + writel(0x4281, card->pBA0 + BA0_CWPR); // (3e0h) - // (0), Blast the clock control register to zero so that the - // PLL starts out in a known state, and blast the master serial - // port control register to zero so that the serial ports also - // start out in a known state. + // (0), Blast the clock control register to zero so that the + // PLL starts out in a known state, and blast the master serial + // port control register to zero so that the serial ports also + // start out in a known state. - writel(0, card->pBA0+BA0_CLKCR1); // (400h) - writel(0, card->pBA0+BA0_SERMC); // (420h) + writel(0, card->pBA0 + BA0_CLKCR1); // (400h) + writel(0, card->pBA0 + BA0_SERMC); // (420h) - // (1), Make ESYN go to zero to turn off - // the Sync pulse on the AC97 link. + // (1), Make ESYN go to zero to turn off + // the Sync pulse on the AC97 link. - writel(0, card->pBA0+BA0_ACCTL); + writel(0, card->pBA0 + BA0_ACCTL); udelay(50); - // (2) Drive the ARST# pin low for a minimum of 1uS (as defined in - // the AC97 spec) and then drive it high. This is done for non - // AC97 modes since there might be logic external to the CS461x - // that uses the ARST# line for a reset. + // (2) Drive the ARST# pin low for a minimum of 1uS (as defined in + // the AC97 spec) and then drive it high. This is done for non + // AC97 modes since there might be logic external to the CS461x + // that uses the ARST# line for a reset. - writel(0, card->pBA0+BA0_SPMC); // (3ech) + writel(0, card->pBA0 + BA0_SPMC); // (3ech) udelay(100); - writel(SPMC_RSTN, card->pBA0+BA0_SPMC); - delayus(50000); // Wait 50 ms for ABITCLK to become stable. + writel(SPMC_RSTN, card->pBA0 + BA0_SPMC); + delayus(50000); // Wait 50 ms for ABITCLK to become stable. // (3) Turn on the Sound System Clocks. - writel(CLKCR1_PLLP, card->pBA0+BA0_CLKCR1); // (400h) - delayus(50000); // Wait for the PLL to stabilize. + writel(CLKCR1_PLLP, card->pBA0 + BA0_CLKCR1); // (400h) + delayus(50000); // Wait for the PLL to stabilize. // Turn on clocking of the core (CLKCR1(400h) = 0x00000030) - writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0+BA0_CLKCR1); + writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0 + BA0_CLKCR1); // (4) Power on everything for now.. - writel(0x7E, card->pBA0 + BA0_SSPM); // (740h) + writel(0x7E, card->pBA0 + BA0_SSPM); // (740h) // (5) Wait for clock stabilization. - for(temp1=0; temp1<1000; temp1++) - { + for (temp1 = 0; temp1 < 1000; temp1++) { udelay(1000); - if(readl(card->pBA0+BA0_CLKCR1) & CLKCR1_DLLRDY) + if (readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY) break; } - if(!(readl(card->pBA0+BA0_CLKCR1) & CLKCR1_DLLRDY)) - { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR "cs4281: DLLRDY failed!\n") ); + if (!(readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)) { + CS_DBGOUT(CS_ERROR, 1, + printk(KERN_ERR "cs4281: DLLRDY failed!\n")); return -EIO; } - // (6) Enable ASYNC generation. - writel(ACCTL_ESYN, card->pBA0+BA0_ACCTL); // (460h) + writel(ACCTL_ESYN, card->pBA0 + BA0_ACCTL); // (460h) // Now wait 'for a short while' to allow the AC97 // part to start generating bit clock. (so we don't @@ -459,99 +727,95 @@ // Set the serial port timing configuration, so that the // clock control circuit gets its clock from the right place. - writel(SERMC_PTC_AC97, card->pBA0+BA0_SERMC); // (420h)=2. + writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC); // (420h)=2. // (7) Wait for the codec ready signal from the AC97 codec. - for(temp1=0; temp1<1000; temp1++) - { + for (temp1 = 0; temp1 < 1000; temp1++) { // Delay a mil to let things settle out and // to prevent retrying the read too quickly. udelay(1000); - if( readl(card->pBA0+BA0_ACSTS) & ACSTS_CRDY ) // If ready, (464h) - break; // exit the 'for' loop. + if (readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY) // If ready, (464h) + break; // exit the 'for' loop. } - if( !(readl(card->pBA0+BA0_ACSTS) & ACSTS_CRDY) ) // If never came ready, - { - CS_DBGOUT(CS_FUNCTION, 2, - printk(KERN_ERR "cs4281: ACSTS never came ready!\n") ); - return -EIO; // exit initialization. - } - - // (8) Assert the 'valid frame' signal so we can - // begin sending commands to the AC97 codec. - writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0+BA0_ACCTL); // (460h) - - // (9), Wait until CODEC calibration is finished. - // Print an error message if it doesn't. - for(temp1 = 0; temp1 < 1000; temp1++) + if (!(readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY)) // If never came ready, { + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_ERR + "cs4281: ACSTS never came ready!\n")); + return -EIO; // exit initialization. + } + // (8) Assert the 'valid frame' signal so we can + // begin sending commands to the AC97 codec. + writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0 + BA0_ACCTL); // (460h) + + // (9), Wait until CODEC calibration is finished. + // Print an error message if it doesn't. + for (temp1 = 0; temp1 < 1000; temp1++) { delayus(10000); // Read the AC97 Powerdown Control/Status Register. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp2); - if( (temp2 & 0x0000000F) == 0x0000000F ) + if ((temp2 & 0x0000000F) == 0x0000000F) break; } - if ( (temp2 & 0x0000000F) != 0x0000000F ) - { - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR - "cs4281: Codec failed to calibrate. Status = %.8x.\n", temp2) ); + if ((temp2 & 0x0000000F) != 0x0000000F) { + CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR + "cs4281: Codec failed to calibrate. Status = %.8x.\n", + temp2)); return -EIO; } - - // (10), Set the serial port timing configuration, so that the - // clock control circuit gets its clock from the right place. - writel(SERMC_PTC_AC97, card->pBA0+BA0_SERMC); // (420h)=2. + // (10), Set the serial port timing configuration, so that the + // clock control circuit gets its clock from the right place. + writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC); // (420h)=2. - // (11) Wait until we've sampled input slots 3 & 4 as valid, meaning - // that the codec is pumping ADC data across the AC link. - for(temp1=0; temp1<1000; temp1++) - { + // (11) Wait until we've sampled input slots 3 & 4 as valid, meaning + // that the codec is pumping ADC data across the AC link. + for (temp1 = 0; temp1 < 1000; temp1++) { // Delay a mil to let things settle out and // to prevent retrying the read too quickly. - delayus(1000); //(test) + delayus(1000); //(test) // Read the input slot valid register; See // if input slots 3 and 4 are valid yet. - if( (readl(card->pBA0+BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ) - == (ACISV_ISV3 | ACISV_ISV4)) - break; // Exit the 'for' if slots are valid. - } - // If we never got valid data, exit initialization. - if( (readl(card->pBA0+BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4) ) - != (ACISV_ISV3 | ACISV_ISV4)) - { - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR "cs4281: Never got valid data!\n")); - return -EIO; // If no valid data, exit initialization. + if ( + (readl(card->pBA0 + BA0_ACISV) & + (ACISV_ISV3 | ACISV_ISV4)) == + (ACISV_ISV3 | ACISV_ISV4)) break; // Exit the 'for' if slots are valid. + } + // If we never got valid data, exit initialization. + if ((readl(card->pBA0 + BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) + != (ACISV_ISV3 | ACISV_ISV4)) { + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_ERR + "cs4281: Never got valid data!\n")); + return -EIO; // If no valid data, exit initialization. } - // (12), Start digital data transfer of audio data to the codec. - writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0+BA0_ACOSV); // (468h) + writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0 + BA0_ACOSV); // (468h) //************************************** // Unmute the Master and Alternate // (headphone) volumes. Set to max. //************************************** - cs4281_write_ac97(card,BA0_AC97_HEADPHONE_VOLUME, 0); - cs4281_write_ac97(card,BA0_AC97_MASTER_VOLUME, 0); + cs4281_write_ac97(card, BA0_AC97_HEADPHONE_VOLUME, 0); + cs4281_write_ac97(card, BA0_AC97_MASTER_VOLUME, 0); //****************************************** // Power on the DAC(AddDACUser()from main()) //****************************************** - cs4281_read_ac97(card,BA0_AC97_POWERDOWN, &temp1); - cs4281_write_ac97(card,BA0_AC97_POWERDOWN, temp1 &= 0xfdff); + cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); + cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfdff); // Wait until we sample a DAC ready state. - for(temp2=0; temp2<32; temp2++) - { + for (temp2 = 0; temp2 < 32; temp2++) { // Let's wait a mil to let things settle. delayus(1000); // Read the current state of the power control reg. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); // If the DAC ready state bit is set, stop waiting. - if(temp1 & 0x2) + if (temp1 & 0x2) break; } @@ -562,14 +826,13 @@ cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfeff); // Wait until we sample ADC ready state. - for(temp2=0; temp2<32; temp2++) - { + for (temp2 = 0; temp2 < 32; temp2++) { // Let's wait a mil to let things settle. delayus(1000); // Read the current state of the power control reg. cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1); // If the ADC ready state bit is set, stop waiting. - if(temp1 & 0x1) + if (temp1 & 0x1) break; } // Set up 4281 Register contents that @@ -580,19 +843,19 @@ // Set the fifo to be 15 bytes at offset zero. ac97_slotid = 0x01000f00; // FCR0.RS[4:0]=1(=>slot4, right PCM playback). - // FCR0.LS[4:0]=0(=>slot3, left PCM playback). - // FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. - writel(ac97_slotid, card->pBA0 + BA0_FCR0); // (180h) - writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0); // Turn on FIFO Enable. + // FCR0.LS[4:0]=0(=>slot3, left PCM playback). + // FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0. + writel(ac97_slotid, card->pBA0 + BA0_FCR0); // (180h) + writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0); // Turn on FIFO Enable. // For capture, we map AC97 slot 10 and 11(Left // and Right PCM Record) to DMA Channel 1. // Set the fifo to be 15 bytes at offset sixteen. ac97_slotid = 0x0B0A0f10; // FCR1.RS[4:0]=11(=>slot11, right PCM record). - // FCR1.LS[4:0]=10(=>slot10, left PCM record). - // FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. - writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1); // (184h) - writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1); // Turn on FIFO Enable. + // FCR1.LS[4:0]=10(=>slot10, left PCM record). + // FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16. + writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1); // (184h) + writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1); // Turn on FIFO Enable. // Map the Playback SRC to the same AC97 slots(3 & 4-- // --Playback left & right)as DMA channel 0. @@ -600,33 +863,34 @@ // -- Record left & right) as DMA channel 1. ac97_slotid = 0x0b0a0100; // SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback). - // SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). - // SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) - // SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). - writel(ac97_slotid, card->pBA0 + BA0_SRCSA); // (75ch) + // SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback). + // SCRSA.CRSS[4:0]=11(=>slot11, right PCM record) + // SCRSA.CLSS[4:0]=10(=>slot10, left PCM record). + writel(ac97_slotid, card->pBA0 + BA0_SRCSA); // (75ch) // Set 'Half Terminal Count Interrupt Enable' and 'Terminal // Count Interrupt Enable' in DMA Control Registers 0 & 1. // Set 'MSK' flag to 1 to keep the DMA engines paused. - temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); // (00030001h) - writel(temp1, card->pBA0 + BA0_DCR0); // (154h - writel(temp1, card->pBA0 + BA0_DCR1); // (15ch) + temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK); // (00030001h) + writel(temp1, card->pBA0 + BA0_DCR0); // (154h + writel(temp1, card->pBA0 + BA0_DCR1); // (15ch) // Set 'Auto-Initialize Control' to 'enabled'; For playback, // set 'Transfer Type Control'(TR[1:0]) to 'read transfer', // for record, set Transfer Type Control to 'write transfer'. // All other bits set to zero; Some will be changed @ transfer start. - temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); // (20000018h) - writel(temp1, card->pBA0 + BA0_DMR0); // (150h) - temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); // (20000014h) - writel(temp1, card->pBA0 + BA0_DMR1); // (158h) + temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ); // (20000018h) + writel(temp1, card->pBA0 + BA0_DMR0); // (150h) + temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE); // (20000014h) + writel(temp1, card->pBA0 + BA0_DMR1); // (158h) // Enable DMA interrupts generally, and // DMA0 & DMA1 interrupts specifically. - temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff; - writel(temp1, card->pBA0+BA0_HIMR); + temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff; + writel(temp1, card->pBA0 + BA0_HIMR); - CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n")); return 0; } @@ -638,29 +902,30 @@ { u32 DACSRvalue = 1; - // Based on the sample rate, program the DACSR register. - if(playrate == 8000) + // Based on the sample rate, program the DACSR register. + if (playrate == 8000) DACSRvalue = 5; - if(playrate == 11025) + if (playrate == 11025) DACSRvalue = 4; - else if(playrate == 22050) + else if (playrate == 22050) DACSRvalue = 2; - else if(playrate == 44100) + else if (playrate == 44100) DACSRvalue = 1; - else if((playrate <= 48000) && (playrate >= 6023)) - DACSRvalue = 24576000/(playrate*16); - else if(playrate < 6023) + else if ((playrate <= 48000) && (playrate >= 6023)) + DACSRvalue = 24576000 / (playrate * 16); + else if (playrate < 6023) // Not allowed by open. return; - else if(playrate > 48000) + else if (playrate > 48000) // Not allowed by open. return; - CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO - "cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n", - DACSRvalue,playrate)); - // Write the 'sample rate select code' - // to the 'DAC Sample Rate' register. - writel(DACSRvalue, card->pBA0 + BA0_DACSR); // (744h) + CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO + "cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n", + DACSRvalue, + playrate)); + // Write the 'sample rate select code' + // to the 'DAC Sample Rate' register. + writel(DACSRvalue, card->pBA0 + BA0_DACSR); // (744h) } //****************************************************************************** @@ -670,35 +935,32 @@ { u32 ADCSRvalue = 1; - // - // Based on the sample rate, program the ADCSR register - // - if(outrate == 8000) + // + // Based on the sample rate, program the ADCSR register + // + if (outrate == 8000) ADCSRvalue = 5; - if(outrate == 11025) + if (outrate == 11025) ADCSRvalue = 4; - else if(outrate == 22050) + else if (outrate == 22050) ADCSRvalue = 2; - else if(outrate == 44100) + else if (outrate == 44100) ADCSRvalue = 1; - else if((outrate <= 48000) && (outrate >= 6023)) - ADCSRvalue = 24576000/(outrate*16); - else if(outrate < 6023) - { + else if ((outrate <= 48000) && (outrate >= 6023)) + ADCSRvalue = 24576000 / (outrate * 16); + else if (outrate < 6023) { // Not allowed by open. return; - } - else if(outrate > 48000) - { + } else if (outrate > 48000) { // Not allowed by open. return; } - CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO - "cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n", - ADCSRvalue,outrate) ); + CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO + "cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n", + ADCSRvalue, outrate)); // Write the 'sample rate select code // to the 'ADC Sample Rate' register. - writel(ADCSRvalue, card->pBA0 + BA0_ADCSR); // (748h) + writel(ADCSRvalue, card->pBA0 + BA0_ADCSR); // (748h) } @@ -708,11 +970,12 @@ unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: stop_dac():\n") ); + CS_DBGOUT(CS_WAVE_WRITE, 3, + printk(KERN_INFO "cs4281: stop_dac():\n")); spin_lock_irqsave(&s->lock, flags); s->ena &= ~FMODE_WRITE; - temp1 = readl(s->pBA0+ BA0_DCR0) | DCRn_MSK; - writel(temp1, s->pBA0+BA0_DCR0); + temp1 = readl(s->pBA0 + BA0_DCR0) | DCRn_MSK; + writel(temp1, s->pBA0 + BA0_DCR0); spin_unlock_irqrestore(&s->lock, flags); } @@ -723,20 +986,27 @@ unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: start_dac():\n") ); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: start_dac()+\n")); spin_lock_irqsave(&s->lock, flags); if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped || - s->dma_dac.count > 0) && s->dma_dac.ready) { + s->dma_dac.count > 0) + && s->dma_dac.ready) { s->ena |= FMODE_WRITE; - temp1 = readl(s->pBA0+BA0_DCR0) & ~DCRn_MSK; // Clear DMA0 channel mask. - writel(temp1, s->pBA0+BA0_DCR0); // Start DMA'ing. - writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR); // Enable interrupts. - - writel(7, s->pBA0+BA0_PPRVC); - writel(7, s->pBA0+BA0_PPLVC); - + temp1 = readl(s->pBA0 + BA0_DCR0) & ~DCRn_MSK; // Clear DMA0 channel mask. + writel(temp1, s->pBA0 + BA0_DCR0); // Start DMA'ing. + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Enable interrupts. + + writel(7, s->pBA0 + BA0_PPRVC); + writel(7, s->pBA0 + BA0_PPLVC); + CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 8, printk(KERN_INFO + "cs4281: start_dac(): writel 0x%x start dma\n", + temp1)); + } spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: start_dac()-\n")); } @@ -745,13 +1015,21 @@ unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO "cs4281: stop_adc():\n") ); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: stop_adc()+\n")); spin_lock_irqsave(&s->lock, flags); s->ena &= ~FMODE_READ; - temp1 = readl(s->pBA0+ BA0_DCR1) | DCRn_MSK; - writel(temp1, s->pBA0+BA0_DCR1); + + if (s->conversion == 1) { + s->conversion = 0; + s->prop_adc.fmt = s->prop_adc.fmt_original; + } + temp1 = readl(s->pBA0 + BA0_DCR1) | DCRn_MSK; + writel(temp1, s->pBA0 + BA0_DCR1); spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 3, + printk(KERN_INFO "cs4281: stop_adc()-\n")); } @@ -760,41 +1038,92 @@ unsigned long flags; unsigned temp1; - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: start_adc():\n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: start_adc()+\n")); spin_lock_irqsave(&s->lock, flags); - if (!(s->ena & FMODE_READ) && (s->dma_adc.mapped - || s->dma_adc.count <= - (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) - && s->dma_adc.ready) - { + if (!(s->ena & FMODE_READ) && + (s->dma_adc.mapped || s->dma_adc.count <= + (signed) (s->dma_adc.dmasize - 2 * s->dma_adc.fragsize)) + && s->dma_adc.ready) { + if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) { + // + // now only use 16 bit capture, due to truncation issue + // in the chip, noticable distortion occurs. + // allocate buffer and then convert from 16 bit to + // 8 bit for the user buffer. + // + s->prop_adc.fmt_original = s->prop_adc.fmt; + if (s->prop_adc.fmt & AFMT_S8) { + s->prop_adc.fmt &= ~AFMT_S8; + s->prop_adc.fmt |= AFMT_S16_LE; + } + if (s->prop_adc.fmt & AFMT_U8) { + s->prop_adc.fmt &= ~AFMT_U8; + s->prop_adc.fmt |= AFMT_U16_LE; + } + // + // prog_dmabuf_adc performs a stop_adc() but that is + // ok since we really haven't started the DMA yet. + // + prog_codec(s, CS_TYPE_ADC); + + if (prog_dmabuf_adc(s) != 0) { + CS_DBGOUT(CS_ERROR, 3, + printk(KERN_INFO + "cs4281: start_adc(): error in prog_dmabuf_adc\n")); + } + s->conversion = 1; + } s->ena |= FMODE_READ; - temp1 = readl(s->pBA0+BA0_DCR1) & ~ DCRn_MSK; // Clear DMA1 channel mask bit. - writel(temp1, s->pBA0+BA0_DCR1); // Start recording - writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR); // Enable interrupts. + temp1 = readl(s->pBA0 + BA0_DCR1) & ~DCRn_MSK; // Clear DMA1 channel mask bit. + writel(temp1, s->pBA0 + BA0_DCR1); // Start recording + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Enable interrupts. + CS_DBGOUT(CS_PARMS, 6, + printk(KERN_INFO + "cs4281: start_adc(): writel 0x%x \n", + temp1)); } spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: start_adc()-\n")); } // --------------------------------------------------------------------- -#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) // == 3(for PC), = log base 2( buff sz = 32k). -#define DMABUF_MINORDER 1 // ==> min buffer size = 8K. +// use 64k (+1) rather than 32k as some of the higher frequencies need a larger buffer. +// comments reflect 32k. +#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT+1) // == 3(for PC), = log base 2( buff sz = 32k). +#define DMABUF_MINORDER 1 // ==> min buffer size = 8K. -extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db) +extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db) { struct page *map, *mapend; if (db->rawbuf) { // Undo prog_dmabuf()'s marking the pages as reserved - mapend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); + mapend = + virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - + 1); for (map = virt_to_page(db->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &map->flags); - pci_free_consistent(s->pcidev,PAGE_SIZE<buforder, - db->rawbuf,db->dmaaddr); + mem_map_unreserve(map); + pci_free_consistent(s->pcidev, PAGE_SIZE << db->buforder, + db->rawbuf, db->dmaaddr); } + if (s->tmpbuff && (db->type == CS_TYPE_ADC)) { + // Undo prog_dmabuf()'s marking the pages as reserved + mapend = + virt_to_page(s->tmpbuff + + (PAGE_SIZE << s->buforder_tmpbuff) - 1); + for (map = virt_to_page(s->tmpbuff); map <= mapend; map++) + mem_map_unreserve(map); + pci_free_consistent(s->pcidev, + PAGE_SIZE << s->buforder_tmpbuff, + s->tmpbuff, s->dmaaddr_tmpbuff); + } + s->tmpbuff = NULL; db->rawbuf = NULL; db->mapped = db->ready = 0; } @@ -806,91 +1135,165 @@ unsigned bufs, sample_shift = 0; struct page *map, *mapend; - db->hwptr = db->swptr = db->total_bytes = db->count = - db->error = db->endcleared = db->blocks = 0; + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_dmabuf()+\n")); + db->hwptr = db->swptr = db->total_bytes = db->count = db->error = + db->endcleared = db->blocks = db->wakeup = 0; + if (!db->rawbuf) { db->ready = db->mapped = 0; - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) - if ((db->rawbuf = (void *)pci_alloc_consistent( - s->pcidev, PAGE_SIZE << order, &db->dmaaddr))) - break; - if (!db->rawbuf) - { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4281: prog_dmabuf(): unable to allocate rawbuf\n") ); + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; + order--) + if ( + (db->rawbuf = + (void *) pci_alloc_consistent(s->pcidev, + PAGE_SIZE << + order, + &db-> + dmaaddr))) + break; + if (!db->rawbuf) { + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: prog_dmabuf(): unable to allocate rawbuf\n")); return -ENOMEM; } db->buforder = order; // Now mark the pages as reserved; otherwise the // remap_page_range() in cs4281_mmap doesn't work. - // 1. get index to last page in mem_map array for rawbuf. - mapend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1); - - // 2. mark each physical page in range as 'reserved'. + // 1. get index to last page in mem_map array for rawbuf. + mapend = + virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - + 1); + + // 2. mark each physical page in range as 'reserved'. for (map = virt_to_page(db->rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &map->flags); + mem_map_reserve(map); + } + if (!s->tmpbuff && (db->type == CS_TYPE_ADC)) { + for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; + order--) + if ( + (s->tmpbuff = + (void *) pci_alloc_consistent(s->pcidev, + PAGE_SIZE << + order, + &s-> + dmaaddr_tmpbuff))) + break; + if (!s->tmpbuff) { + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: prog_dmabuf(): unable to allocate tmpbuff\n")); + return -ENOMEM; + } + s->buforder_tmpbuff = order; + // Now mark the pages as reserved; otherwise the + // remap_page_range() in cs4281_mmap doesn't work. + // 1. get index to last page in mem_map array for rawbuf. + mapend = + virt_to_page(s->tmpbuff + + (PAGE_SIZE << s->buforder_tmpbuff) - 1); + + // 2. mark each physical page in range as 'reserved'. + for (map = virt_to_page(s->tmpbuff); map <= mapend; map++) + mem_map_reserve(map); + } + if (db->type == CS_TYPE_DAC) { + if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE)) + sample_shift++; + if (s->prop_dac.channels > 1) + sample_shift++; + bytespersec = s->prop_dac.rate << sample_shift; + } else // CS_TYPE_ADC + { + if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE)) + sample_shift++; + if (s->prop_adc.channels > 1) + sample_shift++; + bytespersec = s->prop_adc.rate << sample_shift; } - if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) - sample_shift++; - if (s->channels > 1) - sample_shift++; - bytespersec = s->rate << sample_shift; bufs = PAGE_SIZE << db->buforder; -#define INTERRUPT_RATE_MS 100 // Interrupt rate in milliseconds. +#define INTERRUPT_RATE_MS 100 // Interrupt rate in milliseconds. db->numfrag = 2; - temp1 = bytespersec/(1000/INTERRUPT_RATE_MS); // Nominal frag size(bytes/interrupt) - db->fragshift = 8; // Min 256 bytes. - while( 1 << db->fragshift < temp1) // Calc power of 2 frag size. - db->fragshift +=1; - db->fragsize = 1 << db->fragshift; + temp1 = bytespersec / (1000 / INTERRUPT_RATE_MS); // Nominal frag size(bytes/interrupt) + db->fragshift = 8; // Min 256 bytes. + while (1 << db->fragshift < temp1) // Calc power of 2 frag size. + db->fragshift += 1; + db->fragsize = 1 << db->fragshift; db->dmasize = db->fragsize * 2; - - // If the calculated size is larger than the allocated - // buffer, divide the allocated buffer into 2 fragments. - if(db->dmasize > bufs) { - db->numfrag = 2; // Two fragments. - db->fragsize = bufs >> 1; // Each 1/2 the alloc'ed buffer. - db->fragsamples = db->fragsize >> sample_shift; // # samples/fragment. - db->dmasize = bufs; // Use all the alloc'ed buffer. - - db->fragshift = 0; // Calculate 'fragshift'. - temp1 = db->fragsize; // update_ptr() uses it - while( (temp1 >>=1) > 1) // to calc 'total-bytes' - db->fragshift +=1; // returned in DSP_GETI/OPTR. - } - CS_DBGOUT(CS_PARMS, 3, printk(KERN_INFO - "cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d\n", - db->numfrag,db->fragsize,db->fragsamples,db->fragshift) ); + db->fragsamples = db->fragsize >> sample_shift; // # samples/fragment. + +// If the calculated size is larger than the allocated +// buffer, divide the allocated buffer into 2 fragments. + if (db->dmasize > bufs) { + + db->numfrag = 2; // Two fragments. + db->fragsize = bufs >> 1; // Each 1/2 the alloc'ed buffer. + db->fragsamples = db->fragsize >> sample_shift; // # samples/fragment. + db->dmasize = bufs; // Use all the alloc'ed buffer. + + db->fragshift = 0; // Calculate 'fragshift'. + temp1 = db->fragsize; // update_ptr() uses it + while ((temp1 >>= 1) > 1) // to calc 'total-bytes' + db->fragshift += 1; // returned in DSP_GETI/OPTR. + } + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_dmabuf()-\n")); + CS_DBGOUT(CS_PARMS, 8, + printk(KERN_INFO + "cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d bufs=%d fmt=0x%x ch=%d\n", + db->numfrag, db->fragsize, db->fragsamples, + db->fragshift, bufs, + (db->type == + CS_TYPE_DAC) ? s->prop_dac.fmt : s->prop_adc.fmt, + (db->type == + CS_TYPE_DAC) ? s->prop_dac.channels : s-> + prop_adc.channels)); return 0; -} +} static int prog_dmabuf_adc(struct cs4281_state *s) { unsigned long va; - unsigned count; + unsigned count; int c; stop_adc(s); + s->dma_adc.type = CS_TYPE_ADC; if ((c = prog_dmabuf(s, &s->dma_adc))) return c; - + + if (s->dma_adc.rawbuf) { + memset(s->dma_adc.rawbuf, + (s->prop_adc. + fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, + s->dma_adc.dmasize); + } + if (s->tmpbuff) { + memset(s->tmpbuff, + (s->prop_adc. + fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, + PAGE_SIZE << s->buforder_tmpbuff); + } + va = virt_to_bus(s->dma_adc.rawbuf); - - count = s->dma_adc.dmasize; - - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) - count /= 2; // 16-bit. - - if(s->channels > 1) - count /= 2; // Assume stereo. - - CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO - "cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n", count,(unsigned)va) ); - writel(va, s->pBA0+BA0_DBA1); // Set buffer start address. - writel(count-1, s->pBA0+BA0_DBC1); // Set count. + count = s->dma_adc.dmasize; + + if (s->prop_adc. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) + count /= 2; // 16-bit. + + if (s->prop_adc.channels > 1) + count /= 2; // Assume stereo. + + CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO + "cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n", + count, (unsigned) va)); + + writel(va, s->pBA0 + BA0_DBA1); // Set buffer start address. + writel(count - 1, s->pBA0 + BA0_DBC1); // Set count. s->dma_adc.ready = 1; return 0; } @@ -902,43 +1305,50 @@ unsigned count; int c; stop_dac(s); + s->dma_dac.type = CS_TYPE_DAC; if ((c = prog_dmabuf(s, &s->dma_dac))) return c; - memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) - ? 0x80 : 0, s->dma_dac.dmasize); + memset(s->dma_dac.rawbuf, + (s->prop_dac.fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, + s->dma_dac.dmasize); va = virt_to_bus(s->dma_dac.rawbuf); - count = s->dma_dac.dmasize; - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) - count /= 2; // 16-bit. - - if(s->channels > 1) - count /= 2; // Assume stereo. - - writel(va, s->pBA0+BA0_DBA0); // Set buffer start address. - writel(count-1, s->pBA0+BA0_DBC0); // Set count. - - CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO - "cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n", count,(unsigned)va) ); + count = s->dma_dac.dmasize; + if (s->prop_dac. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) + count /= 2; // 16-bit. + + if (s->prop_dac.channels > 1) + count /= 2; // Assume stereo. + + writel(va, s->pBA0 + BA0_DBA0); // Set buffer start address. + writel(count - 1, s->pBA0 + BA0_DBC0); // Set count. + + CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO + "cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n", + count, (unsigned) va)); s->dma_dac.ready = 1; return 0; } -static void clear_advance(void *buf, unsigned bsize, unsigned bptr, unsigned len, unsigned char c) +static void clear_advance(void *buf, unsigned bsize, unsigned bptr, + unsigned len, unsigned char c) { if (bptr + len > bsize) { unsigned x = bsize - bptr; - memset(((char *)buf) + bptr, c, x); + memset(((char *) buf) + bptr, c, x); bptr = 0; len -= x; } - CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO - "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n", - (unsigned)c,(unsigned)((char *)buf) + bptr, len) ); - memset(((char *)buf) + bptr, c, len); + CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO + "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n", + (unsigned) c, + (unsigned) ((char *) buf) + + bptr, len)); + memset(((char *) buf) + bptr, c, len); } @@ -947,156 +1357,219 @@ static void cs4281_update_ptr(struct cs4281_state *s) { int diff; - unsigned hwptr, va, temp1; + unsigned hwptr, va; // update ADC pointer if (s->ena & FMODE_READ) { - hwptr = readl(s->pBA0+BA0_DCA1); // Read capture DMA address. + hwptr = readl(s->pBA0 + BA0_DCA1); // Read capture DMA address. va = virt_to_bus(s->dma_adc.rawbuf); - hwptr -= (unsigned)va; - diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) % s->dma_adc.dmasize; + hwptr -= (unsigned) va; + diff = + (s->dma_adc.dmasize + hwptr - + s->dma_adc.hwptr) % s->dma_adc.dmasize; s->dma_adc.hwptr = hwptr; s->dma_adc.total_bytes += diff; s->dma_adc.count += diff; + if (s->dma_adc.count > s->dma_adc.dmasize) + s->dma_adc.count = s->dma_adc.dmasize; if (s->dma_adc.mapped) { - if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) - wake_up(&s->dma_adc.wait); + if (s->dma_adc.count >= + (signed) s->dma_adc.fragsize) wake_up(&s-> + dma_adc. + wait); } else { if (s->dma_adc.count > 0) wake_up(&s->dma_adc.wait); } - CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned)s,s->dma_adc.hwptr,s->dma_adc.total_bytes,s->dma_adc.count) ); + CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO + "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", + (unsigned) s, + s->dma_adc.hwptr, + s->dma_adc.total_bytes, + s->dma_adc.count)); } // update DAC pointer // // check for end of buffer, means that we are going to wait for another interrupt // to allow silence to fill the fifos on the part, to keep pops down to a minimum. // - if ( (s->ena & FMODE_WRITE) && (!s->endofbuffer) ) - { - hwptr = readl(s->pBA0+BA0_DCA0); // Read play DMA address. + if (s->ena & FMODE_WRITE) { + hwptr = readl(s->pBA0 + BA0_DCA0); // Read play DMA address. va = virt_to_bus(s->dma_dac.rawbuf); - hwptr -= (unsigned)va; - diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize; + hwptr -= (unsigned) va; + diff = + (s->dma_dac.dmasize + hwptr - + s->dma_dac.hwptr) % s->dma_dac.dmasize; s->dma_dac.hwptr = hwptr; s->dma_dac.total_bytes += diff; if (s->dma_dac.mapped) { s->dma_dac.count += diff; - if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) + if (s->dma_dac.count >= s->dma_dac.fragsize) { + s->dma_dac.wakeup = 1; wake_up(&s->dma_dac.wait); + if (s->dma_dac.count > s->dma_dac.dmasize) + s->dma_dac.count &= + s->dma_dac.dmasize - 1; + } } else { + s->dma_dac.count -= diff; if (s->dma_dac.count <= 0) { - s->ena &= ~FMODE_WRITE; - temp1 = readl(s->pBA0+BA0_DCR0); - // - // fill with silence, and wait on turning off the DAC until interrupt routine. - // wait on "Poke(pBA0+BA0_DCR0, temp1 | DCRn_MSK); // Stop Play DMA" - // - CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n", - (unsigned)(s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, - (unsigned)s->dma_dac.rawbuf, s->dma_dac.dmasize) ); - memset(s->dma_dac.rawbuf, (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, - s->dma_dac.dmasize); - s->endofbuffer = 1; - } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize - && !s->dma_dac.endcleared) { - clear_advance(s->dma_dac.rawbuf, - s->dma_dac.dmasize, s->dma_dac.swptr, + // + // fill with silence, and do not shut down the DAC. + // Continue to play silence until the _release. + // + CS_DBGOUT(CS_WAVE_WRITE, 6, + printk(KERN_INFO + "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n", + (unsigned) (s->prop_dac. + fmt & (AFMT_U8 + | + AFMT_U16_LE)) + ? 0x80 : 0, + (unsigned) s->dma_dac. + rawbuf, + s->dma_dac.dmasize)); + memset(s->dma_dac.rawbuf, + (s->prop_dac. + fmt & (AFMT_U8 | AFMT_U16_LE)) ? + 0x80 : 0, s->dma_dac.dmasize); + } else if (s->dma_dac.count <= + (signed) s->dma_dac.fragsize + && !s->dma_dac.endcleared) { + clear_advance(s->dma_dac.rawbuf, + s->dma_dac.dmasize, + s->dma_dac.swptr, s->dma_dac.fragsize, - (s->fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0); + (s->prop_dac. + fmt & (AFMT_U8 | + AFMT_U16_LE)) ? 0x80 + : 0); s->dma_dac.endcleared = 1; } - if (s->dma_dac.count < (signed)s->dma_dac.dmasize) + if (s->dma_dac.count < (signed) s->dma_dac.dmasize) wake_up(&s->dma_dac.wait); } - CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO - "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", - (unsigned)s,s->dma_dac.hwptr,s->dma_dac.total_bytes,s->dma_dac.count) ); + CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO + "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n", + (unsigned) s, + s->dma_dac.hwptr, + s->dma_dac.total_bytes, + s->dma_dac.count)); } } // --------------------------------------------------------------------- -static void prog_codec(struct cs4281_state *s) +static void prog_codec(struct cs4281_state *s, unsigned type) { unsigned long flags; unsigned temp1, format; - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: prog_codec()+ \n") ); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_codec()+ \n")); spin_lock_irqsave(&s->lock, flags); - temp1 = readl(s->pBA0+BA0_DCR0); - writel(temp1 | DCRn_MSK, s->pBA0+BA0_DCR0); // Stop play DMA, if active. - temp1 = readl(s->pBA0+BA0_DCR1); - writel(temp1 | DCRn_MSK, s->pBA0+BA0_DCR1); // Stop capture DMA, if active. - - // program sampling rates - // Note, for CS4281, capture & play rates can be set independently. - cs4281_record_rate(s, s->rate); - - // program ADC parameters - format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE; - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit - if(s->fmt & (AFMT_S16_BE | AFMT_U16_BE)) // Big-endian? - format |= DMRn_BEND; - if(s->fmt & (AFMT_U16_LE | AFMT_U16_BE)) - format |= DMRn_USIGN; // Unsigned. - } - else - format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned - if(s->channels < 2) - format |= DMRn_MONO; - - writel(format, s->pBA0+BA0_DMR1); - - - // program DAC parameters - format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ; - if(s->fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit - if(s->fmt & (AFMT_S16_BE | AFMT_U16_BE)) - format |= DMRn_BEND; // Big Endian. - if(s->fmt & (AFMT_U16_LE | AFMT_U16_BE)) - format |= DMRn_USIGN; // Unsigned. - } - else - format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned - - if(s->channels < 2) - format |= DMRn_MONO; - - writel(format, s->pBA0+BA0_DMR0); - - CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO - "cs4281: prog_codec(): format=0x%.8x rate=%d\n", format,s->rate) ); + if (type == CS_TYPE_ADC) { + temp1 = readl(s->pBA0 + BA0_DCR1); + writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR1); // Stop capture DMA, if active. + + // program sampling rates + // Note, for CS4281, capture & play rates can be set independently. + cs4281_record_rate(s, s->prop_adc.rate); + + // program ADC parameters + format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE; + if (s->prop_adc. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit + if (s->prop_adc.fmt & (AFMT_S16_BE | AFMT_U16_BE)) // Big-endian? + format |= DMRn_BEND; + if (s->prop_adc.fmt & (AFMT_U16_LE | AFMT_U16_BE)) + format |= DMRn_USIGN; // Unsigned. + } else + format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned + if (s->prop_adc.channels < 2) + format |= DMRn_MONO; + + writel(format, s->pBA0 + BA0_DMR1); + + CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO + "cs4281: prog_codec(): adc %s %s %s rate=%d DMR0 format=0x%.8x\n", + (format & DMRn_SIZE8) ? "8" : + "16", + (format & DMRn_USIGN) ? + "Unsigned" : "Signed", + (format & DMRn_MONO) ? "Mono" + : "Stereo", s->prop_adc.rate, + format)); + + s->ena &= ~FMODE_READ; // not capturing data yet + } + + + if (type == CS_TYPE_DAC) { + temp1 = readl(s->pBA0 + BA0_DCR0); + writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR0); // Stop play DMA, if active. + + // program sampling rates + // Note, for CS4281, capture & play rates can be set independently. + cs4281_play_rate(s, s->prop_dac.rate); + + // program DAC parameters + format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ; + if (s->prop_dac. + fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) { // 16-bit + if (s->prop_dac.fmt & (AFMT_S16_BE | AFMT_U16_BE)) + format |= DMRn_BEND; // Big Endian. + if (s->prop_dac.fmt & (AFMT_U16_LE | AFMT_U16_BE)) + format |= DMRn_USIGN; // Unsigned. + } else + format |= DMRn_SIZE8 | DMRn_USIGN; // 8-bit, unsigned + + if (s->prop_dac.channels < 2) + format |= DMRn_MONO; + + writel(format, s->pBA0 + BA0_DMR0); + + + CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO + "cs4281: prog_codec(): dac %s %s %s rate=%d DMR0 format=0x%.8x\n", + (format & DMRn_SIZE8) ? "8" : + "16", + (format & DMRn_USIGN) ? + "Unsigned" : "Signed", + (format & DMRn_MONO) ? "Mono" + : "Stereo", s->prop_dac.rate, + format)); - cs4281_play_rate(s, s->rate); + s->ena &= ~FMODE_WRITE; // not capturing data yet - s->ena = 0; // Neither writing or reading. + } spin_unlock_irqrestore(&s->lock, flags); + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: prog_codec()- \n")); } // --------------------------------------------------------------------- -static const char invalid_magic[] = KERN_CRIT "cs4281: invalid magic value\n"; +static const char invalid_magic[] = + KERN_CRIT "cs4281: invalid magic value\n"; #define VALIDATE_STATE(s) \ ({ \ - if (!(s) || (s)->magic != CS4281_MAGIC) { \ - printk(invalid_magic); \ - return -ENXIO; \ - } \ + if (!(s) || (s)->magic != CS4281_MAGIC) { \ + printk(invalid_magic); \ + return -ENXIO; \ + } \ }) // --------------------------------------------------------------------- -static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, unsigned long arg) +static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd, + unsigned long arg) { // Index to mixer_src[] is value of AC97 Input Mux Select Reg. // Value of array member is recording source Device ID Mask. @@ -1104,39 +1577,81 @@ SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1, SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0 }; - + // 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 + [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 }; - - + + static const unsigned mixreg[] = { BA0_AC97_PCM_OUT_VOLUME, - BA0_AC97_AUX_VOLUME, - BA0_AC97_CD_VOLUME, + BA0_AC97_AUX_VOLUME, + BA0_AC97_CD_VOLUME, BA0_AC97_LINE_IN_VOLUME }; unsigned char l, r, rl, rr, vidx; - unsigned char attentbl[11] = {63,42,26,17,14,11,8,6,4,2,0}; + unsigned char attentbl[11] = + { 63, 42, 26, 17, 14, 11, 8, 6, 4, 2, 0 }; unsigned temp1; int i, val; VALIDATE_STATE(s); - + CS_DBGOUT(CS_FUNCTION, 4, + printk(KERN_INFO + "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n", + (unsigned) s, cmd)); +#if CSDEBUG + printioctl(cmd); +#endif +#if CSDEBUG_INTERFACE + + 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 + if (cmd == SOUND_MIXER_PRIVATE1) { // enable/disable/query mixer preamp - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; if (val != -1) { cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1); @@ -1145,27 +1660,29 @@ } cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1); val = (temp1 & 0x40) ? 1 : 0; - return put_user(val, (int *)arg); + return put_user(val, (int *) arg); } if (cmd == SOUND_MIXER_PRIVATE2) { // enable/disable/query spatializer - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; if (val != -1) { temp1 = (val & 0x3f) >> 2; cs4281_write_ac97(s, BA0_AC97_3D_CONTROL, temp1); - cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, &temp1); - cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE,temp1 | 0x2000); + cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, + &temp1); + cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE, + temp1 | 0x2000); } cs4281_read_ac97(s, BA0_AC97_3D_CONTROL, &temp1); - return put_user((temp1 << 2) | 3, (int *)arg); + return put_user((temp1 << 2) | 3, (int *) arg); } if (cmd == SOUND_MIXER_INFO) { mixer_info info; strncpy(info.id, "CS4281", sizeof(info.id)); strncpy(info.name, "Crystal CS4281", sizeof(info.name)); info.modify_counter = s->mix.modcnt; - if (copy_to_user((void *)arg, &info, sizeof(info))) + if (copy_to_user((void *) arg, &info, sizeof(info))) return -EFAULT; return 0; } @@ -1173,138 +1690,142 @@ _old_mixer_info info; strncpy(info.id, "CS4281", sizeof(info.id)); strncpy(info.name, "Crystal CS4281", sizeof(info.name)); - if (copy_to_user((void *)arg, &info, sizeof(info))) + if (copy_to_user((void *) arg, &info, sizeof(info))) return -EFAULT; return 0; } if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, (int *)arg); - - if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + return put_user(SOUND_VERSION, (int *) arg); + + if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - - // If ioctl has only the IOC_READ bit(bit 31) - // on, process the only-read commands. - if (_IOC_DIR(cmd) == _IOC_READ) { + + // If ioctl has only the SIOC_READ bit(bit 31) + // on, process the only-read commands. + if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { - case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source - cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT, &temp1); - return put_user(mixer_src[temp1 & 7], (int *)arg); - - case SOUND_MIXER_DEVMASK: // Arg contains a bit for each supported device - return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD | - SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC | - SOUND_MASK_VOLUME | SOUND_MASK_RECLEV | - SOUND_MASK_SPEAKER, (int *)arg); - - case SOUND_MIXER_RECMASK: // Arg contains a bit for each supported recording source - return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD - | SOUND_MASK_VOLUME | SOUND_MASK_LINE1, (int *)arg); - - case SOUND_MIXER_STEREODEVS: // Mixer channels supporting stereo - return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | SOUND_MASK_CD | - SOUND_MASK_LINE | SOUND_MASK_LINE1 | SOUND_MASK_MIC | - SOUND_MASK_VOLUME | SOUND_MASK_RECLEV, (int *)arg); + case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source + cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT, + &temp1); + return put_user(mixer_src[temp1 & 7], (int *) arg); + + case SOUND_MIXER_DEVMASK: // Arg contains a bit for each supported device + return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | + SOUND_MASK_CD | SOUND_MASK_LINE | + SOUND_MASK_LINE1 | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | + SOUND_MASK_RECLEV | + SOUND_MASK_SPEAKER, (int *) arg); + + case SOUND_MIXER_RECMASK: // Arg contains a bit for each supported recording source + return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC | + SOUND_MASK_CD | SOUND_MASK_VOLUME | + SOUND_MASK_LINE1, (int *) arg); + + case SOUND_MIXER_STEREODEVS: // Mixer channels supporting stereo + return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH | + SOUND_MASK_CD | SOUND_MASK_LINE | + SOUND_MASK_LINE1 | SOUND_MASK_MIC | + SOUND_MASK_VOLUME | + SOUND_MASK_RECLEV, (int *) arg); case SOUND_MIXER_CAPS: - return put_user(SOUND_CAP_EXCL_INPUT, (int *)arg); + return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg); default: i = _IOC_NR(cmd); - if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) + if (i >= SOUND_MIXER_NRDEVICES + || !(vidx = mixtable1[i])) return -EINVAL; - return put_user(s->mix.vol[vidx-1], (int *)arg); + return put_user(s->mix.vol[vidx - 1], (int *) arg); } } - - // If ioctl doesn't have both the IOC_READ and - // the IOC_WRITE bit set, return invalid. - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + // If ioctl doesn't have both the SIOC_READ and + // the SIOC_WRITE bit set, return invalid. + if (_SIOC_DIR(cmd) != (_SIOC_READ | _SIOC_WRITE)) return -EINVAL; - - // Increment the count of volume writes. + + // Increment the count of volume writes. s->mix.modcnt++; - - // Isolate the command; it must be a write. + + // Isolate the command; it must be a write. switch (_IOC_NR(cmd)) { - - case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source - if (get_user(val, (int *)arg)) + + case SOUND_MIXER_RECSRC: // Arg contains a bit for each recording source + if (get_user(val, (int *) arg)) return -EFAULT; - i = hweight32(val); // i = # bits on in val. - if (i != 1) // One & only 1 bit must be on. + i = hweight32(val); // i = # bits on in val. + if (i != 1) // One & only 1 bit must be on. return 0; - for(i=0; i 100) - l = 100; // Max soundcard.h vol is 100. - if(l < 6) { + if (l > 100) + l = 100; // Max soundcard.h vol is 100. + if (l < 6) { rl = 63; - l = 0; - } - else - rl = attentbl[(10*l)/100]; // Convert 0-100 vol to 63-0 atten. - - r = (val >> 8) & 0xff; - if (r > 100) - r = 100; // Max right volume is 100, too - if(r < 6) { - rr = 63; - r = 0; - } - else - rr = attentbl[(10*r)/100]; // Convert volume to attenuation. - - if ((rl > 60 ) && (rr > 60)) // If both l & r are 'low', - temp1 = 0x8000; // turn on the mute bit. + l = 0; + } else + rl = attentbl[(10 * l) / 100]; // Convert 0-100 vol to 63-0 atten. + + r = (val >> 8) & 0xff; + if (r > 100) + r = 100; // Max right volume is 100, too + if (r < 6) { + rr = 63; + r = 0; + } else + rr = attentbl[(10 * r) / 100]; // Convert volume to attenuation. + + if ((rl > 60) && (rr > 60)) // If both l & r are 'low', + temp1 = 0x8000; // turn on the mute bit. else temp1 = 0; - + temp1 |= (rl << 8) | rr; - + cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, temp1); cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, temp1); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[8] = ((unsigned int)r << 8) | l; + s->mix.vol[8] = ((unsigned int) r << 8) | l; #else s->mix.vol[8] = val; #endif - return put_user(s->mix.vol[8], (int *)arg); + return put_user(s->mix.vol[8], (int *) arg); case SOUND_MIXER_SPEAKER: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) l = 100; - if(l < 3 ) { + if (l < 3) { rl = 0; l = 0; - } - else { - rl = (l*2 - 5)/13; // Convert 0-100 range to 0-15. - l = (rl*13 +5)/2; + } else { + rl = (l * 2 - 5) / 13; // Convert 0-100 range to 0-15. + l = (rl * 13 + 5) / 2; } - if (rl < 3){ - temp1 = 0x8000; - rl = 0; - } - else - temp1 = 0; - rl = 15 - rl; // Convert volume to attenuation. + if (rl < 3) { + temp1 = 0x8000; + rl = 0; + } else + temp1 = 0; + rl = 15 - rl; // Convert volume to attenuation. temp1 |= rl << 1; cs4281_write_ac97(s, BA0_AC97_PC_BEEP_VOLUME, temp1); @@ -1313,10 +1834,10 @@ #else s->mix.vol[6] = val; #endif - return put_user(s->mix.vol[6], (int *)arg); + return put_user(s->mix.vol[6], (int *) arg); case SOUND_MIXER_RECLEV: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) @@ -1324,25 +1845,25 @@ r = (val >> 8) & 0xff; if (r > 100) r = 100; - rl = (l*2 - 5) / 13; // Convert 0-100 scale to 0-15. - rr = (r*2 - 5) / 13; - if (rl <3 && rr <3) + rl = (l * 2 - 5) / 13; // Convert 0-100 scale to 0-15. + rr = (r * 2 - 5) / 13; + if (rl < 3 && rr < 3) temp1 = 0x8000; else temp1 = 0; temp1 = temp1 | (rl << 8) | rr; - cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1); + cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[7] = ((unsigned int)r << 8) | l; + s->mix.vol[7] = ((unsigned int) r << 8) | l; #else s->mix.vol[7] = val; #endif - return put_user(s->mix.vol[7], (int *)arg); + return put_user(s->mix.vol[7], (int *) arg); case SOUND_MIXER_MIC: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) @@ -1350,19 +1871,18 @@ if (l < 1) { l = 0; rl = 0; - } - else { - rl = ((unsigned)l*5 - 4)/16; // Convert 0-100 range to 0-31. - l = (rl*16 +4)/5; + } else { + rl = ((unsigned) l * 5 - 4) / 16; // Convert 0-100 range to 0-31. + l = (rl * 16 + 4) / 5; } cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1); - temp1 &= 0x40; // Isolate 20db gain bit. - if (rl < 3){ - temp1 |= 0x8000; - rl = 0; + temp1 &= 0x40; // Isolate 20db gain bit. + if (rl < 3) { + temp1 |= 0x8000; + rl = 0; } - rl = 31 - rl; // Convert volume to attenuation. - temp1 |= rl; + rl = 31 - rl; // Convert volume to attenuation. + temp1 |= rl; cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS @@ -1370,49 +1890,52 @@ #else s->mix.vol[5] = val; #endif - return put_user(s->mix.vol[5], (int *)arg); - - + return put_user(s->mix.vol[5], (int *) arg); + + case SOUND_MIXER_SYNTH: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) l = 100; - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; r = (val >> 8) & 0xff; if (r > 100) r = 100; - rl = (l * 2 - 11)/3; // Convert 0-100 range to 0-63. - rr = (r * 2 - 11)/3; - if (rl < 3) // If l is low, turn on - temp1 = 0x0080; // the mute bit. + rl = (l * 2 - 11) / 3; // Convert 0-100 range to 0-63. + rr = (r * 2 - 11) / 3; + if (rl < 3) // If l is low, turn on + temp1 = 0x0080; // the mute bit. else temp1 = 0; - rl = 63 - rl; // Convert vol to attenuation. - writel(temp1|rl, s->pBA0+BA0_FMLVC); - if (rr < 3) // If rr is low, turn on - temp1 = 0x0080; // the mute bit. + rl = 63 - rl; // Convert vol to attenuation. + writel(temp1 | rl, s->pBA0 + BA0_FMLVC); + if (rr < 3) // If rr is low, turn on + temp1 = 0x0080; // the mute bit. else temp1 = 0; - rr = 63 - rr; // Convert vol to attenuation. - writel(temp1 | rr, s->pBA0+BA0_FMRVC); + rr = 63 - rr; // Convert vol to attenuation. + writel(temp1 | rr, s->pBA0 + BA0_FMRVC); #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS s->mix.vol[4] = (r << 8) | l; #else s->mix.vol[4] = val; #endif - return put_user(s->mix.vol[4], (int *)arg); + return put_user(s->mix.vol[4], (int *) arg); + - default: + CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO + "cs4281: mixer_ioctl(): default\n")); + i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i])) return -EINVAL; - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; l = val & 0xff; if (l > 100) @@ -1420,32 +1943,30 @@ if (l < 1) { l = 0; rl = 31; - } - else - rl = (attentbl[(l*10)/100])>>1; - + } else + rl = (attentbl[(l * 10) / 100]) >> 1; + r = (val >> 8) & 0xff; if (r > 100) r = 100; if (r < 1) { r = 0; rr = 31; - } - else - rr = (attentbl[(r*10)/100])>>1; + } else + rr = (attentbl[(r * 10) / 100]) >> 1; if ((rl > 30) && (rr > 30)) temp1 = 0x8000; else temp1 = 0; - temp1 = temp1 | (rl << 8) | rr; - cs4281_write_ac97(s, mixreg[vidx-1], temp1); - + temp1 = temp1 | (rl << 8) | rr; + cs4281_write_ac97(s, mixreg[vidx - 1], temp1); + #ifdef OSS_DOCUMENTED_MIXER_SEMANTICS - s->mix.vol[vidx-1] = ((unsigned int)r << 8) | l; + s->mix.vol[vidx - 1] = ((unsigned int) r << 8) | l; #else - s->mix.vol[vidx-1] = val; + s->mix.vol[vidx - 1] = val; #endif - return put_user(s->mix.vol[vidx-1], (int *)arg); + return put_user(s->mix.vol[vidx - 1], (int *) arg); } } @@ -1478,7 +1999,8 @@ static int cs4281_release_mixdev(struct inode *inode, struct file *file) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; VALIDATE_STATE(s); MOD_DEC_USE_COUNT; @@ -1489,22 +2011,72 @@ static int cs4281_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - return mixer_ioctl((struct cs4281_state *)file->private_data, cmd, arg); + return mixer_ioctl((struct cs4281_state *) file->private_data, cmd, + arg); } // ****************************************************************************************** // Mixer file operations struct. // ****************************************************************************************** -static /*const*/ struct file_operations cs4281_mixer_fops = { - llseek: cs4281_llseek, - ioctl: cs4281_ioctl_mixdev, - open: cs4281_open_mixdev, - release: cs4281_release_mixdev, +static /*const */ struct file_operations cs4281_mixer_fops = { + llseek:cs4281_llseek, + ioctl:cs4281_ioctl_mixdev, + open:cs4281_open_mixdev, + release:cs4281_release_mixdev, }; // --------------------------------------------------------------------- + +static int drain_adc(struct cs4281_state *s, int nonblock) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int count; + unsigned tmo; + + if (s->dma_adc.mapped) + return 0; + add_wait_queue(&s->dma_adc.wait, &wait); + for (;;) { + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&s->lock, flags); + count = s->dma_adc.count; + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: drain_adc() %d\n", + count)); + spin_unlock_irqrestore(&s->lock, flags); + if (count <= 0) { + CS_DBGOUT(CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: drain_adc() count<0\n")); + break; + } + if (signal_pending(current)) + break; + if (nonblock) { + remove_wait_queue(&s->dma_adc.wait, &wait); + current->state = TASK_RUNNING; + return -EBUSY; + } + tmo = + 3 * HZ * (count + + s->dma_adc.fragsize) / 2 / s->prop_adc.rate; + if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE)) + tmo >>= 1; + if (s->prop_adc.channels > 1) + tmo >>= 1; + if (!schedule_timeout(tmo + 1)) + printk(KERN_DEBUG "cs4281: dma timed out??\n"); + } + remove_wait_queue(&s->dma_adc.wait, &wait); + current->state = TASK_RUNNING; + if (signal_pending(current)) + return -ERESTARTSYS; + return 0; +} + static int drain_dac(struct cs4281_state *s, int nonblock) { DECLARE_WAITQUEUE(wait, current); @@ -1514,9 +2086,9 @@ if (s->dma_dac.mapped) return 0; - current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->dma_dac.wait, &wait); for (;;) { + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); @@ -1529,10 +2101,12 @@ current->state = TASK_RUNNING; return -EBUSY; } - tmo = 3 * HZ * (count + s->dma_dac.fragsize) / 2 / s->rate; - if (s->fmt & (AFMT_S16_LE | AFMT_U16_LE)) + tmo = + 3 * HZ * (count + + s->dma_dac.fragsize) / 2 / s->prop_dac.rate; + if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE)) tmo >>= 1; - if (s->channels > 1) + if (s->prop_dac.channels > 1) tmo >>= 1; if (!schedule_timeout(tmo + 1)) printk(KERN_DEBUG "cs4281: dma timed out??\n"); @@ -1544,19 +2118,189 @@ return 0; } +//**************************************************************************** +// +// CopySamples copies 16-bit stereo samples from the source to the +// destination, possibly converting down to either 8-bit or mono or both. +// 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. +// iChannels - Stereo - 2 +// Mono - 1 +// fmt - AFMT_xxx (soundcard.h formats) +// +// NOTES: only call this routine for conversion to 8bit from 16bit +// +//**************************************************************************** +static void CopySamples(char *dst, char *src, int count, int iChannels, + unsigned fmt) +{ + + unsigned short *psSrc; + long lAudioSample; + + 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 iChannels=%d fmt=0x%x\n", + (unsigned) dst, (unsigned) src, (unsigned) count, + (unsigned) iChannels, (unsigned) fmt)); + + // Gershwin does format conversion in hardware so normally + // we don't do any host based coversion. The data formatter + // truncates 16 bit data to 8 bit and that causes some hiss. + // We have already forced the HW to do 16 bit sampling and + // 2 channel so that we can use software to round instead + // of truncate + + // + // See if the data should be output as 8-bit unsigned stereo. + // + if ((iChannels == 2) && (fmt & AFMT_U8)) { + // + // Convert each 16-bit unsigned stereo sample to 8-bit unsigned + // stereo using rounding. + // + psSrc = (unsigned short *) src; + count = count / 2; + while (count--) { + lAudioSample = (long) psSrc[count] + (long) 0x80; + if (lAudioSample > 0xffff) { + lAudioSample = 0xffff; + } + dst[count] = (char) (lAudioSample >> 8); + } + } + // + // check for 8-bit signed stereo. + // + else if ((iChannels == 2) && (fmt & AFMT_S8)) { + // + // Convert each 16-bit stereo sample to 8-bit stereo using rounding. + // + psSrc = (short *) src; + while (count--) { + lAudioSample = + (((long) psSrc[0] + (long) psSrc[1]) / 2); + psSrc += 2; + *dst++ = (char) ((short) lAudioSample >> 8); + } + } + // + // See if the data should be output at 8-bit unsigned mono. + // + else if ((iChannels == 1) && (fmt & AFMT_U8)) { + // + // Convert each 16-bit unsigned mono sample to 8-bit unsigned + // mono using rounding. + // + + psSrc = (short *) src; + while (count--) { + lAudioSample = (long) *psSrc++ + (long) 0x80; + if (lAudioSample > 0x7fff) { + lAudioSample = 0x7fff; + } + // + // Convert Signed to Unsigned. + // + + *dst++ = + (unsigned + char) (((short) lAudioSample + + (short) 0x8000) >> 8); + } + } + // + // Otherwise, the data should be output as 8-bit signed mono. + // + else if ((iChannels == 1) && (fmt & AFMT_S8)) { + // + // Convert each 16-bit signed mono sample to 8-bit signed mono + // using rounding. + // + psSrc = (short *) src; + while (count--) { + lAudioSample = + (((long) psSrc[0] + (long) psSrc[1]) / 2); + if (lAudioSample > 0x7fff) { + lAudioSample = 0x7fff; + } + psSrc += 2; + *dst++ = (char) ((short) lAudioSample >> 8); + } + } +} + +// +// cs_copy_to_user() +// replacement for the standard copy_to_user, to allow for a conversion from +// 16 bit to 8 bit if the record conversion is active. the cs4281 has some +// issues with 8 bit capture, so the driver always captures data in 16 bit +// and then if the user requested 8 bit, converts from 16 to 8 bit. +// +static unsigned cs_copy_to_user(struct cs4281_state *s, void *dest, + unsigned *hwsrc, unsigned cnt, + unsigned *copied) +{ + 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 fmt_o=0x%x cnt=%d dest=0x%.8x\n", + s->prop_adc.fmt, + s->prop_adc.fmt_original, + (unsigned) cnt, (unsigned) dest)); + + if (cnt > s->dma_adc.dmasize) { + cnt = s->dma_adc.dmasize; + } + if (!cnt) { + *copied = 0; + return 0; + } + if (s->conversion) { + if (!s->tmpbuff) { + *copied = cnt / 2; + return 0; + } + CopySamples(s->tmpbuff, (void *) hwsrc, cnt, + (unsigned) s->prop_adc.channels, + s->prop_adc.fmt_original); + src = s->tmpbuff; + cnt = cnt / 2; + } + + if (copy_to_user(dest, 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; +} // --------------------------------------------------------------------- -static ssize_t cs4281_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_read(struct file *file, char *buffer, size_t count, + loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned swptr; int cnt; + unsigned copied = 0; - CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4281: cs4281_read()+ \n") ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, + printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count)); VALIDATE_STATE(s); if (ppos != &file->f_pos) @@ -1568,52 +2312,115 @@ if (!access_ok(VERIFY_WRITE, buffer, count)) return -EFAULT; ret = 0; +// +// "count" is the amount of bytes to read (from app), is decremented each loop +// by the amount of bytes that have been returned to the user buffer. +// "cnt" is the running total of each read from the buffer (changes each loop) +// "buffer" points to the app's buffer +// "ret" keeps a running total of the amount of bytes that have been copied +// to the user buffer. +// "copied" is the total bytes copied into the user buffer for each loop. +// while (count > 0) { + CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO + "_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n", + count, s->dma_adc.count, + s->dma_adc.swptr, + s->dma_adc.hwptr)); spin_lock_irqsave(&s->lock, flags); + + // get the current copy point of the sw buffer swptr = s->dma_adc.swptr; - cnt = s->dma_adc.dmasize-swptr; + + // cnt is the amount of unread bytes from the end of the + // hw buffer to the current sw pointer + cnt = s->dma_adc.dmasize - swptr; + + // dma_adc.count is the current total bytes that have not been read. + // if the amount of unread bytes from the current sw pointer to the + // end of the buffer is greater than the current total bytes that + // have not been read, then set the "cnt" (unread bytes) to the + // amount of unread bytes. + if (s->dma_adc.count < cnt) cnt = s->dma_adc.count; spin_unlock_irqrestore(&s->lock, flags); - if (cnt > count) - cnt = count; + // + // if we are converting from 8/16 then we need to copy + // twice the number of 16 bit bytes then 8 bit bytes. + // + if (s->conversion) { + if (cnt > (count * 2)) + cnt = (count * 2); + } else { + if (cnt > count) + cnt = count; + } + // + // "cnt" NOW is the smaller of the amount that will be read, + // and the amount that is requested in this read (or partial). + // if there are no bytes in the buffer to read, then start the + // ADC and wait for the interrupt handler to wake us up. + // if (cnt <= 0) { + + // start up the dma engine and then continue back to the top of + // the loop when wake up occurs. start_adc(s); - if (file->f_flags & O_NONBLOCK) + if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; interruptible_sleep_on(&s->dma_adc.wait); if (signal_pending(current)) return ret ? ret : -ERESTARTSYS; continue; } - if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) + // there are bytes in the buffer to read. + // copy from the hw buffer over to the user buffer. + // user buffer is designated by "buffer" + // virtual address to copy from is rawbuf+swptr + // the "cnt" is the number of bytes to read. + + 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", + s->dma_adc.dmasize, s->dma_adc.count, + (unsigned) buffer, ret)); + + if (cs_copy_to_user + (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied)) return ret ? ret : -EFAULT; swptr = (swptr + cnt) % s->dma_adc.dmasize; spin_lock_irqsave(&s->lock, flags); s->dma_adc.swptr = swptr; s->dma_adc.count -= cnt; spin_unlock_irqrestore(&s->lock, flags); - count -= cnt; - buffer += cnt; - ret += cnt; + count -= copied; + buffer += copied; + ret += copied; start_adc(s); } - CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, - printk(KERN_INFO "cs4281: cs4281_read()- %d\n",ret) ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2, + printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret)); return ret; } -static ssize_t cs4281_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_write(struct file *file, const char *buffer, + size_t count, loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned swptr; int cnt; - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4281: cs4281_write()+ \n") ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, + printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n", + count)); VALIDATE_STATE(s); if (ppos != &file->f_pos) @@ -1632,13 +2439,14 @@ s->dma_dac.swptr = s->dma_dac.hwptr; } swptr = s->dma_dac.swptr; - cnt = s->dma_dac.dmasize-swptr; + cnt = s->dma_dac.dmasize - swptr; if (s->dma_dac.count + cnt > s->dma_dac.dmasize) cnt = s->dma_dac.dmasize - s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); if (cnt > count) cnt = count; if (cnt <= 0) { + start_dac(s); if (file->f_flags & O_NONBLOCK) return ret ? ret : -EAGAIN; @@ -1660,61 +2468,79 @@ ret += cnt; start_dac(s); } - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, - printk(KERN_INFO "cs4281: cs4281_write()- %d\n",ret) ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2, + printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret)); return ret; } -static unsigned int cs4281_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cs4281_poll(struct file *file, + struct poll_table_struct *wait) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; unsigned long flags; unsigned int mask = 0; - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO "cs4281: cs4281_poll()+\n") ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO "cs4281: cs4281_poll()+\n")); VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) + if (file->f_mode & FMODE_WRITE) { + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO + "cs4281: cs4281_poll() wait on FMODE_WRITE\n")); poll_wait(file, &s->dma_dac.wait, wait); - if (file->f_mode & FMODE_READ) + } + if (file->f_mode & FMODE_READ) { + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO + "cs4281: cs4281_poll() wait on FMODE_READ\n")); poll_wait(file, &s->dma_adc.wait, wait); + } spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); - if (file->f_mode & FMODE_READ) { - if (s->dma_adc.mapped) { - if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) - mask |= POLLIN | POLLRDNORM; - } else { - if (s->dma_adc.count > 0) - mask |= POLLIN | POLLRDNORM; - } - } if (file->f_mode & FMODE_WRITE) { if (s->dma_dac.mapped) { - if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) - mask |= POLLOUT | POLLWRNORM; + if (s->dma_dac.count >= + (signed) s->dma_dac.fragsize) { + if (s->dma_dac.wakeup) + mask |= POLLOUT | POLLWRNORM; + else + mask = 0; + s->dma_dac.wakeup = 0; + } } else { - if ((signed)s->dma_dac.dmasize > s->dma_dac.count) + if ((signed) s->dma_dac.dmasize > s->dma_dac.count) mask |= POLLOUT | POLLWRNORM; } + } else if (file->f_mode & FMODE_READ) { + if (s->dma_adc.mapped) { + if (s->dma_adc.count >= + (signed) s->dma_adc.fragsize) mask |= + POLLIN | POLLRDNORM; + } else { + if (s->dma_adc.count > 0) + mask |= POLLIN | POLLRDNORM; + } } spin_unlock_irqrestore(&s->lock, flags); - CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, - printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n",mask) ); + CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4, + printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n", + mask)); return mask; } static int cs4281_mmap(struct file *file, struct vm_area_struct *vma) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; struct dmabuf *db; int ret; unsigned long size; - CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, - printk(KERN_INFO "cs4281: cs4281_mmap()+\n") ); + CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, + printk(KERN_INFO "cs4281: cs4281_mmap()+\n")); VALIDATE_STATE(s); if (vma->vm_flags & VM_WRITE) { @@ -1727,131 +2553,253 @@ db = &s->dma_adc; } else return -EINVAL; +// +// only support PLAYBACK for now +// + db = &s->dma_dac; + if (vma->vm_pgoff != 0) return -EINVAL; size = vma->vm_end - vma->vm_start; if (size > (PAGE_SIZE << db->buforder)) return -EINVAL; - if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot)) - return -EAGAIN; + if (remap_page_range + (vma->vm_start, virt_to_phys(db->rawbuf), size, + vma->vm_page_prot)) return -EAGAIN; db->mapped = 1; - CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, - printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n", - (unsigned)size) ); + CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4, + printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n", + (unsigned) size)); return 0; } -static int cs4281_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int cs4281_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; unsigned long flags; audio_buf_info abinfo; count_info cinfo; int val, mapped, ret; - - CS_DBGOUT(CS_FUNCTION, 4, - printk(KERN_INFO "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n", - (unsigned)file,cmd) ); + + CS_DBGOUT(CS_FUNCTION, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n", + (unsigned) file, cmd)); +#if CSDEBUG + printioctl(cmd); +#endif VALIDATE_STATE(s); mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) || - ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); + ((file->f_mode & FMODE_READ) && s->dma_adc.mapped); switch (cmd) { case OSS_GETVERSION: - CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO - "cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n", SOUND_VERSION) ); - return put_user(SOUND_VERSION, (int *)arg); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO + "cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n", + SOUND_VERSION)); + return put_user(SOUND_VERSION, (int *) arg); case SNDCTL_DSP_SYNC: + CS_DBGOUT(CS_IOCTL, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SYNC\n")); if (file->f_mode & FMODE_WRITE) - return drain_dac(s, 0/*file->f_flags & O_NONBLOCK*/); + return drain_dac(s, + 0 /*file->f_flags & O_NONBLOCK */ + ); return 0; case SNDCTL_DSP_SETDUPLEX: return 0; case SNDCTL_DSP_GETCAPS: - return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg); + return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | + DSP_CAP_TRIGGER | DSP_CAP_MMAP, + (int *) arg); case SNDCTL_DSP_RESET: + CS_DBGOUT(CS_IOCTL, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_RESET\n")); if (file->f_mode & FMODE_WRITE) { stop_dac(s); synchronize_irq(); - s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = - s->dma_dac.total_bytes = s->dma_dac.blocks = 0; + s->dma_dac.swptr = s->dma_dac.hwptr = + s->dma_dac.count = s->dma_dac.total_bytes = + s->dma_dac.blocks = s->dma_dac.wakeup = 0; + prog_codec(s, CS_TYPE_DAC); } if (file->f_mode & FMODE_READ) { stop_adc(s); synchronize_irq(); - s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = - s->dma_adc.total_bytes = s->dma_adc.blocks = 0; + s->dma_adc.swptr = s->dma_adc.hwptr = + s->dma_adc.count = s->dma_adc.total_bytes = + s->dma_adc.blocks = s->dma_dac.wakeup = 0; + prog_codec(s, CS_TYPE_ADC); } - prog_codec(s); return 0; case SNDCTL_DSP_SPEED: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; - if (val >= 0) { - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program sampling rates - if (val > 48000) - val = 48000; - if (val < 6300) - val = 6300; - s->rate = val; - prog_codec(s); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SPEED val=%d\n", + val)); + // + // support independent capture and playback channels + // assume that the file mode bit determines the + // direction of the data flow. + // + if (file->f_mode & FMODE_READ) { + if (val >= 0) { + stop_adc(s); + s->dma_adc.ready = 0; + // program sampling rates + if (val > 48000) + val = 48000; + if (val < 6300) + val = 6300; + s->prop_adc.rate = val; + prog_codec(s, CS_TYPE_ADC); + } + } + if (file->f_mode & FMODE_WRITE) { + if (val >= 0) { + stop_dac(s); + s->dma_dac.ready = 0; + // program sampling rates + if (val > 48000) + val = 48000; + if (val < 6300) + val = 6300; + s->prop_dac.rate = val; + prog_codec(s, CS_TYPE_DAC); + } } - return put_user(s->rate, (int *)arg); + + if (file->f_mode & FMODE_WRITE) + val = s->prop_dac.rate; + else if (file->f_mode & FMODE_READ) + val = s->prop_adc.rate; + + return put_user(val, (int *) arg); case SNDCTL_DSP_STEREO: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program channels - s->channels = val ? 2 : 1; - prog_codec(s); + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_STEREO val=%d\n", + val)); + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + s->prop_adc.channels = val ? 2 : 1; + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + s->prop_dac.channels = val ? 2 : 1; + prog_codec(s, CS_TYPE_DAC); + } return 0; case SNDCTL_DSP_CHANNELS: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_CHANNELS val=%d\n", + val)); if (val != 0) { - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program channels - s->channels = val ? 2 : 1; - prog_codec(s); + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val >= 2) + s->prop_adc.channels = 2; + else + s->prop_adc.channels = 1; + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val >= 2) + s->prop_dac.channels = 2; + else + s->prop_dac.channels = 1; + prog_codec(s, CS_TYPE_DAC); + } } - return put_user(s->channels, (int *)arg); - case SNDCTL_DSP_GETFMTS: // Returns a mask - return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg); + if (file->f_mode & FMODE_WRITE) + val = s->prop_dac.channels; + else if (file->f_mode & FMODE_READ) + val = s->prop_adc.channels; + + return put_user(val, (int *) arg); + + case SNDCTL_DSP_GETFMTS: // Returns a mask + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_GETFMT val=0x%.8x\n", + AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | + AFMT_U8)); + return put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 | + AFMT_U8, (int *) arg); - case SNDCTL_DSP_SETFMT: // Selects ONE fmt - if (get_user(val, (int *)arg)) + case SNDCTL_DSP_SETFMT: + if (get_user(val, (int *) arg)) return -EFAULT; + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SETFMT val=0x%.8x\n", + val)); if (val != AFMT_QUERY) { - stop_adc(s); - stop_dac(s); - s->dma_adc.ready = s->dma_dac.ready = 0; - // program format - if (val != AFMT_S16_LE && val != AFMT_U16_LE && - val != AFMT_S8 && val != AFMT_U8) - val = AFMT_U8; - s->fmt = val; - prog_codec(s); - } - return put_user(s->fmt, (int *)arg); + if (file->f_mode & FMODE_READ) { + stop_adc(s); + s->dma_adc.ready = 0; + if (val != AFMT_S16_LE + && val != AFMT_U16_LE && val != AFMT_S8 + && val != AFMT_U8) + val = AFMT_U8; + s->prop_adc.fmt = val; + s->prop_adc.fmt_original = s->prop_adc.fmt; + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + stop_dac(s); + s->dma_dac.ready = 0; + if (val != AFMT_S16_LE + && val != AFMT_U16_LE && val != AFMT_S8 + && val != AFMT_U8) + val = AFMT_U8; + s->prop_dac.fmt = val; + s->prop_dac.fmt_original = s->prop_dac.fmt; + prog_codec(s, CS_TYPE_DAC); + } + } else { + if (file->f_mode & FMODE_WRITE) + val = s->prop_dac.fmt_original; + else if (file->f_mode & FMODE_READ) + val = s->prop_adc.fmt_original; + } + CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_SETFMT return val=0x%.8x\n", + val)); + return put_user(val, (int *) arg); case SNDCTL_DSP_POST: + CS_DBGOUT(CS_IOCTL, 4, + printk(KERN_INFO + "cs4281: cs4281_ioctl(): DSP_POST\n")); return 0; case SNDCTL_DSP_GETTRIGGER: @@ -1860,14 +2808,15 @@ val |= PCM_ENABLE_INPUT; if (file->f_mode & s->ena & FMODE_WRITE) val |= PCM_ENABLE_OUTPUT; - return put_user(val, (int *)arg); + return put_user(val, (int *) arg); case SNDCTL_DSP_SETTRIGGER: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; if (file->f_mode & FMODE_READ) { if (val & PCM_ENABLE_INPUT) { - if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s))) + if (!s->dma_adc.ready + && (ret = prog_dmabuf_adc(s))) return ret; start_adc(s); } else @@ -1875,7 +2824,8 @@ } if (file->f_mode & FMODE_WRITE) { if (val & PCM_ENABLE_OUTPUT) { - if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s))) + if (!s->dma_dac.ready + && (ret = prog_dmabuf_dac(s))) return ret; start_dac(s); } else @@ -1886,30 +2836,55 @@ case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!(s->ena & FMODE_WRITE) && (val = prog_dmabuf_dac(s)) != 0) + if (!(s->ena & FMODE_WRITE) + && (val = prog_dmabuf_dac(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); abinfo.fragsize = s->dma_dac.fragsize; - abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; + if (s->dma_dac.mapped) + abinfo.bytes = s->dma_dac.dmasize; + else + abinfo.bytes = + s->dma_dac.dmasize - s->dma_dac.count; abinfo.fragstotal = s->dma_dac.numfrag; - abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; + CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO + "cs4281: cs4281_ioctl(): GETOSPACE .fragsize=%d .bytes=%d .fragstotal=%d .fragments=%d\n", + abinfo. + fragsize, + abinfo.bytes, + abinfo. + fragstotal, + abinfo. + fragments)); spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + return copy_to_user((void *) arg, &abinfo, + sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0) - return val; + if (!(s->ena & FMODE_READ) + && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); - abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; - abinfo.fragstotal = s->dma_adc.numfrag; - abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; + if (s->conversion) { + abinfo.fragsize = s->dma_adc.fragsize / 2; + abinfo.bytes = s->dma_adc.count / 2; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = + abinfo.bytes >> (s->dma_adc.fragshift - 1); + } else { + abinfo.fragsize = s->dma_adc.fragsize; + abinfo.bytes = s->dma_adc.count; + abinfo.fragstotal = s->dma_adc.numfrag; + abinfo.fragments = + abinfo.bytes >> s->dma_adc.fragshift; + } spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0; + return copy_to_user((void *) arg, &abinfo, + sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: file->f_flags |= O_NONBLOCK; @@ -1922,7 +2897,7 @@ cs4281_update_ptr(s); val = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + return put_user(val, (int *) arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) @@ -1930,12 +2905,30 @@ spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; - cinfo.ptr = s->dma_adc.hwptr; + if (s->dma_adc.mapped) { + cinfo.blocks = + (cinfo.bytes >> s->dma_adc.fragshift) - + s->dma_adc.blocks; + s->dma_adc.blocks = + cinfo.bytes >> s->dma_adc.fragshift; + } else { + if (s->conversion) { + cinfo.blocks = + s->dma_adc.count / + 2 >> (s->dma_adc.fragshift - 1); + } else + cinfo.blocks = + s->dma_adc.count >> s->dma_adc. + fragshift; + } + if (s->conversion) + cinfo.ptr = s->dma_adc.hwptr / 2; + else + cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) - s->dma_adc.count &= s->dma_adc.fragsize-1; + s->dma_adc.count &= s->dma_adc.fragsize - 1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) @@ -1943,65 +2936,107 @@ spin_lock_irqsave(&s->lock, flags); cs4281_update_ptr(s); cinfo.bytes = s->dma_dac.total_bytes; - if (s->dma_dac.mapped) - { - cinfo.blocks = (cinfo.bytes >> s->dma_dac.fragshift) - - s->dma_adc.blocks; - s->dma_dac.blocks = cinfo.bytes >> s->dma_dac.fragshift; - } - else - { - cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; + if (s->dma_dac.mapped) { + cinfo.blocks = + (cinfo.bytes >> s->dma_dac.fragshift) - + s->dma_dac.blocks; + s->dma_dac.blocks = + cinfo.bytes >> s->dma_dac.fragshift; + } else { + cinfo.blocks = + s->dma_dac.count >> s->dma_dac.fragshift; } cinfo.ptr = s->dma_dac.hwptr; if (s->dma_dac.mapped) - s->dma_dac.count &= s->dma_dac.fragsize-1; + s->dma_dac.count &= s->dma_dac.fragsize - 1; spin_unlock_irqrestore(&s->lock, flags); - return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)); + return copy_to_user((void *) arg, &cinfo, sizeof(cinfo)); case SNDCTL_DSP_GETBLKSIZE: if (file->f_mode & FMODE_WRITE) { if ((val = prog_dmabuf_dac(s))) return val; - return put_user(s->dma_dac.fragsize, (int *)arg); + return put_user(s->dma_dac.fragsize, (int *) arg); } if ((val = prog_dmabuf_adc(s))) return val; - return put_user(s->dma_adc.fragsize, (int *)arg); + if (s->conversion) + return put_user(s->dma_adc.fragsize / 2, + (int *) arg); + else + return put_user(s->dma_adc.fragsize, (int *) arg); case SNDCTL_DSP_SETFRAGMENT: - if (get_user(val, (int *)arg)) + if (get_user(val, (int *) arg)) return -EFAULT; - return 0; // Say OK, but do nothing. + return 0; // Say OK, but do nothing. case SNDCTL_DSP_SUBDIVIDE: - if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || - (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) - return -EINVAL; - if (get_user(val, (int *)arg)) + if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) + || (file->f_mode & FMODE_WRITE + && s->dma_dac.subdivision)) return -EINVAL; + if (get_user(val, (int *) arg)) return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) s->dma_adc.subdivision = val; - if (file->f_mode & FMODE_WRITE) + else if (file->f_mode & FMODE_WRITE) s->dma_dac.subdivision = val; return 0; case SOUND_PCM_READ_RATE: - return put_user(s->rate, (int *)arg); + if (file->f_mode & FMODE_READ) + return put_user(s->prop_adc.rate, (int *) arg); + else if (file->f_mode & FMODE_WRITE) + return put_user(s->prop_dac.rate, (int *) arg); case SOUND_PCM_READ_CHANNELS: - return put_user(s->channels, (int *)arg); + if (file->f_mode & FMODE_READ) + return put_user(s->prop_adc.channels, (int *) arg); + else if (file->f_mode & FMODE_WRITE) + return put_user(s->prop_dac.channels, (int *) arg); case SOUND_PCM_READ_BITS: - return put_user((s->fmt & (AFMT_S8|AFMT_U8)) ? 8 : 16, (int *)arg); + if (file->f_mode & FMODE_READ) + return + put_user( + (s->prop_adc. + fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16, + (int *) arg); + else if (file->f_mode & FMODE_WRITE) + return + put_user( + (s->prop_dac. + fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16, + (int *) arg); case SOUND_PCM_WRITE_FILTER: case SNDCTL_DSP_SETSYNCRO: case SOUND_PCM_READ_FILTER: return -EINVAL; +#if CSDEBUG_INTERFACE + + case SNDCTL_DSP_CS_GETDBGMASK: + return put_user(cs_debugmask, (unsigned long *) arg); + + case SNDCTL_DSP_CS_GETDBGLEVEL: + return put_user(cs_debuglevel, (unsigned long *) arg); + + case SNDCTL_DSP_CS_SETDBGMASK: + if (get_user(val, (unsigned long *) arg)) + return -EFAULT; + cs_debugmask = val; + return 0; + + case SNDCTL_DSP_CS_SETDBGLEVEL: + if (get_user(val, (unsigned long *) arg)) + return -EFAULT; + cs_debuglevel = val; + return 0; +#endif + } return mixer_ioctl(s, cmd, arg); } @@ -2009,29 +3044,36 @@ static int cs4281_release(struct inode *inode, struct file *file) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x\n", - (unsigned)inode,(unsigned)file) ); + CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, + printk(KERN_INFO + "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n", + (unsigned) inode, (unsigned) file, file->f_mode)); VALIDATE_STATE(s); - if (file->f_mode & FMODE_WRITE) - drain_dac(s, file->f_flags & O_NONBLOCK); - down(&s->open_sem); if (file->f_mode & FMODE_WRITE) { + drain_dac(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem_dac); stop_dac(s); - dealloc_dmabuf(s,&s->dma_dac); + dealloc_dmabuf(s, &s->dma_dac); + s->open_mode &= ~FMODE_WRITE; + up(&s->open_sem_dac); + wake_up(&s->open_wait_dac); + MOD_DEC_USE_COUNT; } if (file->f_mode & FMODE_READ) { + drain_adc(s, file->f_flags & O_NONBLOCK); + down(&s->open_sem_adc); stop_adc(s); - dealloc_dmabuf(s,&s->dma_adc); + dealloc_dmabuf(s, &s->dma_adc); + s->open_mode &= ~FMODE_READ; + up(&s->open_sem_adc); + wake_up(&s->open_wait_adc); + MOD_DEC_USE_COUNT; } - s->open_mode &= ~(FMODE_READ | FMODE_WRITE); - up(&s->open_sem); - wake_up(&s->open_wait); - MOD_DEC_USE_COUNT; return 0; } @@ -2040,54 +3082,102 @@ int minor = MINOR(inode->i_rdev); struct cs4281_state *s = devs; - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x\n", - (unsigned)inode,(unsigned)file) ); + CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, + printk(KERN_INFO + "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n", + (unsigned) inode, (unsigned) file, file->f_mode)); while (s && ((s->dev_audio ^ minor) & ~0xf)) s = s->next; - if (!s) - { - CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO - "cs4281: cs4281_open(): ERROR unable to find audio state struct\n") ); + if (!s) { + CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO + "cs4281: cs4281_open(): Error - unable to find audio state struct\n")); return -ENODEV; } VALIDATE_STATE(s); file->private_data = s; - - // wait for device to become free - down(&s->open_sem); - while (s->open_mode & (FMODE_READ | FMODE_WRITE)) { - if (file->f_flags & O_NONBLOCK) { - up(&s->open_sem); - return -EBUSY; + + // wait for device to become free + if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) { + CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, + printk(KERN_INFO + "cs4281: cs4281_open(): Error - must open READ and/or WRITE\n")); + return -ENODEV; + } + if (file->f_mode & FMODE_WRITE) { + down(&s->open_sem_dac); + while (s->open_mode & FMODE_WRITE) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem_dac); + return -EBUSY; + } + up(&s->open_sem_dac); + interruptible_sleep_on(&s->open_wait_dac); + + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem_dac); } - up(&s->open_sem); - interruptible_sleep_on(&s->open_wait); - if (signal_pending(current)) - return -ERESTARTSYS; - down(&s->open_sem); } - s->fmt = AFMT_U8; - s->channels = 1; - s->rate = 8000; - s->clkdiv = 96 | 0x80; - s->ena = s->endofbuffer = 0; - s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0; - s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0; - s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); - up(&s->open_sem); - MOD_INC_USE_COUNT; + if (file->f_mode & FMODE_READ) { + down(&s->open_sem_adc); + while (s->open_mode & FMODE_READ) { + if (file->f_flags & O_NONBLOCK) { + up(&s->open_sem_adc); + return -EBUSY; + } + up(&s->open_sem_adc); + interruptible_sleep_on(&s->open_wait_adc); - if (prog_dmabuf_dac(s) || prog_dmabuf_adc(s)) { - - printk(KERN_ERR "cs4281: Program dmabufs failed.\n"); - cs4281_release(inode, file); - - return -ENOMEM; - } - prog_codec(s); - CS_DBGOUT(CS_INIT | CS_FUNCTION | CS_OPEN, 2, - printk(KERN_INFO "cs4281: cs4281_open()- 0\n") ); + if (signal_pending(current)) + return -ERESTARTSYS; + down(&s->open_sem_adc); + } + } + s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE); + if (file->f_mode & FMODE_READ) { + s->prop_adc.fmt = AFMT_U8; + s->prop_adc.fmt_original = s->prop_adc.fmt; + s->prop_adc.channels = 1; + s->prop_adc.rate = 8000; + s->prop_adc.clkdiv = 96 | 0x80; + s->conversion = 0; + s->ena &= ~FMODE_READ; + s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = + s->dma_adc.subdivision = 0; + up(&s->open_sem_adc); + MOD_INC_USE_COUNT; + + if (prog_dmabuf_adc(s)) { + CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR + "cs4281: adc Program dmabufs failed.\n")); + cs4281_release(inode, file); + return -ENOMEM; + } + prog_codec(s, CS_TYPE_ADC); + } + if (file->f_mode & FMODE_WRITE) { + s->prop_dac.fmt = AFMT_U8; + s->prop_dac.fmt_original = s->prop_dac.fmt; + s->prop_dac.channels = 1; + s->prop_dac.rate = 8000; + s->prop_dac.clkdiv = 96 | 0x80; + s->conversion = 0; + s->ena &= ~FMODE_WRITE; + s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = + s->dma_dac.subdivision = 0; + up(&s->open_sem_dac); + MOD_INC_USE_COUNT; + + if (prog_dmabuf_dac(s)) { + CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR + "cs4281: dac Program dmabufs failed.\n")); + cs4281_release(inode, file); + return -ENOMEM; + } + prog_codec(s, CS_TYPE_DAC); + } + CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, + printk(KERN_INFO "cs4281: cs4281_open()- 0\n")); return 0; } @@ -2095,15 +3185,15 @@ // ****************************************************************************************** // Wave (audio) file operations struct. // ****************************************************************************************** -static /*const*/ struct file_operations cs4281_audio_fops = { - llseek: cs4281_llseek, - read: cs4281_read, - write: cs4281_write, - poll: cs4281_poll, - ioctl: cs4281_ioctl, - mmap: cs4281_mmap, - open: cs4281_open, - release: cs4281_release, +static /*const */ struct file_operations cs4281_audio_fops = { + llseek:cs4281_llseek, + read:cs4281_read, + write:cs4281_write, + poll:cs4281_poll, + ioctl:cs4281_ioctl, + mmap:cs4281_mmap, + open:cs4281_open, + release:cs4281_release, }; // --------------------------------------------------------------------- @@ -2116,8 +3206,8 @@ unsigned temp1; wake = 0; - while (!(readl(s->pBA0+ BA0_MIDSR) & 0x80)) { - ch = readl(s->pBA0+BA0_MIDRP); + while (!(readl(s->pBA0 + BA0_MIDSR) & 0x80)) { + ch = readl(s->pBA0 + BA0_MIDRP); if (s->midi.icnt < MIDIINBUF) { s->midi.ibuf[s->midi.iwr] = ch; s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF; @@ -2128,12 +3218,12 @@ if (wake) wake_up(&s->midi.iwait); wake = 0; - while (!(readl(s->pBA0+ BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) { - temp1 = ( s->midi.obuf[s->midi.ord] ) & 0x000000ff; - writel(temp1, s->pBA0+BA0_MIDWP); + while (!(readl(s->pBA0 + BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) { + temp1 = (s->midi.obuf[s->midi.ord]) & 0x000000ff; + writel(temp1, s->pBA0 + BA0_MIDWP); s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF; s->midi.ocnt--; - if (s->midi.ocnt < MIDIOUTBUF-16) + if (s->midi.ocnt < MIDIOUTBUF - 16) wake = 1; } if (wake) @@ -2144,48 +3234,32 @@ static void cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - struct cs4281_state *s = (struct cs4281_state *)dev_id; + struct cs4281_state *s = (struct cs4281_state *) dev_id; unsigned int temp1; // fastpath out, to ease interrupt sharing - temp1 = readl(s->pBA0+BA0_HISR); // Get Int Status reg. + temp1 = readl(s->pBA0 + BA0_HISR); // Get Int Status reg. - CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO - "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n",temp1) ); + CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO + "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n", + temp1)); - if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) { // If not DMA or MIDI int, - writel(HICR_IEV| HICR_CHGM, s->pBA0+BA0_HICR); // reenable interrupts - CS_DBGOUT(CS_INTERRUPT, 4, printk(KERN_INFO - "cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n") ); - return; // and return. + if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) { // If not DMA or MIDI int, + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // reenable interrupts + CS_DBGOUT(CS_INTERRUPT, 4, printk(KERN_INFO + "cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n")); + return; // and return. } - - if(temp1 & HISR_DMA0) // If play interrupt, - readl(s->pBA0+BA0_HDSR0); // clear the source. - if(temp1 & HISR_DMA1) // Same for play. - readl(s->pBA0+BA0_HDSR1); - writel(HICR_IEV| HICR_CHGM, s->pBA0+BA0_HICR); // Local EOI - + if (temp1 & HISR_DMA0) // If play interrupt, + readl(s->pBA0 + BA0_HDSR0); // clear the source. + + if (temp1 & HISR_DMA1) // Same for play. + readl(s->pBA0 + BA0_HDSR1); + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Local EOI + spin_lock(&s->lock); - // - // ok, at this point we assume that the fifos have been filled - // with silence and so we now turn off the DMA engine. - // if FMODE_WRITE is set that means that some thread - // attempted to start_dac, which probably means that an open - // occurred, so do not stop the dac in this case. - // - if(s->endofbuffer && !(s->ena & FMODE_WRITE)) - { - CS_DBGOUT(CS_INTERRUPT, 2, printk(KERN_INFO - "cs4281: cs4281_interrupt() stopping play DMA\n") ); - writel(temp1|DCRn_MSK, s->pBA0+BA0_DCR0); // Stop Play DMA - s->endofbuffer = 0; - } - else - { - cs4281_update_ptr(s); - } + cs4281_update_ptr(s); cs4281_handle_midi(s); spin_unlock(&s->lock); } @@ -2194,22 +3268,24 @@ static void cs4281_midi_timer(unsigned long data) { - struct cs4281_state *s = (struct cs4281_state *)data; + struct cs4281_state *s = (struct cs4281_state *) data; unsigned long flags; spin_lock_irqsave(&s->lock, flags); cs4281_handle_midi(s); spin_unlock_irqrestore(&s->lock, flags); - s->midi.timer.expires = jiffies+1; + s->midi.timer.expires = jiffies + 1; add_timer(&s->midi.timer); } // --------------------------------------------------------------------- -static ssize_t cs4281_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_midi_read(struct file *file, char *buffer, + size_t count, loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned ptr; @@ -2253,9 +3329,11 @@ } -static ssize_t cs4281_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos) +static ssize_t cs4281_midi_write(struct file *file, const char *buffer, + size_t count, loff_t * ppos) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; ssize_t ret; unsigned long flags; unsigned ptr; @@ -2304,9 +3382,11 @@ } -static unsigned int cs4281_midi_poll(struct file *file, struct poll_table_struct *wait) +static unsigned int cs4281_midi_poll(struct file *file, + struct poll_table_struct *wait) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; unsigned long flags; unsigned int mask = 0; @@ -2333,7 +3413,7 @@ { int minor = MINOR(inode->i_rdev); struct cs4281_state *s = devs; - unsigned long flags,temp1; + unsigned long flags, temp1; while (s && s->dev_midi != minor) s = s->next; if (!s) @@ -2357,16 +3437,16 @@ if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { s->midi.ird = s->midi.iwr = s->midi.icnt = 0; s->midi.ord = s->midi.owr = s->midi.ocnt = 0; - writel(1, s->pBA0+BA0_MIDCR); // Reset the interface. - writel(0, s->pBA0+BA0_MIDCR); // Return to normal mode. + writel(1, s->pBA0 + BA0_MIDCR); // Reset the interface. + writel(0, s->pBA0 + BA0_MIDCR); // Return to normal mode. s->midi.ird = s->midi.iwr = s->midi.icnt = 0; - writel(0x0000000f, s->pBA0+BA0_MIDCR); // Enable transmit, record, ints. - temp1 = readl(s->pBA0+BA0_HIMR); - writel(temp1 & 0xffbfffff, s->pBA0+BA0_HIMR); // Enable midi int. recognition. - writel(HICR_IEV | HICR_CHGM, s->pBA0+BA0_HICR); // Enable interrupts + writel(0x0000000f, s->pBA0 + BA0_MIDCR); // Enable transmit, record, ints. + temp1 = readl(s->pBA0 + BA0_HIMR); + writel(temp1 & 0xffbfffff, s->pBA0 + BA0_HIMR); // Enable midi int. recognition. + writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR); // Enable interrupts init_timer(&s->midi.timer); - s->midi.timer.expires = jiffies+1; - s->midi.timer.data = (unsigned long)s; + s->midi.timer.expires = jiffies + 1; + s->midi.timer.data = (unsigned long) s; s->midi.timer.function = cs4281_midi_timer; add_timer(&s->midi.timer); } @@ -2377,7 +3457,10 @@ s->midi.ord = s->midi.owr = s->midi.ocnt = 0; } spin_unlock_irqrestore(&s->lock, flags); - s->open_mode |= (file->f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | FMODE_MIDI_WRITE); + s->open_mode |= + (file-> + f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ | + FMODE_MIDI_WRITE); up(&s->open_sem); MOD_INC_USE_COUNT; return 0; @@ -2386,7 +3469,8 @@ static int cs4281_midi_release(struct inode *inode, struct file *file) { - struct cs4281_state *s = (struct cs4281_state *)file->private_data; + struct cs4281_state *s = + (struct cs4281_state *) file->private_data; DECLARE_WAITQUEUE(wait, current); unsigned long flags; unsigned count, tmo; @@ -2394,9 +3478,9 @@ VALIDATE_STATE(s); if (file->f_mode & FMODE_WRITE) { - current->state = TASK_INTERRUPTIBLE; add_wait_queue(&s->midi.owait, &wait); for (;;) { + set_current_state(TASK_INTERRUPTIBLE); spin_lock_irqsave(&s->lock, flags); count = s->midi.ocnt; spin_unlock_irqrestore(&s->lock, flags); @@ -2411,16 +3495,19 @@ } tmo = (count * HZ) / 3100; if (!schedule_timeout(tmo ? : 1) && tmo) - printk(KERN_DEBUG "cs4281: midi timed out??\n"); + printk(KERN_DEBUG + "cs4281: midi timed out??\n"); } remove_wait_queue(&s->midi.owait, &wait); current->state = TASK_RUNNING; } down(&s->open_sem); - s->open_mode &= (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ|FMODE_MIDI_WRITE); + s->open_mode &= + (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ | + FMODE_MIDI_WRITE); spin_lock_irqsave(&s->lock, flags); if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) { - writel(0, s->pBA0+BA0_MIDCR); // Disable Midi interrupts. + writel(0, s->pBA0 + BA0_MIDCR); // Disable Midi interrupts. del_timer(&s->midi.timer); } spin_unlock_irqrestore(&s->lock, flags); @@ -2433,20 +3520,20 @@ // ****************************************************************************************** // Midi file operations struct. // ****************************************************************************************** -static /*const*/ struct file_operations cs4281_midi_fops = { - llseek: cs4281_llseek, - read: cs4281_midi_read, - write: cs4281_midi_write, - poll: cs4281_midi_poll, - open: cs4281_midi_open, - release: cs4281_midi_release, +static /*const */ struct file_operations cs4281_midi_fops = { + llseek:cs4281_llseek, + read:cs4281_midi_read, + write:cs4281_midi_write, + poll:cs4281_midi_poll, + open:cs4281_midi_open, + release:cs4281_midi_release, }; // --------------------------------------------------------------------- // maximum number of devices -#define NR_DEVICE 8 // Only eight devices supported currently. +#define NR_DEVICE 8 // Only eight devices supported currently. // --------------------------------------------------------------------- @@ -2454,127 +3541,144 @@ int mixch; int vol; } initvol[] __initdata = { - { SOUND_MIXER_WRITE_VOLUME, 0x4040 }, - { SOUND_MIXER_WRITE_PCM, 0x4040 }, - { SOUND_MIXER_WRITE_SYNTH, 0x4040 }, - { SOUND_MIXER_WRITE_CD, 0x4040 }, - { SOUND_MIXER_WRITE_LINE, 0x4040 }, - { SOUND_MIXER_WRITE_LINE1, 0x4040 }, - { SOUND_MIXER_WRITE_RECLEV, 0x0000 }, - { SOUND_MIXER_WRITE_SPEAKER, 0x4040 }, - { SOUND_MIXER_WRITE_MIC, 0x0000 } + + { + SOUND_MIXER_WRITE_VOLUME, 0x4040}, { + SOUND_MIXER_WRITE_PCM, 0x4040}, { + SOUND_MIXER_WRITE_SYNTH, 0x4040}, { + SOUND_MIXER_WRITE_CD, 0x4040}, { + SOUND_MIXER_WRITE_LINE, 0x4040}, { + SOUND_MIXER_WRITE_LINE1, 0x4040}, { + SOUND_MIXER_WRITE_RECLEV, 0x0000}, { + SOUND_MIXER_WRITE_SPEAKER, 0x4040}, { + SOUND_MIXER_WRITE_MIC, 0x0000} }; -static int __devinit cs4281_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid) +static int __devinit cs4281_probe(struct pci_dev *pcidev, + const struct pci_device_id *pciid) { struct cs4281_state *s; dma_addr_t dma_mask; mm_segment_t fs; int i, val, index = 0; unsigned int temp1, temp2; - - CS_DBGOUT(CS_INIT, 2, printk(KERN_INFO "cs4281: probe()+\n") ); + + CS_DBGOUT(CS_FUNCTION | CS_INIT, 2, + printk(KERN_INFO "cs4281: probe()+\n")); if (!RSRCISMEMORYREGION(pcidev, 0) || - !RSRCISMEMORYREGION(pcidev, 1)) - { + !RSRCISMEMORYREGION(pcidev, 1)) { CS_DBGOUT(CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe()- Memory region not assigned\n") ); + printk(KERN_ERR + "cs4281: probe()- Memory region not assigned\n")); return -1; } if (pcidev->irq == 0) { CS_DBGOUT(CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() IRQ not assigned\n") ); + printk(KERN_ERR + "cs4281: probe() IRQ not assigned\n")); return -1; - } + } if (!pci_dma_supported(pcidev, 0xffffffff)) { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n") ); + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n")); return -1; - } - dma_mask = 0xffffffff; /* this enables playback and recording */ + } + dma_mask = 0xffffffff; /* this enables playback and recording */ if (!(s = kmalloc(sizeof(struct cs4281_state), GFP_KERNEL))) { - CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR - "cs4281: probe() no memory for state struct.\n") ); + CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR + "cs4281: probe() no memory for state struct.\n")); return -1; } memset(s, 0, sizeof(struct cs4281_state)); init_waitqueue_head(&s->dma_adc.wait); init_waitqueue_head(&s->dma_dac.wait); init_waitqueue_head(&s->open_wait); + init_waitqueue_head(&s->open_wait_adc); + init_waitqueue_head(&s->open_wait_dac); init_waitqueue_head(&s->midi.iwait); init_waitqueue_head(&s->midi.owait); init_MUTEX(&s->open_sem); + init_MUTEX(&s->open_sem_adc); + init_MUTEX(&s->open_sem_dac); spin_lock_init(&s->lock); s->pBA0phys = RSRCADDRESS(pcidev, 0); s->pBA1phys = RSRCADDRESS(pcidev, 1); - s->pBA0 = ioremap_nocache(s->pBA0phys, 4096); // Convert phys - s->pBA1 = ioremap_nocache(s->pBA1phys, 65536); // to linear. - temp1 = readl(s->pBA0+ BA0_PCICFG00); - temp2 = readl(s->pBA0+ BA0_PCICFG04); - - CS_DBGOUT(CS_INIT, 2, - printk(KERN_INFO "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n", - (unsigned)temp1,(unsigned)temp2,(unsigned)s->pBA0,(unsigned)s->pBA1) ); - - CS_DBGOUT(CS_INIT, 2, - printk(KERN_INFO "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n", - (unsigned)s->pBA0phys,(unsigned)s->pBA1phys) ); + s->pBA0 = ioremap_nocache(s->pBA0phys, 4096); // Convert phys + s->pBA1 = ioremap_nocache(s->pBA1phys, 65536); // to linear. + temp1 = readl(s->pBA0 + BA0_PCICFG00); + temp2 = readl(s->pBA0 + BA0_PCICFG04); + + CS_DBGOUT(CS_INIT, 2, + printk(KERN_INFO + "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n", + (unsigned) temp1, (unsigned) temp2, + (unsigned) s->pBA0, (unsigned) s->pBA1)); + + CS_DBGOUT(CS_INIT, 2, + printk(KERN_INFO + "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n", + (unsigned) s->pBA0phys, (unsigned) s->pBA1phys)); temp1 = cs4281_hw_init(s); - if(temp1){ - CS_DBGOUT(CS_ERROR | CS_INIT, 1, - printk(KERN_ERR "cs4281: cs4281_hw_init() failed. Skipping part.\n") ); + if (temp1) { + CS_DBGOUT(CS_ERROR | CS_INIT, 1, + printk(KERN_ERR + "cs4281: cs4281_hw_init() failed. Skipping part.\n")); return -1; - } + } s->magic = CS4281_MAGIC; s->pcidev = pcidev; s->irq = pcidev->irq; - if (pci_enable_device(pcidev)) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: pci_enable_device() failed\n") ); + if (pci_enable_device(pcidev)) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: pci_enable_device() failed\n")); goto err_irq; } - if(request_irq(s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)){ - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: irq %u in use\n", s->irq) ); + if (request_irq + (s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR "cs4281: irq %u in use\n", + s->irq)); goto err_irq; } - if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) < 0) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() register_sound_dsp() failed.\n") ); + if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) < + 0) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: probe() register_sound_dsp() failed.\n")); goto err_dev1; } - if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) < 0) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() register_sound_mixer() failed.\n") ); + if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) < + 0) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: probe() register_sound_mixer() failed.\n")); goto err_dev2; } - if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0) - { - CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_ERR "cs4281: probe() register_sound_midi() failed.\n") ); + if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0) { + CS_DBGOUT(CS_INIT | CS_ERROR, 1, + printk(KERN_ERR + "cs4281: probe() register_sound_midi() failed.\n")); goto err_dev3; } - - pci_set_master(pcidev); // enable bus mastering + + pci_set_master(pcidev); // enable bus mastering fs = get_fs(); set_fs(KERNEL_DS); val = SOUND_MASK_LINE; - mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val); - for (i = 0; i < sizeof(initvol)/sizeof(initvol[0]); i++) { + mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val); + for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) { val = initvol[i].vol; - mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val); + mixer_ioctl(s, initvol[i].mixch, (unsigned long) &val); } - val = 1; // enable mic preamp - mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long)&val); + val = 1; // enable mic preamp + mixer_ioctl(s, SOUND_MIXER_PRIVATE1, (unsigned long) &val); set_fs(fs); - + // queue it for later freeing s->next = devs; pcidev->driver_data = s; @@ -2583,32 +3687,33 @@ index++; return 0; -err_dev3: + err_dev3: unregister_sound_mixer(s->dev_mixer); -err_dev2: + err_dev2: unregister_sound_dsp(s->dev_audio); -err_dev1: + err_dev1: free_irq(s->irq, s); -err_irq: + err_irq: kfree(s); - if (!devs) - { + if (!devs) { CS_DBGOUT(CS_INIT | CS_ERROR, 1, - printk(KERN_INFO "cs4281: probe()- no device allocated\n") ); + printk(KERN_INFO + "cs4281: probe()- no device allocated\n")); return -ENODEV; } CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: probe()- device allocated successfully\n") ); + printk(KERN_INFO + "cs4281: probe()- device allocated successfully\n")); return 0; -} // probe_cs4281 +} // probe_cs4281 // --------------------------------------------------------------------- static void __devinit cs4281_remove(struct pci_dev *dev) { - struct cs4281_state *s = (struct cs4281_state *)dev->driver_data; + struct cs4281_state *s = (struct cs4281_state *) dev->driver_data; // stop DMA controller synchronize_irq(); free_irq(s->irq, s); @@ -2616,44 +3721,51 @@ unregister_sound_mixer(s->dev_mixer); unregister_sound_midi(s->dev_midi); kfree(s); - dev->driver_data = NULL; - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: cs4281_remove(): remove successful\n") ); + dev->driver_data = NULL; + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: cs4281_remove(): remove successful\n")); } static struct pci_device_id id_table[] __devinitdata = { - { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281, PCI_ANY_ID, PCI_ANY_ID, 0, 0 }, - { 0, } + + {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281, + PCI_ANY_ID, PCI_ANY_ID, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, id_table); static struct pci_driver cs4281_driver = { - name: "cs4281", - id_table: id_table, - probe: cs4281_probe, - remove: cs4281_remove + name:"cs4281", + id_table:id_table, + probe:cs4281_probe, + remove:cs4281_remove }; static int __init init_cs4281(void) { - - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: init_cs4281()+ \n") ); - if (!pci_present()) /* No PCI bus in this machine! */ - { - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: init_cs4281()- no pci bus found\n") ); + + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: init_cs4281()+ \n")); + if (!pci_present()) { /* No PCI bus in this machine! */ + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: init_cs4281()- no pci bus found\n")); return -ENODEV; } - printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " " __DATE__ "\n", - CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION, CS4281_ARCH); + printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " " + __DATE__ "\n", CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION, + CS4281_ARCH); if (!pci_register_driver(&cs4281_driver)) { pci_unregister_driver(&cs4281_driver); - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: init_cs4281()- unable to register pci device \n") ); + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO + "cs4281: init_cs4281()- unable to register pci device \n")); return -ENODEV; } - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO "cs4281: init_cs4281()- 0\n") ); + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: init_cs4281()- 0\n")); return 0; } @@ -2667,12 +3779,11 @@ static void __exit cleanup_cs4281(void) { pci_unregister_driver(&cs4281_driver); - CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, - printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n") ); + CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, + printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n")); } // --------------------------------------------------------------------- module_init(init_cs4281); module_exit(cleanup_cs4281); - diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/cs461x_image.h linux/drivers/sound/cs461x_image.h --- v2.4.0-test10/linux/drivers/sound/cs461x_image.h Tue Aug 22 11:31:05 2000 +++ linux/drivers/sound/cs461x_image.h Sat Nov 11 18:33:13 2000 @@ -1,4 +1,4 @@ -struct BA1struct BA1Struct = { +struct BA1struct BA1Struct __initdata = { {{ 0x00000000, 0x00003000 },{ 0x00010000, 0x00003800 },{ 0x00020000, 0x00007000 }}, {0x00000000,0x00000000,0x00000000,0x00000000, 0x00000000,0x00000000,0x00000000,0x00000000, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c --- v2.4.0-test10/linux/drivers/sound/cs46xx.c Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/cs46xx.c Sat Nov 11 18:33:13 2000 @@ -25,7 +25,9 @@ * 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 */ #include @@ -1999,7 +2001,7 @@ /* Boot the card */ -static void cs461x_download(struct cs_card *card, u32 *src, unsigned long offset, unsigned long len) +static void __init cs461x_download(struct cs_card *card, u32 *src, unsigned long offset, unsigned long len) { unsigned long counter; void *dst; @@ -2024,7 +2026,7 @@ #include "cs461x_image.h" -static void cs461x_download_image(struct cs_card *card) +static void __init cs461x_download_image(struct cs_card *card) { int idx; unsigned long offset = 0; @@ -2240,7 +2242,7 @@ -static int cs_hardware_init(struct cs_card *card) +static int __init cs_hardware_init(struct cs_card *card) { unsigned long end_time; unsigned int tmp; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/dmasound/dmasound.h linux/drivers/sound/dmasound/dmasound.h --- v2.4.0-test10/linux/drivers/sound/dmasound/dmasound.h Tue Apr 25 17:58:46 2000 +++ linux/drivers/sound/dmasound/dmasound.h Tue Nov 7 10:59:43 2000 @@ -47,7 +47,6 @@ #define MAX_BUFSIZE 128 /* Limit for Amiga in KB */ -#define arraysize(x) (sizeof(x)/sizeof(*(x))) #define min(x, y) ((x) < (y) ? (x) : (y)) #define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff)) #define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff)) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/dmasound/dmasound_atari.c linux/drivers/sound/dmasound/dmasound_atari.c --- v2.4.0-test10/linux/drivers/sound/dmasound/dmasound_atari.c Tue Apr 25 17:58:46 2000 +++ linux/drivers/sound/dmasound/dmasound_atari.c Tue Nov 7 10:59:43 2000 @@ -9,6 +9,7 @@ #include +#include #include #include #include @@ -895,7 +896,7 @@ /* search a frequency that fits into the allowed error range */ idx = -1; - for (i = 0; i < arraysize(freq); i++) + for (i = 0; i < ARRAY_SIZE(freq); i++) /* this isn't as much useful for a TT than for a Falcon, but * then it doesn't hurt very much to implement it for a TT too. */ @@ -1021,7 +1022,7 @@ /* search a frequency that fits into the allowed error range */ idx = -1; - for (i = 0; i < arraysize(freq); i++) + for (i = 0; i < ARRAY_SIZE(freq); i++) /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would * be playable without expanding, but that now a kernel runtime * option diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/dmasound/dmasound_core.c linux/drivers/sound/dmasound/dmasound_core.c --- v2.4.0-test10/linux/drivers/sound/dmasound/dmasound_core.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sound/dmasound/dmasound_core.c Sat Nov 11 18:19:56 2000 @@ -936,6 +936,7 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg) { + int val; u_long fmt; int data; int size, nbufs; @@ -1013,7 +1014,7 @@ } else size = write_sq.bufSize; sq_setup(&write_sq, write_sq.numBufs, nbufs, size); - return 0; + return IOCTL_OUT(arg,write_sq.bufSize | write_sq.numBufs << 16); case SNDCTL_DSP_GETOSPACE: info.fragments = write_sq.max_active - write_sq.count; info.fragstotal = write_sq.max_active; @@ -1022,6 +1023,9 @@ if (copy_to_user((void *)arg, &info, sizeof(info))) return -EFAULT; return 0; + case SNDCTL_DSP_GETCAPS: + val = 1; /* Revision level of this ioctl() */ + return IOCTL_OUT(arg,val); default: return mixer_ioctl(inode, file, cmd, arg); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/emu10k1/emu_wrapper.h linux/drivers/sound/emu10k1/emu_wrapper.h --- v2.4.0-test10/linux/drivers/sound/emu10k1/emu_wrapper.h Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/emu10k1/emu_wrapper.h Tue Nov 7 11:09:19 2000 @@ -1,8 +1,8 @@ #ifndef __EMU_WRAPPER_H #define __EMU_WRAPPER_H -#include +#define vma_get_pgoff(v) ((v)->vm_pgoff) -#define PCI_SET_DMA_MASK(pdev,mask) (((pdev)->dma_mask) = (mask)) +#define PCI_SET_DMA_MASK(pdev,mask) (((pdev)->dma_mask) = (mask)) #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c --- v2.4.0-test10/linux/drivers/sound/es1370.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/es1370.c Thu Nov 16 12:51:28 2000 @@ -898,9 +898,9 @@ } if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); - if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { + if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ return put_user(s->mix.recsrc, (int *)arg); @@ -937,7 +937,7 @@ return put_user(s->mix.vol[mixtable[i].volidx], (int *)arg); } } - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c --- v2.4.0-test10/linux/drivers/sound/esssolo1.c Sun Oct 8 10:50:26 2000 +++ linux/drivers/sound/esssolo1.c Thu Nov 16 12:51:28 2000 @@ -725,9 +725,9 @@ } if (cmd == OSS_GETVERSION) return put_user(SOUND_VERSION, (int *)arg); - if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { + if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ return put_user(mixer_src[read_mixer(s, 0x1c) & 7], (int *)arg); @@ -756,7 +756,7 @@ return put_user(s->mix.vol[vidx-1], (int *)arg); } } - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/gus_midi.c linux/drivers/sound/gus_midi.c --- v2.4.0-test10/linux/drivers/sound/gus_midi.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/gus_midi.c Sun Nov 12 20:35:35 2000 @@ -9,7 +9,13 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * 11-10-2000 Bartlomiej Zolnierkiewicz + * Added __init to gus_midi_init() */ + +#include "linux/init.h" #include "sound_config.h" #include "gus.h" @@ -199,7 +205,7 @@ buffer_status: gus_midi_buffer_status, }; -void gus_midi_init(struct address_info *hw_config) +void __init gus_midi_init(struct address_info *hw_config) { int dev = sound_alloc_mididev(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c --- v2.4.0-test10/linux/drivers/sound/gus_wave.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/gus_wave.c Sun Nov 12 20:35:35 2000 @@ -14,9 +14,10 @@ * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) * Frank van de Pol : Fixed GUS MAX interrupt handling. Enabled simultanious * usage of CS4231A codec, GUS wave and MIDI for GUS MAX. + * Bartlomiej Zolnierkiewicz : added some __init/__exit */ - +#include #include #define GUSPNP_AUTODETECT @@ -853,7 +854,7 @@ } -static void pnp_mem_init(void) +static void __init pnp_mem_init(void) { #include "iwmem.h" #define CHUNK_SIZE (256*1024) @@ -1022,7 +1023,7 @@ gus_write8(0x19, (gus_read8(0x19) | 0x01) & ~0x02); } -int gus_wave_detect(int baseaddr) +int __init gus_wave_detect(int baseaddr) { unsigned long i, max_mem = 1024L; unsigned long loc; @@ -2901,7 +2902,7 @@ ioctl: gus_default_mixer_ioctl }; -static int gus_default_mixer_init(void) +static int __init gus_default_mixer_init(void) { int n; @@ -2926,7 +2927,7 @@ return n; } -void gus_wave_init(struct address_info *hw_config) +void __init gus_wave_init(struct address_info *hw_config) { unsigned long flags; unsigned char val; @@ -3167,7 +3168,7 @@ } } -void gus_wave_unload(struct address_info *hw_config) +void __exit gus_wave_unload(struct address_info *hw_config) { #ifdef CONFIG_SOUND_GUSMAX if (have_gus_max) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c --- v2.4.0-test10/linux/drivers/sound/i810_audio.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sound/i810_audio.c Wed Nov 8 17:09:50 2000 @@ -14,6 +14,11 @@ * Analog Devices (A major AC97 codec maker) * Intel Corp (you've probably heard of them already) * + * AC97 clues and assistance provided by + * Analog Devices + * Zach 'Fufu' Brown + * Jeff Garzik + * * 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 @@ -96,7 +101,7 @@ #endif static int ftsodell=0; -static int clocking=48000; +static unsigned int clocking=48000; #define ADC_RUNNING 1 @@ -377,7 +382,7 @@ static unsigned int i810_set_dac_rate(struct i810_state * state, unsigned int rate) { struct dmabuf *dmabuf = &state->dmabuf; - u16 dacp, rp; + u32 dacp; struct ac97_codec *codec=state->card->ac97_codec[0]; if(!(state->card->ac97_features&0x0001)) @@ -403,22 +408,18 @@ if(rate < 8000) rate = 8000; - /* Power down the DAC */ - dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0200); - - /* Load the rate and read the effective rate */ - i810_ac97_set(codec, AC97_PCM_FRONT_DAC_RATE, rate); - rp=i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE); - -// printk("DAC rate set to %d Returned %d\n", -// rate, (int)rp); - - rate=(rp * 48000) / clocking; - - /* Power it back up */ - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); - + if(rate != i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE)) + { + /* Power down the DAC */ + dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); + i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0200); + /* Load the rate and read the effective rate */ + i810_ac97_set(codec, AC97_PCM_FRONT_DAC_RATE, rate); + rate=i810_ac97_get(codec, AC97_PCM_FRONT_DAC_RATE); + /* Power it back up */ + i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); + } + rate=(rate * 48000) / clocking; dmabuf->rate = rate; #ifdef DEBUG printk("i810_audio: called i810_set_dac_rate : rate = %d\n", rate); @@ -431,7 +432,7 @@ static unsigned int i810_set_adc_rate(struct i810_state * state, unsigned int rate) { struct dmabuf *dmabuf = &state->dmabuf; - u16 dacp, rp; + u32 dacp; struct ac97_codec *codec=state->card->ac97_codec[0]; if(!(state->card->ac97_features&0x0001)) @@ -457,30 +458,23 @@ if(rate < 8000) rate = 8000; - - /* Power down the ADC */ - dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0100); - - /* Load the rate and read the effective rate */ - i810_ac97_set(codec, AC97_PCM_LR_DAC_RATE, rate); - rp=i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE); - -// printk("ADC rate set to %d Returned %d\n", -// rate, (int)rp); - - rate = (rp * 48000) / clocking; - - /* Power it back up */ - i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); - + if(rate != i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE)) + { + /* Power down the ADC */ + dacp=i810_ac97_get(codec, AC97_POWER_CONTROL); + i810_ac97_set(codec, AC97_POWER_CONTROL, dacp|0x0100); + /* Load the rate and read the effective rate */ + i810_ac97_set(codec, AC97_PCM_LR_DAC_RATE, rate); + rate=i810_ac97_get(codec, AC97_PCM_LR_DAC_RATE); + /* Power it back up */ + i810_ac97_set(codec, AC97_POWER_CONTROL, dacp); + } + rate = (rate * 48000) / clocking; dmabuf->rate = rate; #ifdef DEBUG printk("i810_audio: called i810_set_adc_rate : rate = %d\n", rate); #endif - return rate; - } /* prepare channel attributes for playback */ @@ -1726,10 +1720,37 @@ int ready_2nd = 0; struct ac97_codec *codec; u16 eid; + int i=0; + u32 reg; - outl(0, card->iobase + GLOB_CNT); - udelay(500); - outl(1<<1, card->iobase + GLOB_CNT); + reg = inl(card->iobase + GLOB_CNT); + + if((reg&2)==0) /* Cold required */ + reg|=2; + else + reg|=4; /* Warm */ + + reg&=~8; /* ACLink on */ + outl(reg , card->iobase + GLOB_CNT); + + while(i<10) + { + if((inl(card->iobase+GLOB_CNT)&4)==0) + break; + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ/20); + i++; + } + if(i==10) + { + printk(KERN_ERR "i810_audio: AC'97 reset failed.\n"); + return 0; + } + + current->state = TASK_UNINTERRUPTIBLE; + schedule_timeout(HZ/5); + + inw(card->ac97base); for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/ics2101.c linux/drivers/sound/ics2101.c --- v2.4.0-test10/linux/drivers/sound/ics2101.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/ics2101.c Sun Nov 12 20:35:35 2000 @@ -12,7 +12,9 @@ * * * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Bartlomiej Zolnierkiewicz : added __init to ics2101_mixer_init() */ +#include #include "sound_config.h" #include @@ -212,8 +214,7 @@ ioctl: ics2101_mixer_ioctl }; -int -ics2101_mixer_init(void) +int __init ics2101_mixer_init(void) { int i; int n; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/iwmem.h linux/drivers/sound/iwmem.h --- v2.4.0-test10/linux/drivers/sound/iwmem.h Tue Sep 30 08:46:45 1997 +++ linux/drivers/sound/iwmem.h Sat Nov 11 18:33:13 2000 @@ -1,5 +1,5 @@ /* - * sound/iwmem.c + * sound/iwmem.h * * DRAM size encoding table for AMD Interwave chip. */ @@ -9,12 +9,15 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * Bartlomiej Zolnierkiewicz : added __initdata to mem_decode */ #define K 1024 #define M (1024*K) -static int mem_decode[][4] = +static int mem_decode[][4] __initdata = { /* Bank0 Bank1 Bank2 Bank3 Encoding bits */ {256*K, 0, 0, 0}, /* 0 */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c --- v2.4.0-test10/linux/drivers/sound/maestro.c Tue Aug 29 14:09:15 2000 +++ linux/drivers/sound/maestro.c Sat Nov 11 18:33:13 2000 @@ -115,6 +115,8 @@ * themselves, but we'll see. * * History + * (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 * move to 2.3 power management interface, which * required hacking some suspend/resume/check paths @@ -812,7 +814,7 @@ * The PT101 setup is untested. */ -static u16 maestro_ac97_init(struct ess_card *card) +static u16 __init maestro_ac97_init(struct ess_card *card) { u16 vend1, vend2, caps; @@ -3290,7 +3292,7 @@ return card->power_regs ? 1 : 0; } -static int +static int __init maestro_install(struct pci_dev *pcidev, int card_type) { u32 n; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/maui.c linux/drivers/sound/maui.c --- v2.4.0-test10/linux/drivers/sound/maui.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/maui.c Sat Nov 11 18:33:13 2000 @@ -14,6 +14,8 @@ * Alan Cox General clean up, use kernel IRQ * system * Christoph Hellwig Adapted to module_init/module_exit + * Bartlomiej Zolnierkiewicz + * Added __init to download_code() * * Status: * Andrew J. Kroll Tested 06/01/1999 with: @@ -104,7 +106,7 @@ irq_ok = 1; } -static int download_code(void) +static int __init download_code(void) { int i, lines = 0; int eol_seen = 0, done = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c --- v2.4.0-test10/linux/drivers/sound/mpu401.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/mpu401.c Sat Nov 11 18:32:01 2000 @@ -13,6 +13,7 @@ * * Thomas Sailer ioctl code reworked (vmalloc/vfree removed) * Alan Cox modularisation, use normal request_irq, use dev_id + * Bartlomiej Zolnierkiewicz removed some __init to allow using many drivers */ #include @@ -908,7 +909,7 @@ static struct midi_operations mpu401_midi_operations[MAX_MIDI_DEV]; -static void __init mpu401_chk_version(int n, struct mpu_config *devc) +static void mpu401_chk_version(int n, struct mpu_config *devc) { int tmp; unsigned long flags; @@ -939,7 +940,7 @@ restore_flags(flags); } -void __init attach_mpu401(struct address_info *hw_config, struct module *owner) +void attach_mpu401(struct address_info *hw_config, struct module *owner) { unsigned long flags; char revision_char; @@ -1166,7 +1167,7 @@ } -int __init probe_mpu401(struct address_info *hw_config) +int probe_mpu401(struct address_info *hw_config) { int ok = 0; struct mpu_config tmp_devc; @@ -1662,7 +1663,7 @@ } } -static int __init mpu_timer_init(int midi_dev) +static int mpu_timer_init(int midi_dev) { struct mpu_config *devc; int n; @@ -1724,7 +1725,7 @@ MODULE_PARM(irq, "i"); MODULE_PARM(io, "i"); -int init_mpu401(void) +int __init init_mpu401(void) { /* Can be loaded either for module use or to provide functions to others */ @@ -1739,7 +1740,7 @@ return 0; } -void cleanup_mpu401(void) +void __exit cleanup_mpu401(void) { if (io != -1 && irq != -1) { /* Check for use by, for example, sscape driver */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/msnd.c linux/drivers/sound/msnd.c --- v2.4.0-test10/linux/drivers/sound/msnd.c Wed Jul 26 12:37:06 2000 +++ linux/drivers/sound/msnd.c Sat Nov 11 18:33:14 2000 @@ -57,7 +57,7 @@ static multisound_dev_t *devs[MSND_MAX_DEVS]; static int num_devs; -int msnd_register(multisound_dev_t *dev) +int __init msnd_register(multisound_dev_t *dev) { int i; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c --- v2.4.0-test10/linux/drivers/sound/msnd_pinnacle.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/msnd_pinnacle.c Sat Nov 11 18:33:14 2000 @@ -1404,7 +1404,7 @@ } #ifdef MODULE -static void unload_multisound(void) +static void __exit unload_multisound(void) { release_region(dev.io, dev.numio); free_irq(dev.irq, &dev); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/nm256_audio.c linux/drivers/sound/nm256_audio.c --- v2.4.0-test10/linux/drivers/sound/nm256_audio.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/nm256_audio.c Sat Nov 11 18:33:14 2000 @@ -11,6 +11,10 @@ * This driver was written by someone who wishes to remain anonymous. * It is in the public domain, so share and enjoy. Try to make a profit * off of it; go on, I dare you. + * + * Changes: + * 11-10-2000 Bartlomiej Zolnierkiewicz + * Added some __init */ #define __NO_VERSION__ @@ -945,7 +949,7 @@ /* Installs the AC97 mixer into CARD. */ -static int +static int __init nm256_install_mixer (struct nm256_info *card) { int mixer; @@ -989,7 +993,7 @@ * RAM. */ -static void +static void __init nm256_peek_for_sig (struct nm256_info *card) { u32 port1offset @@ -1031,7 +1035,7 @@ * VERSTR is a human-readable version string. */ -static int +static int __init nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) { struct nm256_info *card; @@ -1252,7 +1256,7 @@ * the sound cards are. */ -int +int __init init_nm256(void) { struct pci_dev *pcidev = NULL; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/pas2_midi.c linux/drivers/sound/pas2_midi.c --- v2.4.0-test10/linux/drivers/sound/pas2_midi.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/pas2_midi.c Sun Nov 12 20:35:35 2000 @@ -9,8 +9,11 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Bartlomiej Zolnierkiewicz : Added __init to pas_init_mixer() */ +#include #include "sound_config.h" #include "pas2.h" @@ -204,7 +207,7 @@ buffer_status: pas_buffer_status, }; -void pas_midi_init(void) +void __init pas_midi_init(void) { int dev = sound_alloc_mididev(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/pas2_mixer.c linux/drivers/sound/pas2_mixer.c --- v2.4.0-test10/linux/drivers/sound/pas2_mixer.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/pas2_mixer.c Sun Nov 12 20:35:35 2000 @@ -14,7 +14,9 @@ */ /* * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) + * Bartlomiej Zolnierkiewicz : added __init to pas_init_mixer() */ +#include #include "sound_config.h" #include "pas2.h" @@ -315,7 +317,7 @@ ioctl: pas_mixer_ioctl }; -int +int __init pas_init_mixer(void) { int d; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/pas2_pcm.c linux/drivers/sound/pas2_pcm.c --- v2.4.0-test10/linux/drivers/sound/pas2_pcm.c Fri Aug 11 08:26:43 2000 +++ linux/drivers/sound/pas2_pcm.c Sun Nov 12 20:35:35 2000 @@ -12,8 +12,10 @@ * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) * Alan Cox : Swatted a double allocation of device bug. Made a few * more things module options. + * Bartlomiej Zolnierkiewicz : Added __init to pas_pcm_init() */ +#include #include "sound_config.h" #include "pas2.h" @@ -385,7 +387,7 @@ trigger: pas_audio_trigger }; -void pas_pcm_init(struct address_info *hw_config) +void __init pas_pcm_init(struct address_info *hw_config) { DEB(printk("pas2_pcm.c: long pas_pcm_init()\n")); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/pss.c linux/drivers/sound/pss.c --- v2.4.0-test10/linux/drivers/sound/pss.c Sun Oct 8 10:50:27 2000 +++ linux/drivers/sound/pss.c Sat Nov 11 18:33:14 2000 @@ -50,6 +50,8 @@ * setting is the previous hardcoded setting "/etc/sound/pss_synth". * 00-03-03: Christoph Hellwig * Adapted to module_init/module_exit + * 11-10-2000: Bartlomiej Zolnierkiewicz + * Added __init to probe_pss(), attach_pss() and probe_pss_mpu() */ @@ -168,7 +170,7 @@ printk(KERN_WARNING "PSS: DSP Command (%04x) Timeout.\n", data); } -int probe_pss(struct address_info *hw_config) +int __init probe_pss(struct address_info *hw_config) { unsigned short id; int irq, dma; @@ -644,7 +646,7 @@ } } -void attach_pss(struct address_info *hw_config) +void __init attach_pss(struct address_info *hw_config) { unsigned short id; char tmp[100]; @@ -693,7 +695,7 @@ conf_printf(tmp, hw_config); } -int probe_pss_mpu(struct address_info *hw_config) +int __init probe_pss_mpu(struct address_info *hw_config) { int timeout; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/sgalaxy.c linux/drivers/sound/sgalaxy.c --- v2.4.0-test10/linux/drivers/sound/sgalaxy.c Fri Aug 11 08:26:44 2000 +++ linux/drivers/sound/sgalaxy.c Sat Nov 11 18:33:14 2000 @@ -16,6 +16,10 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * 11-10-2000 Bartlomiej Zolnierkiewicz + * Added __init to sb_rst() and sb_cmd() */ #include @@ -40,7 +44,7 @@ #define SBDSP_STATUS SBDSP_COMMAND #define SBDSP_DATA_AVAIL 0xE -static int sb_rst(int base) +static int __init sb_rst(int base) { int i; @@ -62,7 +66,7 @@ return 1; } -static int sb_cmd( int base, unsigned char val ) +static int __init sb_cmd( int base, unsigned char val ) { int i; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c --- v2.4.0-test10/linux/drivers/sound/sonicvibes.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/sonicvibes.c Thu Nov 16 12:51:28 2000 @@ -1073,9 +1073,9 @@ return put_user(0, (int *)arg); return put_user(((4 - (l & 7)) << 2) | ((4 - (r & 7)) << 5) | 2, (int *)arg); } - if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int)) + if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int)) return -EINVAL; - if (_IOC_DIR(cmd) == _IOC_READ) { + if (_SIOC_DIR(cmd) == _SIOC_READ) { switch (_IOC_NR(cmd)) { case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ return put_user(mixer_recmask(s), (int *)arg); @@ -1114,7 +1114,7 @@ #endif /* OSS_DOCUMENTED_MIXER_SEMANTICS */ } } - if (_IOC_DIR(cmd) != (_IOC_READ|_IOC_WRITE)) + if (_SIOC_DIR(cmd) != (_SIOC_READ|_SIOC_WRITE)) return -EINVAL; s->mix.modcnt++; switch (_IOC_NR(cmd)) { diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c --- v2.4.0-test10/linux/drivers/sound/sscape.c Fri Aug 11 08:26:44 2000 +++ linux/drivers/sound/sscape.c Sat Nov 11 18:33:14 2000 @@ -14,6 +14,7 @@ * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed) * Sergey Smitienko : ensoniq p'n'p support * Christoph Hellwig : adapted to module_init/module_exit + * Bartlomiej Zolnierkiewicz : added __init to attach_sscape() */ #include @@ -609,7 +610,7 @@ static int sscape_detected = 0; static int sscape_is_pnp = 0; -void attach_sscape(struct address_info *hw_config) +void __init attach_sscape(struct address_info *hw_config) { #ifndef SSCAPE_REGS /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/trident.c linux/drivers/sound/trident.c --- v2.4.0-test10/linux/drivers/sound/trident.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/trident.c Fri Nov 10 11:37:55 2000 @@ -31,6 +31,9 @@ * * History * v0.14.6 + * Nov 1 2000 Ching-Ling Lee + * Fix the bug of memory leak when swithing 5.1-channels to 2 channels. + * Add lock protection into dynamic changing format of data. * Oct 18 2000 Ching-Ling Lee * 5.1-channels support for ALi * June 28 2000 Ching-Ling Lee @@ -142,7 +145,7 @@ /* minor number of /dev/swmodem (temporary, experimental) */ #define SND_DEV_SWMODEM 7 -static const unsigned ali_multi_channels[] = { ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL,ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL/*, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL*/}; +static const unsigned ali_multi_channels_5_1[] = { ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL}; static const unsigned sample_size[] = { 1, 2, 2, 4 }; static const unsigned sample_shift[] = { 0, 1, 1, 2 }; @@ -225,12 +228,14 @@ unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; + } dmabuf; /* 5.1channels */ struct trident_state *other_states[4]; int multi_channels_adjust_count; unsigned chans_num; + unsigned fmt_flag:1; }; /* hardware channels */ @@ -341,7 +346,6 @@ static int ali_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data); static void ali_restore_regs(struct trident_card *card); static void ali_save_regs(struct trident_card *card); -static int ali_allocate_multi_channels(struct trident_state *state, int chan_nums); static void ali_free_pcm_channel(struct trident_card *card, unsigned int channel); static int ali_setup_multi_channels(struct trident_card *card, int chan_nums); static unsigned int ali_get_spdif_in_rate(struct trident_card *card); @@ -349,7 +353,9 @@ static void ali_disable_spdif_in(struct trident_card *card); static void ali_disable_special_channel(struct trident_card *card, int ch); static void ali_setup_spdif_out(struct trident_card *card, int flag); -static unsigned int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel); +static int ali_write_5_1(struct trident_state *state, const char *buffer,int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt); +static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums); +static void ali_free_other_states_resources(struct trident_state *state); /* save registers for ALi Power Management */ @@ -359,9 +365,22 @@ unsigned mixer_regs[ALI_MIXER_REGS]; } ali_registers; -#define seek_offset(dma_ptr, buffer, cnt, offset) (dma_ptr) += (offset); \ +#define seek_offset(dma_ptr, buffer, cnt, offset, copy_count) (dma_ptr) += (offset); \ (buffer) += (offset); \ - (cnt) -= (offset); + (cnt) -= (offset); \ + (copy_count) += (offset); + +#define lock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ + if (state->fmt_flag) { \ + spin_unlock_irqrestore(&state->card->lock, flags); \ + return -EFAULT; \ + } \ + state->fmt_flag = 1; \ + spin_unlock_irqrestore(&state->card->lock, flags);} + +#define unlock_set_fmt(state) {spin_lock_irqsave(&state->card->lock, flags); \ + state->fmt_flag = 0; \ + spin_unlock_irqrestore(&state->card->lock, flags);} static int trident_enable_loop_interrupts(struct trident_card * card) { @@ -993,18 +1012,15 @@ struct dmabuf *dmabuf = &state->dmabuf; unsigned bytepersec; struct trident_state *s = state; - unsigned bufsize, dma_nums, default_order; + unsigned bufsize, dma_nums; unsigned long flags; int ret, i, order; struct page *page, *pend; - default_order = DMABUF_DEFAULTORDER; - if (s->chans_num == 6) { + lock_set_fmt(state); + if (state->chans_num == 6) dma_nums = 5; - } - else { - dma_nums = 1; - } + else dma_nums = 1; for (i = 0; i < dma_nums; i++) { if (i > 0) { @@ -1022,8 +1038,10 @@ /* allocate DMA buffer if not allocated yet */ if (!dmabuf->rawbuf) { if (i == 0) { - if ((ret = alloc_dmabuf(state))) + if ((ret = alloc_dmabuf(state))) { + unlock_set_fmt(state); return ret; + } } else { if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) @@ -1034,6 +1052,7 @@ i-=2; for (; i >= 0; i--) free_pages((unsigned long)state->other_states[i]->dmabuf.rawbuf, state->other_states[i]->dmabuf.buforder); + unlock_set_fmt(state); return -ENOMEM; } dmabuf->ready = dmabuf->mapped = 0; @@ -1087,6 +1106,7 @@ dmabuf->fragsize, dmabuf->dmasize); #endif } + unlock_set_fmt(state); return 0; } @@ -1451,6 +1471,7 @@ unsigned swptr; int cnt; unsigned int state_cnt; + unsigned int copy_count; #ifdef DEBUG printk("trident: trident_write called, count = %d\n", count); @@ -1493,8 +1514,10 @@ } /* No matter how much data left in the buffer, we have to wait untill CSO == ESO/2 or CSO == ESO when address engine interrupts */ + lock_set_fmt(state); tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2); tmo >>= sample_shift[dmabuf->fmt]; + unlock_set_fmt(state); /* 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 @@ -1518,17 +1541,34 @@ } continue; } - + lock_set_fmt(state); if (state->chans_num == 6) { - state_cnt = ali_write_5_1(state, buffer, cnt); + copy_count = 0; + state_cnt = 0; + if (ali_write_5_1(state, buffer, cnt, ©_count, &state_cnt) == -EFAULT) { + if (state_cnt){ + swptr = (swptr + state_cnt) % dmabuf->dmasize; + spin_lock_irqsave(&state->card->lock, flags); + dmabuf->swptr = swptr; + dmabuf->count += state_cnt; + dmabuf->endcleared = 0; + spin_unlock_irqrestore(&state->card->lock, flags); + } + ret += copy_count; + if (!ret) ret = -EFAULT; + unlock_set_fmt(state); + return ret; + } } else { if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) { if (!ret) ret = -EFAULT; + unlock_set_fmt(state); return ret; } state_cnt = cnt; } + unlock_set_fmt(state); swptr = (swptr + state_cnt) % dmabuf->dmasize; @@ -1684,6 +1724,7 @@ case SNDCTL_DSP_STEREO: /* set stereo or mono channel */ if (get_user(val, (int *)arg)) return -EFAULT; + lock_set_fmt(state); if (file->f_mode & FMODE_WRITE) { stop_dac(state); dmabuf->ready = 0; @@ -1700,6 +1741,7 @@ else dmabuf->fmt &= ~TRIDENT_FMT_STEREO; } + unlock_set_fmt(state); return 0; case SNDCTL_DSP_GETBLKSIZE: @@ -1720,6 +1762,7 @@ case SNDCTL_DSP_SETFMT: /* Select sample format */ if (get_user(val, (int *)arg)) return -EFAULT; + lock_set_fmt(state); if (val != AFMT_QUERY) { if (file->f_mode & FMODE_WRITE) { stop_dac(state); @@ -1738,6 +1781,7 @@ dmabuf->fmt &= ~TRIDENT_FMT_16BIT; } } + unlock_set_fmt(state); return put_user((dmabuf->fmt & TRIDENT_FMT_16BIT) ? AFMT_S16_LE : AFMT_U8, (int *)arg); @@ -1745,40 +1789,49 @@ if (get_user(val, (int *)arg)) return -EFAULT; if (val != 0) { + lock_set_fmt(state); if (file->f_mode & FMODE_WRITE) { stop_dac(state); dmabuf->ready = 0; + + //prevent from memory leak + if ((state->chans_num > 2) && (state->chans_num != val)) { + ali_free_other_states_resources(state); + state->chans_num = 1; + } + if (val >= 2) { dmabuf->fmt |= TRIDENT_FMT_STEREO; - if (val == 6) { - val = ali_setup_multi_channels(state->card, 6); - if (val < 0) - return val; + if ((val == 6) && (state->card->pci_id == PCI_DEVICE_ID_ALI_5451)) { + ali_setup_multi_channels(state->card, 6); down(&state->card->open_sem); - val = ali_allocate_multi_channels(state, 6); + ret = ali_allocate_other_states_resources(state, 6); up(&state->card->open_sem); - if (val < 0) - return val; - val = 6; + if (ret < 0) { + unlock_set_fmt(state); + return ret; + } } - else val = 2; + else val = 2; /*yield to 2-channels*/ } else dmabuf->fmt &= ~TRIDENT_FMT_STEREO; + state->chans_num = val; } if (file->f_mode & FMODE_READ) { stop_adc(state); dmabuf->ready = 0; if (val >= 2) { - if (val!=6) + if (!((file->f_mode & FMODE_WRITE) && (val == 6))) val = 2; dmabuf->fmt |= TRIDENT_FMT_STEREO; } else dmabuf->fmt &= ~TRIDENT_FMT_STEREO; + state->chans_num = val; } + unlock_set_fmt(state); } - state->chans_num = val; return put_user(val, (int *)arg); case SNDCTL_DSP_POST: @@ -2059,6 +2112,7 @@ struct trident_state *state = (struct trident_state *)file->private_data; struct trident_card *card; struct dmabuf *dmabuf; + unsigned long flags; lock_kernel(); card = state->card; @@ -2075,24 +2129,10 @@ if (file->f_mode & FMODE_WRITE) { stop_dac(state); - if (state->chans_num == 6) { - dealloc_dmabuf(state->other_states[0]); - dealloc_dmabuf(state->other_states[1]); - dealloc_dmabuf(state->other_states[2]); - dealloc_dmabuf(state->other_states[3]); - state->card->free_pcm_channel(state->card, state->other_states[0]->dmabuf.channel->num); - state->card->free_pcm_channel(state->card, state->other_states[1]->dmabuf.channel->num); - state->card->free_pcm_channel(state->card, state->other_states[2]->dmabuf.channel->num); - state->card->free_pcm_channel(state->card, state->other_states[3]->dmabuf.channel->num); - card->states[state->other_states[0]->virt] = NULL; - kfree(state->other_states[0]); - card->states[state->other_states[1]->virt] = NULL; - kfree(state->other_states[1]); - card->states[state->other_states[2]->virt] = NULL; - kfree(state->other_states[2]); - card->states[state->other_states[3]->virt] = NULL; - kfree(state->other_states[3]); - } + lock_set_fmt(state); + if (state->chans_num > 2) + ali_free_other_states_resources(state); + unlock_set_fmt(state); dealloc_dmabuf(state); state->card->free_pcm_channel(state->card, dmabuf->channel->num); } @@ -2495,11 +2535,10 @@ static int ali_setup_multi_channels(struct trident_card *card, int chan_nums) { unsigned long dwValue; + if (chan_nums == 6) { dwValue = inl(TRID_REG(card, ALI_SCTRL)) | 0x000f0000; outl(dwValue, TRID_REG(card, ALI_SCTRL)); - dwValue = inl(TRID_REG(card, ALI_GLOBAL_CONTROL)) | 0x07800000; - outl(dwValue, TRID_REG(card, ALI_GLOBAL_CONTROL)); } return 1; } @@ -2517,7 +2556,7 @@ card->banks[bank].bitmap &= ~(1 << (channel)); } -static int ali_allocate_multi_channels(struct trident_state *state, int chan_nums) +static int ali_allocate_other_states_resources(struct trident_state *state, int chan_nums) { struct trident_card *card = state->card; struct trident_state *s; @@ -2530,26 +2569,26 @@ if (chan_nums == 6) { for(i = 0;(i < ALI_CHANNELS) && (state_count != 4); i++) { if (!card->states[i]) { - if (!(bank->bitmap & (1 << ali_multi_channels[state_count]))) { - bank->bitmap |= (1 << ali_multi_channels[state_count]); - channel = &bank->channels[ali_multi_channels[state_count]]; - channel->num = ali_multi_channels[state_count]; + if (!(bank->bitmap & (1 << ali_multi_channels_5_1[state_count]))) { + bank->bitmap |= (1 << ali_multi_channels_5_1[state_count]); + channel = &bank->channels[ali_multi_channels_5_1[state_count]]; + channel->num = ali_multi_channels_5_1[state_count]; } else { state_count--; for (; state_count >= 0; state_count--) { kfree(state->other_states[state_count]); - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); } return -EBUSY; } s = card->states[i] = (struct trident_state *) kmalloc(sizeof(struct trident_state), GFP_KERNEL); if (!s) { - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); state_count--; for (; state_count >= 0; state_count--) { - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); kfree(state->other_states[state_count]); } return -ENOMEM; @@ -2562,7 +2601,7 @@ s->magic = card->magic; s->card = card; s->virt = i; - + ali_enable_special_channel(s); state->other_states[state_count++] = s; } } @@ -2571,7 +2610,7 @@ state_count--; for (; state_count >= 0; state_count--) { kfree(state->other_states[state_count]); - ali_free_pcm_channel(card, ali_multi_channels[state_count]); + ali_free_pcm_channel(card, ali_multi_channels_5_1[state_count]); } return -EBUSY; } @@ -2791,32 +2830,34 @@ depend on a master state's DMA, and changing the counters of the master state DMA is protected by a spinlock. */ -static unsigned int ali_write_5_1(struct trident_state *state, const char *buf, int cnt_for_multi_channel) +static int ali_write_5_1(struct trident_state *state, const char *buf, int cnt_for_multi_channel, unsigned int *copy_count, unsigned int *state_cnt) { struct dmabuf *dmabuf = &state->dmabuf; struct dmabuf *dmabuf_temp; const char *buffer = buf; unsigned swptr, other_dma_nums, sample_s; - unsigned int i, loop, state_cnt = 0; + unsigned int i, loop; other_dma_nums = 4; sample_s = sample_size[dmabuf->fmt] >> 1; swptr = dmabuf->swptr; - + if ((i = state->multi_channels_adjust_count) > 0) { if (i == 1) { - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); i--; - state_cnt += sample_s; + (*state_cnt) += sample_s; state->multi_channels_adjust_count++; } else i = i - (state->chans_num - other_dma_nums); for (; (i < other_dma_nums) && (cnt_for_multi_channel > 0); i++) { dmabuf_temp = &state->other_states[i]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); } if (cnt_for_multi_channel == 0) state->multi_channels_adjust_count += i; @@ -2824,46 +2865,53 @@ if (cnt_for_multi_channel > 0) { loop = cnt_for_multi_channel / (state->chans_num * sample_s); for (i = 0; i < loop; i++) { - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s * 2); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s * 2); + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s * 2)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s * 2, *copy_count); + (*state_cnt) += (sample_s * 2); dmabuf_temp = &state->other_states[0]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); dmabuf_temp = &state->other_states[1]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); dmabuf_temp = &state->other_states[2]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); dmabuf_temp = &state->other_states[3]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); } - state_cnt += (sample_s * 2 * loop); - if (cnt_for_multi_channel > 0) { state->multi_channels_adjust_count = cnt_for_multi_channel / sample_s; - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s); - state_cnt += sample_s; + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); + (*state_cnt) += sample_s; if (cnt_for_multi_channel > 0) { - copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s); - seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s); - state_cnt += sample_s; + if (copy_from_user(dmabuf->rawbuf + swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); + (*state_cnt) += sample_s; if (cnt_for_multi_channel > 0) { loop = state->multi_channels_adjust_count - (state->chans_num - other_dma_nums); for (i = 0; i < loop; i++) { dmabuf_temp = &state->other_states[i]->dmabuf; - copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s); - seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s); + if (copy_from_user(dmabuf_temp->rawbuf + dmabuf_temp->swptr, buffer, sample_s)) + return -EFAULT; + seek_offset(dmabuf_temp->swptr, buffer, cnt_for_multi_channel, sample_s, *copy_count); } } } @@ -2875,7 +2923,25 @@ dmabuf_temp = &state->other_states[i]->dmabuf; dmabuf_temp->swptr = dmabuf_temp->swptr % dmabuf_temp->dmasize; } - return state_cnt; + return *state_cnt; +} + +static void ali_free_other_states_resources(struct trident_state *state) +{ + int i; + struct trident_card *card = state->card; + struct trident_state *s; + unsigned other_states_count; + + other_states_count = state->chans_num - 2; /* except PCM L/R channels*/ + for ( i = 0; i < other_states_count; i++) { + s = state->other_states[i]; + dealloc_dmabuf(s); + ali_disable_special_channel(s->card, s->dmabuf.channel->num); + state->card->free_pcm_channel(s->card, s->dmabuf.channel->num); + card->states[s->virt] = NULL; + kfree(s); + } } #ifdef CONFIG_PROC_FS diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/vwsnd.c linux/drivers/sound/vwsnd.c --- v2.4.0-test10/linux/drivers/sound/vwsnd.c Sun Oct 8 10:50:29 2000 +++ linux/drivers/sound/vwsnd.c Wed Nov 15 22:35:54 2000 @@ -135,6 +135,10 @@ * For AFMT_S8, AFMT_MU_LAW and AFMT_A_LAW output, we have to XOR * the 0x80 bit in software to compensate for Lithium's XOR. * This happens in pcm_copy_{in,out}(). + * + * Changes: + * 11-10-2000 Bartlomiej Zolnierkiewicz + * Added some __init/__exit */ #include @@ -1330,7 +1334,7 @@ * * return 0 on success, -errno on failure. */ -static int ad1843_init(lithium_t *lith) +static int __init ad1843_init(lithium_t *lith) { unsigned long later; int err; @@ -1822,8 +1826,8 @@ aport->swstate = SW_INITIAL; add_wait_queue(&aport->queue, &wait); - current->state = TASK_UNINTERRUPTIBLE; while (1) { + set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_irqsave(&aport->lock, flags); { hwstate = aport->hwstate; @@ -2192,8 +2196,8 @@ DBGEV("(devc=0x%p)\n", devc); add_wait_queue(&wport->queue, &wait); - current->state = TASK_UNINTERRUPTIBLE; while (1) { + set_current_state(TASK_UNINTERRUPTIBLE); spin_lock_irqsave(&wport->lock, flags); { hwstate = wport->hwstate; @@ -2280,9 +2284,9 @@ while (count) { DECLARE_WAITQUEUE(wait, current); add_wait_queue(&rport->queue, &wait); - current->state = TASK_INTERRUPTIBLE; while ((nb = swb_inc_u(rport, 0)) == 0) { DBGPV("blocking\n"); + set_current_state(TASK_INTERRUPTIBLE); if (rport->flags & DISABLED || file->f_flags & O_NONBLOCK) { current->state = TASK_RUNNING; @@ -2356,8 +2360,8 @@ while (count) { DECLARE_WAITQUEUE(wait, current); add_wait_queue(&wport->queue, &wait); - current->state = TASK_INTERRUPTIBLE; while ((nb = swb_inc_u(wport, 0)) == 0) { + set_current_state(TASK_INTERRUPTIBLE); if (wport->flags & DISABLED || file->f_flags & O_NONBLOCK) { current->state = TASK_RUNNING; @@ -3239,7 +3243,7 @@ /* driver probe routine. Return nonzero if hardware is found. */ -static int probe_vwsnd(struct address_info *hw_config) +static int __init probe_vwsnd(struct address_info *hw_config) { lithium_t lith; int w; @@ -3291,7 +3295,7 @@ * Return +minor_dev on success, -errno on failure. */ -static int attach_vwsnd(struct address_info *hw_config) +static int __init attach_vwsnd(struct address_info *hw_config) { vwsnd_dev_t *devc = NULL; int err = -ENOMEM; @@ -3417,7 +3421,7 @@ return err; } -static int unload_vwsnd(struct address_info *hw_config) +static int __exit unload_vwsnd(struct address_info *hw_config) { vwsnd_dev_t *devc, **devcp; @@ -3481,10 +3485,3 @@ module_init(init_vwsnd); module_exit(cleanup_vwsnd); - -/* - * Local variables: - * compile-command: "cd ../..; make modules SUBDIRS=drivers/sound" - * c-basic-offset: 8 - * End: - */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/waveartist.c linux/drivers/sound/waveartist.c --- v2.4.0-test10/linux/drivers/sound/waveartist.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/sound/waveartist.c Sat Nov 11 18:33:14 2000 @@ -17,6 +17,10 @@ * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software * for more info. + * + * Changes: + * 11-10-2000 Bartlomiej Zolnierkiewicz + * Added __init to waveartist_init() */ /* Debugging */ @@ -1190,8 +1194,7 @@ ioctl: waveartist_mixer_ioctl }; -static int -waveartist_init(wavnc_info *devc) +static int __init waveartist_init(wavnc_info *devc) { wavnc_port_info *portc; char rev[3], dev_name[64]; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c --- v2.4.0-test10/linux/drivers/sound/wavfront.c Fri Aug 11 08:26:44 2000 +++ linux/drivers/sound/wavfront.c Sat Nov 11 18:33:14 2000 @@ -60,7 +60,12 @@ * * This program is distributed under the GNU GENERAL PUBLIC LICENSE (GPL) * Version 2 (June 1991). See the "COPYING" file distributed with this software - * for more info. */ + * for more info. + * + * Changes: + * 11-10-2000 Bartlomiej Zolnierkiewicz + * Added some __init and __initdata to entries in yss225.c + */ #include @@ -2247,9 +2252,7 @@ restore_flags (flags); } -static int -wavefront_hw_reset (void) - +static int __init wavefront_hw_reset (void) { int bits; int hwv[2]; @@ -2703,8 +2706,7 @@ return 0; } -static int -wavefront_do_reset (int atboot) +static int __init wavefront_do_reset (int atboot) { char voices[1]; @@ -3076,7 +3078,7 @@ a somewhat "algorithmic" approach. */ -static int wffx_init (void) +static int __init wffx_init (void) { int i; int j; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/ymf_sb.c linux/drivers/sound/ymf_sb.c --- v2.4.0-test10/linux/drivers/sound/ymf_sb.c Sun Oct 8 10:50:29 2000 +++ linux/drivers/sound/ymf_sb.c Sat Nov 11 18:33:14 2000 @@ -43,6 +43,10 @@ Thu Sep 21 05:32:51 BRT 2000 0.0.5 * got rid of attach_uart401 and attach_sbmpu Arnaldo Carvalho de Melo + + Fri Nov 10 21:24:11 CET 2000 0.0.6 + * added some __init and __initdata to entries in 724hwmcode.h + Bartlomiej Zolnierkiewicz */ #include @@ -220,7 +224,7 @@ #define PFX "ymf_sb: " -#define YMFSB_VERSION "0.0.5" +#define YMFSB_VERSION "0.0.6" #define YMFSB_CARD_NAME "YMF7xx Legacy Audio driver " YMFSB_VERSION #ifdef SUPPORT_UART401_MIDI @@ -338,7 +342,7 @@ return 0; } -static int checkCodec( struct pci_dev *pcidev ) +static int __init checkCodec( struct pci_dev *pcidev ) { u8 tmp8; @@ -357,7 +361,7 @@ return 0; } -static int setupLegacyIO( struct pci_dev *pcidev ) +static int __init setupLegacyIO( struct pci_dev *pcidev ) { int v; int sbio=0,mpuio=0,oplio=0,dma=0; @@ -500,7 +504,7 @@ return; } -static int setupInstruction( struct pci_dev *pcidev ) +static int __init setupInstruction( struct pci_dev *pcidev ) { int i; int val; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/sound/yss225.c linux/drivers/sound/yss225.c --- v2.4.0-test10/linux/drivers/sound/yss225.c Sat Jul 18 14:11:41 1998 +++ linux/drivers/sound/yss225.c Sun Nov 12 20:41:05 2000 @@ -1,4 +1,6 @@ -unsigned char page_zero[] = { +#include + +unsigned char page_zero[] __initdata = { 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00, @@ -25,7 +27,7 @@ 0x1d, 0x02, 0xdf }; -unsigned char page_one[] = { +unsigned char page_one[] __initdata = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00, 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, @@ -52,7 +54,7 @@ 0x60, 0x00, 0x1b }; -unsigned char page_two[] = { +unsigned char page_two[] __initdata = { 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4, 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -67,7 +69,7 @@ 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44 }; -unsigned char page_three[] = { +unsigned char page_three[] __initdata = { 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -82,7 +84,7 @@ 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40 }; -unsigned char page_four[] = { +unsigned char page_four[] __initdata = { 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -97,7 +99,7 @@ 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01 }; -unsigned char page_six[] = { +unsigned char page_six[] __initdata = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00, @@ -118,7 +120,7 @@ 0x80, 0x00, 0x7e, 0x80, 0x80 }; -unsigned char page_seven[] = { +unsigned char page_seven[] __initdata = { 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f, @@ -145,7 +147,7 @@ 0x00, 0x02, 0x00 }; -unsigned char page_zero_v2[] = { +unsigned char page_zero_v2[] __initdata = { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -157,7 +159,7 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -unsigned char page_one_v2[] = { +unsigned char page_one_v2[] __initdata = { 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -169,21 +171,21 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -unsigned char page_two_v2[] = { +unsigned char page_two_v2[] __initdata = { 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -unsigned char page_three_v2[] = { +unsigned char page_three_v2[] __initdata = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -unsigned char page_four_v2[] = { +unsigned char page_four_v2[] __initdata = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -191,7 +193,7 @@ 0x00, 0x00, 0x00, 0x00 }; -unsigned char page_seven_v2[] = { +unsigned char page_seven_v2[] __initdata = { 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -202,7 +204,7 @@ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; -unsigned char mod_v2[] = { +unsigned char mod_v2[] __initdata = { 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05, 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0, @@ -232,7 +234,7 @@ 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01, 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01 }; -unsigned char coefficients[] = { +unsigned char coefficients[] __initdata = { 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03, 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01, @@ -268,14 +270,14 @@ 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02, 0xba }; -unsigned char coefficients2[] = { +unsigned char coefficients2[] __initdata = { 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f, 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d, 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00 }; -unsigned char coefficients3[] = { +unsigned char coefficients3[] __initdata = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00, 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c --- v2.4.0-test10/linux/drivers/telephony/ixj.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/telephony/ixj.c Wed Nov 15 00:41:03 2000 @@ -1812,6 +1812,8 @@ while (!j->read_buffer_ready || (j->dtmf_state && j->flags.dtmf_oob)) { ++j->read_wait; if(j->tone_state) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->read_q, &wait); j->flags.inread = 0; return -EAGAIN; } @@ -1894,6 +1896,8 @@ while (!j->write_buffers_empty) { ++j->write_wait; if(j->tone_state) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&j->write_q, &wait); j->flags.inwrite = 0; return -EAGAIN; } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/Config.in linux/drivers/usb/Config.in --- v2.4.0-test10/linux/drivers/usb/Config.in Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/Config.in Sat Nov 11 19:04:30 2000 @@ -37,6 +37,7 @@ 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 @@ -49,8 +50,8 @@ 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 Digi International AccelePort USB Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_DIGI_ACCELEPORT $CONFIG_USB_SERIAL 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 diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/acm.c linux/drivers/usb/acm.c --- v2.4.0-test10/linux/drivers/usb/acm.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/acm.c Sat Nov 11 18:17:09 2000 @@ -477,114 +477,113 @@ * USB probe and disconnect routines. */ -static void *acm_probe(struct usb_device *dev, unsigned int ifnum) +static void *acm_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct acm *acm; struct usb_config_descriptor *cfacm; struct usb_interface_descriptor *ifcom, *ifdata; struct usb_endpoint_descriptor *epctrl, *epread, *epwrite; - int readsize, ctrlsize, minor, i; + int readsize, ctrlsize, minor; unsigned char *buf; - if (dev->descriptor.bDeviceClass != 2 || dev->descriptor.bDeviceSubClass != 0 + /* 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; - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) { + cfacm = dev->actconfig; - cfacm = dev->config + i; + dbg("probing config %d", cfacm->bConfigurationValue); - dbg("probing config %d", cfacm->bConfigurationValue); - - if (cfacm->bNumInterfaces != 2 || - usb_interface_claimed(cfacm->interface + 0) || - usb_interface_claimed(cfacm->interface + 1)) - continue; - - ifcom = cfacm->interface[0].altsetting + 0; - ifdata = cfacm->interface[1].altsetting + 0; - - 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; - } - - 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; - } - - usb_set_configuration(dev, cfacm->bConfigurationValue); - - for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); - if (acm_table[minor]) { - err("no more free acm devices"); - return NULL; - } - - if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { - err("out of memory"); + if (cfacm->bNumInterfaces != 2 || + usb_interface_claimed(cfacm->interface + 0) || + usb_interface_claimed(cfacm->interface + 1)) + return NULL; + + ifcom = cfacm->interface[0].altsetting + 0; + ifdata = cfacm->interface[1].altsetting + 0; + + 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; - } - memset(acm, 0, sizeof(struct acm)); + } - ctrlsize = epctrl->wMaxPacketSize; - readsize = epread->wMaxPacketSize; - acm->writesize = epwrite->wMaxPacketSize; - acm->iface = cfacm->interface; - acm->minor = minor; - acm->dev = dev; - - acm->tqueue.routine = acm_softint; - acm->tqueue.data = acm; - - if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { - err("out of memory"); - kfree(acm); + if (ifcom->bInterfaceClass != 2 || ifcom->bInterfaceSubClass != 2 || + ifcom->bInterfaceProtocol != 1 || ifcom->bNumEndpoints != 1) return NULL; - } - FILL_INT_URB(&acm->ctrlurb, dev, usb_rcvintpipe(dev, epctrl->bEndpointAddress), - buf, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); + 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 ((epread->bEndpointAddress & 0x80) != 0x80) { + epread = ifdata->endpoint + 1; + epwrite = ifdata->endpoint + 0; + } - 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; + usb_set_configuration(dev, cfacm->bConfigurationValue); - 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; - - printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); + for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++); + if (acm_table[minor]) { + err("no more free acm devices"); + return NULL; + } - acm_set_control(acm, acm->ctrlout); + if (!(acm = kmalloc(sizeof(struct acm), GFP_KERNEL))) { + err("out of memory"); + return NULL; + } + memset(acm, 0, sizeof(struct acm)); - acm->line.speed = cpu_to_le32(9600); - acm->line.databits = 8; - acm_set_line(acm, &acm->line); + ctrlsize = epctrl->wMaxPacketSize; + readsize = epread->wMaxPacketSize; + acm->writesize = epwrite->wMaxPacketSize; + acm->iface = cfacm->interface; + acm->minor = minor; + acm->dev = dev; - usb_driver_claim_interface(&acm_driver, acm->iface + 0, acm); - usb_driver_claim_interface(&acm_driver, acm->iface + 1, acm); + acm->tqueue.routine = acm_softint; + acm->tqueue.data = acm; - tty_register_devfs(&acm_tty_driver, 0, minor); - return acm_table[minor] = acm; + if (!(buf = kmalloc(ctrlsize + readsize + acm->writesize, GFP_KERNEL))) { + err("out of memory"); + kfree(acm); + return NULL; } - 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->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress), + buf += ctrlsize, readsize, acm_read_bulk, acm); + acm->readurb.transfer_flags |= USB_NO_FSBR; + + 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; + + printk(KERN_INFO "ttyACM%d: USB ACM device\n", minor); + + acm_set_control(acm, acm->ctrlout); + + 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; } static void acm_disconnect(struct usb_device *dev, void *ptr) @@ -622,10 +621,19 @@ * USB driver structure. */ +static struct usb_device_id acm_ids [] = { + { bDeviceClass: 2}, + { bInterfaceClass: 2, bInterfaceSubClass: 2, bInterfaceProtocol: 1}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, acm_ids); + static struct usb_driver acm_driver = { name: "acm", probe: acm_probe, - disconnect: acm_disconnect + disconnect: acm_disconnect, + id_table: acm_ids, }; /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/audio.c linux/drivers/usb/audio.c --- v2.4.0-test10/linux/drivers/usb/audio.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/audio.c Sat Nov 11 18:17:09 2000 @@ -2691,16 +2691,23 @@ /* --------------------------------------------------------------------- */ -static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum); +static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); static void usb_audio_disconnect(struct usb_device *dev, void *ptr); +static struct usb_device_id usb_audio_ids [] = { + { bInterfaceClass: USB_CLASS_AUDIO, bInterfaceSubClass: 1}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_audio_ids); + static struct usb_driver usb_audio_driver = { - "audio", - usb_audio_probe, - usb_audio_disconnect, - LIST_HEAD_INIT(usb_audio_driver.driver_list), - NULL, - 0 + name: "audio", + probe: usb_audio_probe, + disconnect: usb_audio_disconnect, + driver_list: LIST_HEAD_INIT(usb_audio_driver.driver_list), + id_table: usb_audio_ids, }; static void *find_descriptor(void *descstart, unsigned int desclen, void *after, @@ -3640,7 +3647,8 @@ /* we only care for the currently active configuration */ -static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum) +static void *usb_audio_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_config_descriptor *config = dev->actconfig; unsigned char *buffer; @@ -3653,25 +3661,13 @@ config->interface[ifnum].altsetting[0].bInterfaceClass, config->interface[ifnum].altsetting[0].bInterfaceSubClass); #endif - if (config->interface[ifnum].altsetting[0].bInterfaceClass != USB_CLASS_AUDIO || - config->interface[ifnum].altsetting[0].bInterfaceSubClass != 1) { -#if 0 - printk(KERN_DEBUG "usbaudio: vendor id 0x%04x, product id 0x%04x contains no AudioControl interface\n", - dev->descriptor.idVendor, dev->descriptor.idProduct); -#endif - return NULL; - } + /* * audiocontrol interface found * find which configuration number is active */ - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) - if (dev->config+i == config) - goto configfound; - printk(KERN_ERR "usbaudio: cannot find active configuration number of device %d\n", dev->devnum); - return NULL; + i = dev->actconfig - config; - configfound: if (usb_set_configuration(dev, config->bConfigurationValue) < 0) { printk(KERN_ERR "usbaudio: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue); return NULL; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c --- v2.4.0-test10/linux/drivers/usb/bluetooth.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/bluetooth.c Sat Nov 11 18:17:09 2000 @@ -183,14 +183,27 @@ static void bluetooth_read_bulk_callback (struct urb *urb); static void bluetooth_write_bulk_callback (struct urb *urb); -static void * usb_bluetooth_probe (struct usb_device *dev, unsigned int ifnum); +static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); static void usb_bluetooth_disconnect (struct usb_device *dev, void *ptr); +static struct usb_device_id usb_bluetooth_ids [] = { + { + bDeviceClass: WIRELESS_CLASS_CODE, + bDeviceSubClass: RF_SUBCLASS_CODE, + bDeviceProtocol: BLUETOOTH_PROGRAMMING_PROTOCOL_CODE + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_bluetooth_ids); + static struct usb_driver usb_bluetooth_driver = { name: "bluetooth", probe: usb_bluetooth_probe, disconnect: usb_bluetooth_disconnect, + id_table: usb_bluetooth_ids, }; static int bluetooth_refcount; @@ -950,7 +963,8 @@ } -static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum) +static void * usb_bluetooth_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_bluetooth *bluetooth = NULL; struct usb_interface_descriptor *interface; @@ -966,16 +980,6 @@ int num_interrupt_in = 0; int num_bulk_in = 0; int num_bulk_out = 0; - - /* see if this device has the proper class signature */ - if ((dev->descriptor.bDeviceClass != WIRELESS_CLASS_CODE) || - (dev->descriptor.bDeviceSubClass != RF_SUBCLASS_CODE) || - (dev->descriptor.bDeviceProtocol != BLUETOOTH_PROGRAMMING_PROTOCOL_CODE)) { - dbg (__FUNCTION__ " - class signature %d, %d, %d did not match", - dev->descriptor.bDeviceClass, dev->descriptor.bDeviceSubClass, - dev->descriptor.bDeviceProtocol); - return NULL; - } interface = &dev->actconfig->interface[ifnum].altsetting[0]; control_out_endpoint = interface->bInterfaceNumber; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/dabusb.c linux/drivers/usb/dabusb.c --- v2.4.0-test10/linux/drivers/usb/dabusb.c Thu Sep 7 08:36:40 2000 +++ linux/drivers/usb/dabusb.c Sat Nov 11 18:17:09 2000 @@ -718,7 +718,8 @@ } /* --------------------------------------------------------------------- */ -static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum) +static void *dabusb_probe (struct usb_device *usbdev, unsigned int ifnum, + const struct usb_device_id *id) { int devnum; pdabusb_t s; @@ -726,11 +727,6 @@ dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum); - /* the 1234:5678 is just a self assigned test ID */ - if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) && - (usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x9999)) - return NULL; - /* We don't handle multiple configurations */ if (usbdev->descriptor.bNumConfigurations != 1) return NULL; @@ -790,14 +786,22 @@ MOD_DEC_USE_COUNT; } +static struct usb_device_id dabusb_ids [] = { + { idVendor: 0x0547, idProduct: 0x2131 }, + { idVendor: 0x0547, idProduct: 0x9999 }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, dabusb_ids); + static struct usb_driver dabusb_driver = { - "dabusb", - dabusb_probe, - dabusb_disconnect, - {NULL, NULL}, - &dabusb_fops, - DABUSB_MINOR + name: "dabusb", + probe: dabusb_probe, + disconnect: dabusb_disconnect, + fops: &dabusb_fops, + minor: DABUSB_MINOR, + id_table: dabusb_ids, }; /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c --- v2.4.0-test10/linux/drivers/usb/dc2xx.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/dc2xx.c Sun Nov 12 20:40:42 2000 @@ -44,11 +44,14 @@ * 03 Nov, 1999 -- update for 2.3.25 kernel API changes. * 08 Jan, 2000 .. multiple camera support * 12 Aug, 2000 .. add some real locking, remove an Oops + * 10 Oct, 2000 .. usb_device_id table created. + * 01 Nov, 2000 .. usb_device_id support added by Adam J. Richter * * Thanks to: the folk who've provided USB product IDs, sent in * patches, and shared their sucesses! */ +#include #include #include #include @@ -59,7 +62,12 @@ #include #include #include -#undef DEBUG + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif #include @@ -82,7 +90,7 @@ /* table of cameras that work through this driver */ -static __devinitdata struct usb_device_id camera_table [] = { +static struct usb_device_id camera_table [] = { /* These have the same application level protocol */ { idVendor: 0x040a, idProduct: 0x0120 }, // Kodak DC-240 @@ -105,7 +113,7 @@ * means, among other things, no iso or interrupt endpoints. */ - { } // TERMINATING ENTRY + { } /* Terminating entry */ }; MODULE_DEVICE_TABLE (usb, camera_table); @@ -346,7 +354,7 @@ static void * __devinit -camera_bind (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *camera_info) +camera_probe (struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *camera_info) { int i; struct usb_interface_descriptor *interface; @@ -471,7 +479,7 @@ name: "dc2xx", id_table: camera_table, - bind: camera_bind, + probe: camera_probe, disconnect: camera_disconnect, fops: &usb_camera_fops, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/devio.c linux/drivers/usb/devio.c --- v2.4.0-test10/linux/drivers/usb/devio.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/devio.c Sun Nov 12 20:45:19 2000 @@ -292,7 +292,8 @@ * interface claiming */ -static void *driver_probe(struct usb_device *dev, unsigned int intf) +static void *driver_probe(struct usb_device *dev, unsigned int intf, + const struct usb_device_id *id) { return NULL; } @@ -541,13 +542,17 @@ i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.request, ctrl.requesttype, ctrl.value, ctrl.index, tbuf, ctrl.length, tmo); if ((i > 0) && ctrl.length) { - if (copy_to_user(ctrl.data, tbuf, ctrl.length)) + if (copy_to_user(ctrl.data, tbuf, ctrl.length)) { + free_page((unsigned long)tbuf); return -EFAULT; + } } } else { if (ctrl.length) { - if (copy_from_user(tbuf, ctrl.data, ctrl.length)) + if (copy_from_user(tbuf, ctrl.data, ctrl.length)) { + free_page((unsigned long)tbuf); return -EFAULT; + } } i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.request, ctrl.requesttype, ctrl.value, ctrl.index, tbuf, ctrl.length, tmo); @@ -583,7 +588,7 @@ return -EINVAL; len1 = bulk.len; if (len1 > PAGE_SIZE) - len1 = PAGE_SIZE; + return -EINVAL; if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL))) return -ENOMEM; tmo = (bulk.timeout * HZ + 999) / 1000; @@ -594,13 +599,17 @@ } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); if (!i && len2) { - if (copy_to_user(bulk.data, tbuf, len2)) + if (copy_to_user(bulk.data, tbuf, len2)) { + free_page((unsigned long)tbuf); return -EFAULT; + } } } else { if (len1) { - if (copy_from_user(tbuf, bulk.data, len1)) + if (copy_from_user(tbuf, bulk.data, len1)) { + free_page((unsigned long)tbuf); return -EFAULT; + } } i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); } @@ -697,9 +706,11 @@ continue; if (intf->driver) { + const struct usb_device_id *id; down(&intf->driver->serialize); intf->driver->disconnect(ps->dev, intf->private_data); - intf->driver->probe(ps->dev, i); + id = usb_match_id(ps->dev,intf,intf->driver->id_table); + intf->driver->probe(ps->dev, i, id); up(&intf->driver->serialize); } } diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c --- v2.4.0-test10/linux/drivers/usb/dsbr100.c Thu Sep 7 08:36:04 2000 +++ linux/drivers/usb/dsbr100.c Fri Nov 17 17:56:52 2000 @@ -70,7 +70,8 @@ #define TB_LEN 16 -static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum); +static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); static void usb_dsbr100_disconnect(struct usb_device *dev, void *ptr); static int usb_dsbr100_ioctl(struct video_device *dev, unsigned int cmd, void *arg); @@ -90,28 +91,30 @@ static struct video_device usb_dsbr100_radio= { - "D-Link DSB R-100 USB radio", - VID_TYPE_TUNER, - VID_HARDWARE_AZTECH, - usb_dsbr100_open, - usb_dsbr100_close, - NULL, /* Can't read (no capture ability) */ - NULL, /* Can't write */ - NULL, /* No poll */ - usb_dsbr100_ioctl, - NULL, - NULL + name: "D-Link DSB R-100 USB radio", + type: VID_TYPE_TUNER, + hardware: VID_HARDWARE_AZTECH, + open: usb_dsbr100_open, + close: usb_dsbr100_close, + ioctl: usb_dsbr100_ioctl, }; static int users = 0; +static struct usb_device_id usb_dsbr100_table [] = { + { idVendor: DSB100_VENDOR, idProduct: DSB100_PRODUCT }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_dsbr100_table); + static struct usb_driver usb_dsbr100_driver = { name: "dsbr100", probe: usb_dsbr100_probe, disconnect: usb_dsbr100_disconnect, - driver_list: {NULL,NULL}, - fops: NULL, - minor: 0 + fops: NULL, + minor: 0, + id_table: usb_dsbr100_table, }; @@ -164,13 +167,11 @@ } -static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum) +static void *usb_dsbr100_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { usb_dsbr100 *radio; - if (dev->descriptor.idVendor!=DSB100_VENDOR || - dev->descriptor.idProduct!=DSB100_PRODUCT) - return NULL; if (!(radio = kmalloc(sizeof(usb_dsbr100),GFP_KERNEL))) return NULL; usb_dsbr100_radio.priv = radio; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/hid.c linux/drivers/usb/hid.c --- v2.4.0-test10/linux/drivers/usb/hid.c Sun Oct 8 10:50:30 2000 +++ linux/drivers/usb/hid.c Sat Nov 11 18:17:09 2000 @@ -1373,9 +1373,6 @@ if ((hid_blacklist[n].idVendor == dev->descriptor.idVendor) && (hid_blacklist[n].idProduct == dev->descriptor.idProduct)) return NULL; - if (interface->bInterfaceClass != USB_INTERFACE_CLASS_HID) - return NULL; - if (usb_get_extra_descriptor(interface, USB_DT_HID, &hdesc) && usb_get_extra_descriptor(&interface->endpoint[0], USB_DT_HID, &hdesc)) { dbg("class descriptor not present\n"); @@ -1471,7 +1468,8 @@ return hid; } -static void* hid_probe(struct usb_device *dev, unsigned int ifnum) +static void* hid_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct hid_device *hid; char name[128]; @@ -1527,10 +1525,18 @@ hid_free_device(hid); } +static struct usb_device_id hid_usb_ids [] = { + { bInterfaceClass: USB_INTERFACE_CLASS_HID}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, hid_usb_ids); + static struct usb_driver hid_driver = { name: "hid", probe: hid_probe, - disconnect: hid_disconnect + disconnect: hid_disconnect, + id_table: hid_usb_ids, }; static int __init hid_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/hub.c linux/drivers/usb/hub.c --- v2.4.0-test10/linux/drivers/usb/hub.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/hub.c Fri Nov 17 16:44:55 2000 @@ -36,7 +36,7 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait); static int khubd_pid = 0; /* PID of khubd */ -static int khubd_running = 0; +static DECLARE_MUTEX_LOCKED(khubd_exited); static int usb_get_hub_descriptor(struct usb_device *dev, void *data, int size) { @@ -235,7 +235,9 @@ return 0; } -static void *hub_probe(struct usb_device *dev, unsigned int i) +static void *hub_probe(struct usb_device *dev, unsigned int i, + const struct usb_device_id *id) + { struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; @@ -244,10 +246,6 @@ interface = &dev->actconfig->interface[i].altsetting[0]; - /* Is it a hub? */ - if (interface->bInterfaceClass != USB_CLASS_HUB) - return NULL; - /* Some hubs have a subclass of 1, which AFAICT according to the */ /* specs is not defined, but it works */ if ((interface->bInterfaceSubClass != 0) && @@ -743,17 +741,13 @@ static int usb_hub_thread(void *__hub) { - khubd_running = 1; - lock_kernel(); /* * This thread doesn't need any user-level access, * so get rid of all our resources */ - exit_files(current); /* daemonize doesn't do exit_files */ - current->files = init_task.files; - atomic_inc(¤t->files->count); + daemonize(); /* Setup a nice name */ @@ -766,16 +760,23 @@ } while (!signal_pending(current)); dbg("usb_hub_thread exiting"); - khubd_running = 0; - return 0; + up_and_exit(&khubd_exited, 0); } +static struct usb_device_id hub_id_table [] = { + { bInterfaceClass: USB_CLASS_HUB}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, hub_id_table); + static struct usb_driver hub_driver = { name: "hub", probe: hub_probe, ioctl: hub_ioctl, - disconnect: hub_disconnect + disconnect: hub_disconnect, + id_table: hub_id_table, }; /* @@ -811,18 +812,8 @@ /* Kill the thread */ ret = kill_proc(khubd_pid, SIGTERM, 1); - if (!ret) { - /* Wait 10 seconds */ - int count = 10 * 100; - while (khubd_running && --count) { - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(1); - } - - if (!count) - err("giving up on killing khubd"); - } + down(&khubd_exited); /* * Hub resources are freed for us by usb_deregister. It calls diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c --- v2.4.0-test10/linux/drivers/usb/ibmcam.c Tue Sep 5 13:42:52 2000 +++ linux/drivers/usb/ibmcam.c Fri Nov 17 17:56:52 2000 @@ -2492,11 +2492,6 @@ MOD_DEC_USE_COUNT; } -static int ibmcam_init_done(struct video_device *dev) -{ - return 0; -} - static long ibmcam_write(struct video_device *dev, const char *buf, unsigned long count, int noblock) { return -EINVAL; @@ -2855,20 +2850,15 @@ } static struct video_device ibmcam_template = { - "CPiA USB Camera", - VID_TYPE_CAPTURE, - VID_HARDWARE_CPIA, - ibmcam_open, - ibmcam_close, - ibmcam_read, - ibmcam_write, - NULL, - ibmcam_ioctl, - ibmcam_mmap, - ibmcam_init_done, - NULL, - 0, - 0 + name: "CPiA USB Camera", + type: VID_TYPE_CAPTURE, + hardware: VID_HARDWARE_CPIA, + open: ibmcam_open, + close: ibmcam_close, + read: ibmcam_read, + write: ibmcam_write, + ioctl: ibmcam_ioctl, + mmap: ibmcam_mmap, }; static void usb_ibmcam_configure_video(struct usb_ibmcam *ibmcam) @@ -2953,7 +2943,8 @@ * 5/24/00 Corrected to prevent race condition (MOD_xxx_USE_COUNT). * 7/3/00 Fixed endianness bug. */ -static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum) +static void *usb_ibmcam_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_ibmcam *ibmcam = NULL; const struct usb_interface_descriptor *interface; @@ -2967,11 +2958,6 @@ if (dev->descriptor.bNumConfigurations != 1) return NULL; - /* Is it an IBM camera? */ - if ((dev->descriptor.idVendor != 0x0545) || - (dev->descriptor.idProduct != 0x8080)) - return NULL; - /* Check the version/revision */ switch (dev->descriptor.bcdDevice) { case 0x0002: @@ -2988,10 +2974,9 @@ dev->descriptor.bcdDevice); model = IBMCAM_MODEL_2; break; - default: - printk(KERN_ERR "IBM camera with revision 0x%04x is not supported.\n", - dev->descriptor.bcdDevice); - return NULL; + + /* ibmcam_table contents prevents any other values from ever + being passed to us, so no need for "default" case. */ } /* Validate found interface: must have one ISO endpoint */ @@ -3124,11 +3109,29 @@ MOD_DEC_USE_COUNT; } +static struct usb_device_id ibmcam_table [] = { + { + idVendor: 0x0545, + idProduct: 0x8080, + bcdDevice_lo: 0x0002, + bcdDevice_hi: 0x0002 + }, + { + idVendor: 0x0545, + idProduct: 0x8080, + bcdDevice_lo: 0X030a, + bcdDevice_hi: 0x030a + }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, ibmcam_table); + static struct usb_driver ibmcam_driver = { - "ibmcam", - usb_ibmcam_probe, - usb_ibmcam_disconnect, - { NULL, NULL } + name: "ibmcam", + probe: usb_ibmcam_probe, + disconnect: usb_ibmcam_disconnect, + id_table: ibmcam_table, }; /* diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c --- v2.4.0-test10/linux/drivers/usb/mdc800.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/mdc800.c Sat Nov 11 18:17:09 2000 @@ -370,7 +370,8 @@ /* * Callback to search the Mustek MDC800 on the USB Bus */ -static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum ) +static void* mdc800_usb_probe (struct usb_device *dev ,unsigned int ifnum, + const struct usb_device_id *id) { int i,j; struct usb_interface_descriptor *intf_desc; @@ -379,11 +380,6 @@ dbg ("(mdc800_usb_probe) called."); - if (dev->descriptor.idVendor != MDC800_VENDOR_ID) - return 0; - if (dev->descriptor.idProduct != MDC800_PRODUCT_ID) - return 0; - if (mdc800->dev != 0) { warn ("only one Mustek MDC800 is supported."); @@ -873,17 +869,23 @@ +static struct usb_device_id mdc800_table [] = { + { idVendor: MDC800_VENDOR_ID, idProduct: MDC800_PRODUCT_ID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, mdc800_table); /* * USB Driver Struct for this device */ static struct usb_driver mdc800_usb_driver = { - "mdc800", - mdc800_usb_probe, - mdc800_usb_disconnect, - { 0,0 }, - &mdc800_device_ops, - MDC800_DEVICE_MINOR_BASE + name: "mdc800", + probe: mdc800_usb_probe, + disconnect: mdc800_usb_disconnect, + fops: &mdc800_device_ops, + minor: MDC800_DEVICE_MINOR_BASE, + id_table: mdc800_table }; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c --- v2.4.0-test10/linux/drivers/usb/microtek.c Sun Oct 8 10:50:30 2000 +++ linux/drivers/usb/microtek.c Sat Nov 11 18:17:09 2000 @@ -140,14 +140,17 @@ /* USB layer driver interface */ -static void *mts_usb_probe(struct usb_device *dev, unsigned int interface); +static void *mts_usb_probe(struct usb_device *dev, unsigned int interface, + const struct usb_device_id *id); static void mts_usb_disconnect(struct usb_device *dev, void *ptr); +static struct usb_device_id mts_usb_ids []; + static struct usb_driver mts_usb_driver = { - "microtek", - mts_usb_probe, - mts_usb_disconnect, - { NULL, NULL } /* we need no fops. let gcc fill it */ + name: "microtek", + probe: mts_usb_probe, + disconnect: mts_usb_disconnect, + id_table: mts_usb_ids, }; @@ -338,6 +341,7 @@ while( !atomic_read(&desc->lock.count) ) { /* Is there a function to check if the semaphore is locked? */ + set_current_state(TASK_INTERRUPTIBLE); schedule_timeout( MTS_ABORT_TIMEOUT ); MTS_DEBUG_GOT_HERE(); mts_urb_abort(desc); @@ -791,8 +795,6 @@ struct vendor_product { - u16 idVendor; - u16 idProduct; char* name; enum { @@ -807,37 +809,37 @@ /* These are taken from the msmUSB.inf file on the Windows driver CD */ const static struct vendor_product mts_supported_products[] = { - { - 0x4ce, 0x300,"Phantom 336CX",mts_sup_unknown - }, - { - 0x5da, 0x94,"Phantom 336CX",mts_sup_unknown - }, - { - 0x5da, 0x99,"Scanmaker X6",mts_sup_alpha - }, - { - 0x5da, 0x9a,"Phantom C6",mts_sup_unknown - }, - { - 0x5da, 0xa0,"Phantom 336CX",mts_sup_unknown - }, - { - 0x5da, 0xa3,"ScanMaker V6USL",mts_sup_unknown - }, - { - 0x5da, 0x80a3,"ScanMaker V6USL",mts_sup_unknown - }, - { - 0x5da, 0x80ac,"Scanmaker V6UL",mts_sup_unknown - } -} -; -const static struct vendor_product* mts_last_product = &mts_supported_products[ sizeof(mts_supported_products) / sizeof(struct vendor_product) ]; - /* Must never be derefed, points to one after last entry */ + { "Phantom 336CX", mts_sup_unknown}, + { "Phantom 336CX", mts_sup_unknown}, + { "Scanmaker X6", mts_sup_alpha}, + { "Phantom C6", mts_sup_unknown}, + { "Phantom 336CX", mts_sup_unknown}, + { "ScanMaker V6USL", mts_sup_unknown}, + { "ScanMaker V6USL", mts_sup_unknown}, + { "Scanmaker V6UL", mts_sup_unknown}, +}; + +/* The entries of microtek_table must correspond, line-by-line to + the entries of mts_supported_products[]. */ + +static struct usb_device_id mts_usb_ids [] = +{ + {idVendor: 0x4ce, idProduct: 0x0300}, + {idVendor: 0x5da, idProduct: 0x0094}, + {idVendor: 0x5da, idProduct: 0x0099}, + {idVendor: 0x5da, idProduct: 0x009a}, + {idVendor: 0x5da, idProduct: 0x00a0}, + {idVendor: 0x5da, idProduct: 0x00a3}, + {idVendor: 0x5da, idProduct: 0x80a3}, + {idVendor: 0x5da, idProduct: 0x80ac}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, mts_usb_ids); -static void * mts_usb_probe (struct usb_device *dev, unsigned int interface) +static void * mts_usb_probe (struct usb_device *dev, unsigned int interface, + const struct usb_device_id *id) { int i; int result; @@ -860,20 +862,8 @@ (int)dev->descriptor.idVendor ); MTS_DEBUG_GOT_HERE(); - - /* checking IDs */ - for( p = mts_supported_products; p != mts_last_product; p++ ) - if ( dev->descriptor.idVendor == p->idVendor && - dev->descriptor.idProduct == p->idProduct ) - goto is_supported; - else - MTS_DEBUG( "doesn't appear to be model %s\n", p->name ); - MTS_DEBUG( "returning NULL: unsupported\n" ); - - return NULL; - - is_supported: + p = &mts_supported_products[id - mts_usb_ids]; MTS_DEBUG_GOT_HERE(); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/net1080.c linux/drivers/usb/net1080.c --- v2.4.0-test10/linux/drivers/usb/net1080.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/net1080.c Tue Nov 14 23:36:01 2000 @@ -11,7 +11,9 @@ * The IP-over-USB protocol here may be of interest. Embedded devices * could implement it at the cost of two bulk endpoints, and whatever * other system resources the desired IP-based applications need. - * Some Linux palmtops could support that today. + * Some Linux palmtops could support that today. (Devices that don't + * support the TTL-driven data mangling of the net1080 chip won't need + * the header/trailer support though.) * * STATUS: * @@ -22,6 +24,15 @@ * should handle static and dynamic ("pump") setups. * * RX/TX queue sizes currently fixed at one due to URB unlink problems. + * + * 10-oct-2000 + * usb_device_id table created. + * + * 28-oct-2000 + * misc fixes; mostly, discard more TTL-mangled rx packets. + * + * 01-nov-2000 + * usb_device_id table support added by Adam J. Richter . * *-------------------------------------------------------------------------*/ @@ -642,6 +653,7 @@ dbg ("waited for %d urb completions", temp); } dev->wait = 0; + current->state = TASK_RUNNING; remove_wait_queue (&unlink_wakeup, &wait); mutex_unlock (&dev->mutex); @@ -989,7 +1001,7 @@ // precondition: never called in_interrupt static void * -net1080_bind (struct usb_device *udev, unsigned ifnum, const struct usb_device_id *prod) +net1080_probe (struct usb_device *udev, unsigned ifnum, const struct usb_device_id *prod) { struct net1080 *dev; struct net_device *net; @@ -1073,7 +1085,7 @@ static struct usb_driver net1080_driver = { name: "net1080", id_table: products, - bind: net1080_bind, + probe: net1080_probe, disconnect: net1080_disconnect, }; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c --- v2.4.0-test10/linux/drivers/usb/ov511.c Sun Oct 8 10:50:30 2000 +++ linux/drivers/usb/ov511.c Sun Nov 12 20:45:19 2000 @@ -30,7 +30,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -static const char version[] = "1.25"; +static const char version[] = "1.28"; #define __NO_VERSION__ @@ -51,8 +51,6 @@ #include "ov511.h" -#undef OV511_GBR422 /* Experimental -- sets the 7610 to GBR422 */ - #define OV511_I2C_RETRIES 3 /* Video Size 640 x 480 x 3 bytes for RGB */ @@ -60,8 +58,6 @@ #define MAX_DATA_SIZE (MAX_FRAME_SIZE + sizeof(struct timeval)) #define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_GREY ? 256 : 384) -#define GET_DEPTH(p) ((p) == VIDEO_PALETTE_GREY ? 8 : \ - ((p) == VIDEO_PALETTE_YUV422 ? 16 : 24)) /* PARAMETER VARIABLES: */ static int autoadjust = 1; /* CCD dynamically changes exposure, etc... */ @@ -74,7 +70,7 @@ * 5=highly repetitive mesgs * NOTE: This should be changed to 0, 1, or 2 for production kernels */ -static int debug = 3; +static int debug = 0; /* Fix vertical misalignment of red and blue at 640x480 */ static int fix_rgb_offset = 0; @@ -112,6 +108,13 @@ /* Display test pattern - doesn't work yet either */ static int testpat = 0; +/* Setting this to 1 will make the sensor output GBR422 instead on YUV420. Only + * affects RGB24 mode. */ +static int sensor_gbr = 0; + +/* Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details. */ +static int dumppix = 0; + MODULE_PARM(autoadjust, "i"); MODULE_PARM_DESC(autoadjust, "CCD dynamically changes exposure"); MODULE_PARM(debug, "i"); @@ -138,6 +141,10 @@ MODULE_PARM_DESC(compress, "Turn on compression (not functional yet)"); MODULE_PARM(testpat, "i"); MODULE_PARM_DESC(testpat, "Replace image with vertical bar testpattern (only partially working)"); +MODULE_PARM(sensor_gbr, "i"); +MODULE_PARM_DESC(sensor_gbr, "Make sensor output GBR422 rather than YUV420"); +MODULE_PARM(dumppix, "i"); +MODULE_PARM_DESC(dumppix, "Dump raw pixel data, in one of 3 formats. See ov511_dumppix() for details"); MODULE_AUTHOR("Mark McClelland & Bret Wallach & Orion Sky Lawlor & Kevin Moore & Charl P. Botha & Claudio Matsuoka "); MODULE_DESCRIPTION("OV511 USB Camera Driver"); @@ -167,6 +174,15 @@ { -1, NULL } }; +static __devinitdata struct usb_device_id device_table [] = { + { idVendor: 0x05a9, idProduct: 0x0511 }, /* OV511 */ + { idVendor: 0x05a9, idProduct: 0xA511 }, /* OV511+ */ + { idVendor: 0x0813, idProduct: 0x0002 }, /* Intel Play Me2Cam OV511+ */ + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, device_table); + #if defined(CONFIG_PROC_FS) && defined(CONFIG_VIDEO_PROC_FS) static struct palette_list plist[] = { { VIDEO_PALETTE_GREY, "GREY" }, @@ -357,6 +373,7 @@ ov511->bridge == BRG_OV511PLUS ? "OV511+" : "unknown"); out += sprintf (out, "sensor : %s\n", + ov511->sensor == SEN_OV6620 ? "OV6620" : ov511->sensor == SEN_OV7610 ? "OV7610" : ov511->sensor == SEN_OV7620 ? "OV7620" : ov511->sensor == SEN_OV7620AE ? "OV7620AE" : @@ -448,7 +465,6 @@ } #endif /* CONFIG_PROC_FS && CONFIG_VIDEO_PROC_FS */ - /********************************************************************** * * Camera interface @@ -700,7 +716,7 @@ { int rc; - PDEBUG(3, "Reset: type=0x%X", reset_type); + PDEBUG(4, "Reset: type=0x%X", reset_type); rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type); rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0); @@ -829,14 +845,21 @@ } else if ((ov511->sensor == SEN_OV7620) || (ov511->sensor == SEN_OV7620AE)) { #if 0 - cur_con = ov511_i2c_read(dev, OV7610_REG_CNT); - cur_brt = ov511_i2c_read(dev, OV7610_REG_BRT); - // DEBUG_CODE - PDEBUG(1, "con=%d brt=%d", ov511_i2c_read(dev, OV7610_REG_CNT), - ov511_i2c_read(dev, OV7610_REG_BRT)); + int cur_sat, new_sat, tmp; - if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0) + cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE); + + tmp = (p->hue >> 8) - cur_sat; + new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp; + + PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp); + + if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0) return -EIO; + + // DEBUG_CODE + PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE)); + #endif } @@ -882,6 +905,23 @@ return 0; } +/* Returns number of bits per pixel (regardless of where they are located; planar or + * not), or zero for unsupported format. + */ +static int ov511_get_depth(int palette) +{ + switch (palette) { + case VIDEO_PALETTE_GREY: return 8; + case VIDEO_PALETTE_RGB565: return 16; + case VIDEO_PALETTE_RGB24: return 24; + case VIDEO_PALETTE_YUV422: return 16; + case VIDEO_PALETTE_YUYV: return 16; + case VIDEO_PALETTE_YUV420: return 24; + case VIDEO_PALETTE_YUV422P: return 24; /* Planar */ + default: return 0; /* Invalid format */ + } +} + /* LNCNT values fixed by Lawrence Glaister */ static struct mode_list mlist[] = { /* W H C PXCNT LNCNT PXDIV LNDIV M420 COMA COML */ @@ -917,6 +957,12 @@ if (ov511_stop(ov511->dev) < 0) return -EIO; + /* Dumppix only works with RGB24 */ + if (dumppix && (mode != VIDEO_PALETTE_RGB24)) { + err("dumppix only supported with RGB 24"); + return -EINVAL; + } + if (mode == VIDEO_PALETTE_GREY) { ov511_reg_write(dev, 0x16, 0x00); if (ov511->sensor == SEN_OV7610 @@ -953,9 +999,9 @@ break; case SEN_OV6620: hwsbase = 0x38; - hwebase = 0x39; - vwsbase = 0x03; - vwebase = 0x04; + hwebase = 0x3a; + vwsbase = 0x05; + vwebase = 0x06; break; case SEN_OV7620: hwsbase = 0x2c; @@ -1039,13 +1085,16 @@ /* Calculate and set the clock divisor */ clock = ((sub_flag ? ov511->subw * ov511->subh : width * height) * (mlist[i].color ? 3 : 2) / 2) / 66000; +#if 0 + clock *= cams; +#endif ov511_i2c_write(dev, 0x11, clock); -#ifdef OV511_GBR422 - ov511_i2c_write(dev, 0x12, mlist[i].common_A | 0x08); -#else - ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00)); -#endif + /* We only have code to convert GBR -> RGB24 */ + if ((mode == VIDEO_PALETTE_RGB24) && sensor_gbr) + ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x0a:0x08)); + else + ov511_i2c_write(dev, 0x12, mlist[i].common_A | (testpat?0x02:0x00)); /* 7620/6620 don't have register 0x35, so play it safe */ if (ov511->sensor == SEN_OV7610 || @@ -1113,7 +1162,7 @@ static inline void ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, - int rowPixels, unsigned char * rgb) + int rowPixels, unsigned char * rgb, int bits) { const int rvScale = 91881; const int guScale = -22553; @@ -1134,14 +1183,32 @@ yTL *= yScale; yTR *= yScale; yBL *= yScale; yBR *= yScale; - /* Write out top two pixels */ - rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL); - rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR); - - /* Skip down to next line to write out bottom two pixels */ - rgb += 3 * rowPixels; - rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL); - rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR); + if (bits == 24) { + /* Write out top two pixels */ + rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL); + rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR); + + /* Skip down to next line to write out bottom two pixels */ + rgb += 3 * rowPixels; + rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL); + rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR); + } else if (bits == 16) { + /* Write out top two pixels */ + rgb[0] = ((LIMIT(b+yTL) >> 3) & 0x1F) | ((LIMIT(g+yTL) << 3) & 0xE0); + rgb[1] = ((LIMIT(g+yTL) >> 5) & 0x07) | (LIMIT(r+yTL) & 0xF8); + + rgb[2] = ((LIMIT(b+yTR) >> 3) & 0x1F) | ((LIMIT(g+yTR) << 3) & 0xE0); + rgb[3] = ((LIMIT(g+yTR) >> 5) & 0x07) | (LIMIT(r+yTR) & 0xF8); + + /* Skip down to next line to write out bottom two pixels */ + rgb += 2 * rowPixels; + + rgb[0] = ((LIMIT(b+yBL) >> 3) & 0x1F) | ((LIMIT(g+yBL) << 3) & 0xE0); + rgb[1] = ((LIMIT(g+yBL) >> 5) & 0x07) | (LIMIT(r+yBL) & 0xF8); + + rgb[2] = ((LIMIT(b+yBR) >> 3) & 0x1F) | ((LIMIT(g+yBR) << 3) & 0xE0); + rgb[3] = ((LIMIT(g+yBR) >> 5) & 0x07) | (LIMIT(r+yBR) & 0xF8); + } } /* @@ -1167,7 +1234,7 @@ * Note that the U and V data in one segment represents a 16 x 16 pixel * area, but the Y data represents a 32 x 8 pixel area. * - * If OV511_DUMPPIX is defined, _parse_data just dumps the incoming segments, + * If dumppix module param is set, _parse_data just dumps the incoming segments, * verbatim, in order, into the frame. When used with vidcat -f ppm -s 640x480 * this puts the data on the standard output and can be analyzed with the * parseppm.c utility I wrote. That's a much faster way for figuring out how @@ -1177,14 +1244,8 @@ #define HDIV 8 #define WDIV (256/HDIV) -#undef OV511_DUMPPIX - -/* #define this and OV511_DUMPPIX to disable parsing of UV data */ -#undef OV511_FORCE_MONO - -#ifdef OV511_GBR422 static void -ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0, +ov511_parse_gbr422_to_rgb24(unsigned char *pIn0, unsigned char *pOut0, int iOutY, int iOutUV, int iHalf, int iWidth) { int k, l, m; @@ -1231,14 +1292,12 @@ } } -#else - static void -ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0, - int iOutY, int iOutUV, int iHalf, int iWidth) +ov511_parse_yuv420_to_rgb(unsigned char *pIn0, unsigned char *pOut0, + int iOutY, int iOutUV, int iHalf, int iWidth, int bits) { -#ifndef OV511_DUMPPIX int k, l, m; + int bytes = bits >> 3; unsigned char *pIn; unsigned char *pOut, *pOut1; @@ -1251,11 +1310,11 @@ for (l = 0; l < 8; l++) { for (m = 0; m < 8; m++) { *pOut1 = *pIn++; - pOut1 += 3; + pOut1 += bytes; } - pOut1 += (iWidth - 8) * 3; + pOut1 += (iWidth - 8) * bytes; } - pOut += 8 * 3; + pOut += 8 * bytes; } } @@ -1265,16 +1324,16 @@ for (l = 0; l < 4; l++) { for (m=0; m<8; m++) { int y00 = *(pOut); - int y01 = *(pOut+3); - int y10 = *(pOut+iWidth*3); - int y11 = *(pOut+iWidth*3+3); + int y01 = *(pOut+bytes); + int y10 = *(pOut+iWidth*bytes); + int y11 = *(pOut+iWidth*bytes+bytes); int v = *(pIn+64) - 128; int u = *pIn++ - 128; ov511_move_420_block(y00, y01, y10, y11, u, v, iWidth, - pOut); - pOut += 6; + pOut, bits); + pOut += 2 * bytes; } - pOut += (iWidth*2 - 16) * 3; + pOut += (iWidth*2 - 16) * bytes; } /* Just copy the other UV rows */ @@ -1282,9 +1341,9 @@ for (m = 0; m < 8; m++) { *pOut++ = *(pIn + 64); *pOut = *pIn++; - pOut += 5; + pOut += 2 * bytes - 1; } - pOut += (iWidth*2 - 16) * 3; + pOut += (iWidth*2 - 16) * bytes; } /* Calculate values if it's the second half */ @@ -1302,72 +1361,65 @@ int v = *pOut1 - 128; int u = *(pOut1+1) - 128; ov511_move_420_block(y00, y01, y10, - y11, u, v, iWidth, pOut1); - pOut1 += 6; + y11, u, v, iWidth, pOut1, bits); + pOut1 += 2 * bytes; } - pOut1 += (iWidth*2 - 8) * 3; + pOut1 += (iWidth*2 - 8) * bytes; pIn += 8; } - pOut += 8 * 3; + pOut += 8 * bytes; } } -#else +} -#ifndef OV511_FORCE_MONO - /* Just dump pix data straight out for debug */ - int i, j; - - pOut0 += iOutY; - for (i = 0; i < HDIV; i++) { - for (j = 0; j < WDIV; j++) { - *pOut0++ = *pIn0++; - *pOut0++ = *pIn0++; - *pOut0++ = *pIn0++; - } - pOut0 += (iWidth - WDIV) * 3; - } -#else - -#if 1 - /* This converts the Y data to "black-and-white" RGB data */ - /* Useful for experimenting with compression */ - int k, l, m; +static void +ov511_dumppix(unsigned char *pIn0, unsigned char *pOut0, + int iOutY, int iOutUV, int iHalf, int iWidth) +{ + int i, j, k; unsigned char *pIn, *pOut, *pOut1; - pIn = pIn0 + 128; - pOut = pOut0 + iOutY; - for (k = 0; k < 4; k++) { - pOut1 = pOut; - for (l = 0; l < 8; l++) { - for (m = 0; m < 8; m++) { - *pOut1++ = *pIn; - *pOut1++ = *pIn; - *pOut1++ = *pIn++; + switch (dumppix) { + case 1: /* Just dump YUV data straight out for debug */ + pOut0 += iOutY; + for (i = 0; i < HDIV; i++) { + for (j = 0; j < WDIV; j++) { + *pOut0++ = *pIn0++; + *pOut0++ = *pIn0++; + *pOut0++ = *pIn0++; } - pOut1 += (iWidth - 8) * 3; + pOut0 += (iWidth - WDIV) * 3; } - pOut += 8 * 3; - } -#else - /* This will dump the Y channel data stream as-is */ - int count; - unsigned char *pIn, *pOut; - - pIn = pIn0 + 128; - pOut = pOut0 + output_offset; - for (count = 0; count < 256; count++) { - *pOut++ = *pIn; - *pOut++ = *pIn; - *pOut++ = *pIn++; - output_offset += 3; - } -#endif - -#endif - -#endif + break; + case 2: /* This converts the Y data to "black-and-white" RGB data */ + /* Useful for experimenting with compression */ + pIn = pIn0 + 128; + pOut = pOut0 + iOutY; + for (i = 0; i < 4; i++) { + pOut1 = pOut; + for (j = 0; j < 8; j++) { + for (k = 0; k < 8; k++) { + *pOut1++ = *pIn; + *pOut1++ = *pIn; + *pOut1++ = *pIn++; + } + pOut1 += (iWidth - 8) * 3; + } + pOut += 8 * 3; + } + break; + case 3: /* This will dump only the Y channel data stream as-is */ + pIn = pIn0 + 128; + pOut = pOut0 + output_offset; + for (i = 0; i < 256; i++) { + *pOut++ = *pIn; + *pOut++ = *pIn; + *pOut++ = *pIn++; + output_offset += 3; + } + break; + } /* End switch (dumppix) */ } -#endif /* This converts YUV420 segments to YUYV */ static void @@ -1662,6 +1714,11 @@ /* Frame start */ PDEBUG(4, "Frame start, framenum = %d", ov511->curframe); +#if 0 + /* Make sure no previous data carries over; necessary + * for compression experimentation */ + memset(frame->data, 0, MAX_DATA_SIZE); +#endif output_offset = 0; /* Check to see if it's a snapshot frame */ @@ -1740,8 +1797,19 @@ ov511_parse_data_grey (pData, pOut, iOutY, frame->width); break; case VIDEO_PALETTE_RGB24: - ov511_parse_data_rgb24 (pData, pOut, iOutY, iOutUV, - iY & 1, frame->width); + if (dumppix) + ov511_dumppix(pData, pOut, iOutY, iOutUV, + iY & 1, frame->width); + else if (sensor_gbr) + ov511_parse_gbr422_to_rgb24(pData, pOut, iOutY, iOutUV, + iY & 1, frame->width); + else + ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV, + iY & 1, frame->width, 24); + break; + case VIDEO_PALETTE_RGB565: + ov511_parse_yuv420_to_rgb(pData, pOut, iOutY, iOutUV, + iY & 1, frame->width, 16); break; case VIDEO_PALETTE_YUV422: case VIDEO_PALETTE_YUYV: @@ -1782,11 +1850,20 @@ static void ov511_isoc_irq(struct urb *urb) { int len; - struct usb_ov511 *ov511 = urb->context; + struct usb_ov511 *ov511; struct ov511_sbuf *sbuf; - if (!ov511->dev) + if (!urb->context) { + PDEBUG(4, "no context"); + return; + } + + ov511 = (struct usb_ov511 *) urb->context; + + if (!ov511->dev || !ov511->user) { + PDEBUG(4, "no device, or not open"); return; + } if (!ov511->streaming) { PDEBUG(4, "hmmm... not streaming, but got interrupt"); @@ -1805,6 +1882,8 @@ /* Move to the next sbuf */ ov511->cursbuf = (ov511->cursbuf + 1) % OV511_NUMSBUF; + urb->dev = ov511->dev; + return; } @@ -1872,6 +1951,7 @@ ov511->sbuf[n].urb->next = ov511->sbuf[n+1].urb; for (n = 0; n < OV511_NUMSBUF; n++) { + ov511->sbuf[n].urb->dev = ov511->dev; err = usb_submit_urb(ov511->sbuf[n].urb); if (err) err("init isoc: usb_submit_urb(%d) ret %d", n, err); @@ -2079,7 +2159,7 @@ static int ov511_open(struct video_device *dev, int flags) { struct usb_ov511 *ov511 = (struct usb_ov511 *)dev; - int err = 0; + int err; MOD_INC_USE_COUNT; PDEBUG(4, "opening"); @@ -2174,8 +2254,8 @@ b.audios = 0; b.maxwidth = ov511->maxwidth; b.maxheight = ov511->maxheight; - b.minwidth = 32; - b.minheight = 16; + b.minwidth = 160; + b.minheight = 120; if (copy_to_user(arg, &b, sizeof(b))) return -EFAULT; @@ -2237,12 +2317,7 @@ if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; - if (p.palette != VIDEO_PALETTE_GREY && - p.palette != VIDEO_PALETTE_RGB24 && - p.palette != VIDEO_PALETTE_YUV422 && - p.palette != VIDEO_PALETTE_YUYV && - p.palette != VIDEO_PALETTE_YUV420 && - p.palette != VIDEO_PALETTE_YUV422P) + if (!ov511_get_depth(p.palette)) return -EINVAL; if (ov7610_set_picture(ov511, &p)) @@ -2373,7 +2448,7 @@ case VIDIOCMCAPTURE: { struct video_mmap vm; - int ret; + int ret, depth; if (copy_from_user((void *)&vm, (void *)arg, sizeof(vm))) return -EFAULT; @@ -2382,19 +2457,21 @@ PDEBUG(4, "frame: %d, size: %dx%d, format: %d", vm.frame, vm.width, vm.height, vm.format); - if (vm.format != VIDEO_PALETTE_RGB24 && - vm.format != VIDEO_PALETTE_YUV422 && - vm.format != VIDEO_PALETTE_YUYV && - vm.format != VIDEO_PALETTE_YUV420 && - vm.format != VIDEO_PALETTE_YUV422P && - vm.format != VIDEO_PALETTE_GREY) + depth = ov511_get_depth(vm.format); + if (!depth) { + err("VIDIOCMCAPTURE: invalid format (%d)", vm.format); return -EINVAL; + } - if ((vm.frame != 0) && (vm.frame != 1)) + if ((vm.frame != 0) && (vm.frame != 1)) { + err("VIDIOCMCAPTURE: invalid frame (%d)", vm.frame); return -EINVAL; - - if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight) + } + + if (vm.width > ov511->maxwidth || vm.height > ov511->maxheight) { + err("VIDIOCMCAPTURE: requested dimensions too big"); return -EINVAL; + } if (ov511->frame[vm.frame].grabstate == FRAME_GRABBING) return -EBUSY; @@ -2422,7 +2499,7 @@ ov511->frame[vm.frame].format = vm.format; ov511->frame[vm.frame].sub_flag = ov511->sub_flag; ov511->frame[vm.frame].segsize = GET_SEGSIZE(vm.format); - ov511->frame[vm.frame].depth = GET_DEPTH(vm.format); + ov511->frame[vm.frame].depth = depth; /* Mark it as ready */ ov511->frame[vm.frame].grabstate = FRAME_READY; @@ -2481,6 +2558,13 @@ goto redo; } case FRAME_DONE: + if (ov511->snap_enabled && !ov511->frame[frame].snapshot) { + int ret; + if ((ret = ov511_new_frame(ov511, frame)) < 0) + return ret; + goto redo; + } + ov511->frame[frame].grabstate = FRAME_UNUSED; /* Reset the hardware snapshot button */ @@ -2657,7 +2741,7 @@ PDEBUG(4, "mmap: %ld (%lX) bytes", size, size); - if (size > (((2 * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) + if (size > (((OV511_NUMFRAMES * MAX_DATA_SIZE) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))) return -EINVAL; pos = (unsigned long)ov511->fbuf; @@ -3057,7 +3141,7 @@ init_waitqueue_head(&ov511->wq); - if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) == -1) { + if (video_register_device(&ov511->vdev, VFL_TYPE_GRABBER) < 0) { err("video_register_device failed"); return -EBUSY; } @@ -3144,7 +3228,9 @@ * ***************************************************************************/ -static void* ov511_probe(struct usb_device *dev, unsigned int ifnum) +static void * __devinit +ov511_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_interface_descriptor *interface; struct usb_ov511 *ov511; @@ -3158,17 +3244,8 @@ interface = &dev->actconfig->interface[ifnum].altsetting[0]; - /* Is it an OV511/OV511+? */ - if (dev->descriptor.idVendor != 0x05a9 - && dev->descriptor.idVendor != 0x0813) - return NULL; - if (dev->descriptor.idProduct != 0x0511 - && dev->descriptor.idProduct != 0xA511 - && dev->descriptor.idProduct != 0x0002) - return NULL; - /* Checking vendor/product should be enough, but what the hell */ - if (interface->bInterfaceClass != 0xFF) + if (interface->bInterfaceClass != 0xFF) return NULL; if (interface->bInterfaceSubClass != 0x00) return NULL; @@ -3263,7 +3340,8 @@ } -static void ov511_disconnect(struct usb_device *dev, void *ptr) +static void __devexit +ov511_disconnect(struct usb_device *dev, void *ptr) { struct usb_ov511 *ov511 = (struct usb_ov511 *) ptr; int n; @@ -3321,10 +3399,10 @@ } static struct usb_driver ov511_driver = { - "ov511", - ov511_probe, - ov511_disconnect, - { NULL, NULL } + name: "ov511", + id_table: device_table, + probe: ov511_probe, + disconnect: ov511_disconnect }; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c --- v2.4.0-test10/linux/drivers/usb/pegasus.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/pegasus.c Tue Nov 14 12:57:50 2000 @@ -40,7 +40,6 @@ */ -#include #include #include #include @@ -48,162 +47,44 @@ #include #include #include - - -static const char *version = __FILE__ ": v0.4.13 2000/10/13 (C) 1999-2000 Petko Manolov (petkan@dce.bg)"; +#include +#include "pegasus.h" #define PEGASUS_USE_INTR +#define PEGASUS_WRITE_EEPROM +static const char *version = __FILE__ ": v0.4.17 2000/11/13 (C) 1999-2000 Petko Manolov (petkan@dce.bg)"; -#define PEGASUS_II 0x80000000 -#define HAS_HOME_PNA 0x40000000 -#define PEGASUS_MTU 1500 -#define PEGASUS_MAX_MTU 1536 +static int loopback = 0; +static int mii_mode = 0; +static int multicast_filter_limit = 32; -#define EPROM_WRITE 0x01 -#define EPROM_READ 0x02 -#define EPROM_DONE 0x04 -#define EPROM_WR_ENABLE 0x10 -#define EPROM_LOAD 0x20 - -#define MII_BMCR 0x00 -#define MII_BMSR 0x01 -#define BMSR_MEDIA 0x7808 -#define MII_ANLPA 0x05 -#define ANLPA_100TX_FD 0x0100 -#define ANLPA_100TX_HD 0x0080 -#define ANLPA_10T_FD 0x0040 -#define ANLPA_10T_HD 0x0020 -#define PHY_DONE 0x80 -#define PHY_READ 0x40 -#define PHY_WRITE 0x20 -#define DEFAULT_GPIO_RESET 0x24 -#define LINKSYS_GPIO_RESET 0x24 -#define DEFAULT_GPIO_SET 0x26 - -#define PEGASUS_PRESENT 0x00000001 -#define PEGASUS_RUNNING 0x00000002 -#define PEGASUS_TX_BUSY 0x00000004 -#define PEGASUS_RX_BUSY 0x00000008 -#define CTRL_URB_RUNNING 0x00000010 -#define CTRL_URB_SLEEP 0x00000020 -#define PEGASUS_UNPLUG 0x00000040 -#define ETH_REGS_CHANGE 0x40000000 -#define ETH_REGS_CHANGED 0x80000000 - -#define RX_MULTICAST 2 -#define RX_PROMISCUOUS 4 - -#define REG_TIMEOUT (HZ) -#define PEGASUS_TX_TIMEOUT (HZ*10) - -#define TX_UNDERRUN 0x80 -#define EXCESSIVE_COL 0x40 -#define LATE_COL 0x20 -#define NO_CARRIER 0x10 -#define LOSS_CARRIER 0x08 -#define JABBER_TIMEOUT 0x04 - -#define PEGASUS_REQT_READ 0xc0 -#define PEGASUS_REQT_WRITE 0x40 -#define PEGASUS_REQ_GET_REGS 0xf0 -#define PEGASUS_REQ_SET_REGS 0xf1 -#define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS -#define NUM_CTRL_URBS 0x10 -#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES))) - -enum pegasus_registers { - EthCtrl0 = 0, - EthCtrl1 = 1, - EthCtrl2 = 2, - EthID = 0x10, - Reg1d = 0x1d, - EpromOffset = 0x20, - EpromData = 0x21, /* 0x21 low, 0x22 high byte */ - EpromCtrl = 0x23, - PhyAddr = 0x25, - PhyData = 0x26, /* 0x26 low, 0x27 high byte */ - PhyCtrl = 0x28, - UsbStst = 0x2a, - EthTxStat0 = 0x2b, - EthTxStat1 = 0x2c, - EthRxStat = 0x2d, - Reg7b = 0x7b, - Gpio0 = 0x7e, - Gpio1 = 0x7f, - Reg81 = 0x81, +static struct usb_eth_dev usb_dev_id[] = { +#define PEGASUS_DEV(pn, vid, pid, flags) \ + {name:pn, vendor:vid, device:pid, private:flags}, +#include "pegasus.h" +#undef PEGASUS_DEV + {NULL, 0, 0, 0} }; - -typedef struct pegasus { - struct usb_device *usb; - struct net_device *net; - struct net_device_stats stats; - unsigned flags; - unsigned features; - int intr_interval; - struct urb ctrl_urb, rx_urb, tx_urb, intr_urb; - devrequest dr; - wait_queue_head_t ctrl_wait; - struct semaphore ctrl_sem; - unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]); - unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]); - unsigned char ALIGN(intr_buff[8]); - __u8 eth_regs[4]; - __u8 phy; - __u8 gpio_res; -} pegasus_t; - -struct usb_eth_dev { - char *name; - __u16 vendor; - __u16 device; - __u32 private; /* LSB is gpio reset value */ +static struct usb_device_id pegasus_ids[] = { +#define PEGASUS_DEV(pn, vid, pid, flags) {idVendor:vid, idProduct:pid}, +#include "pegasus.h" +#undef PEGASUS_DEV + { } }; -static int loopback = 0; -static int mii_mode = 0; -static int multicast_filter_limit = 32; - - MODULE_AUTHOR("Petko Manolov "); MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver"); MODULE_PARM(loopback, "i"); -MODULE_PARM(mode, "i"); +MODULE_PARM(mii_mode, "i"); MODULE_PARM_DESC(loopback, "Enable MAC loopback mode (bit 0)"); -MODULE_PARM_DESC(mode, "Enable HomePNA mode (bit 0) - default = MII mode = 0"); +MODULE_PARM_DESC(mii_mode, "Enable HomePNA mode (bit 0),default=MII mode = 0"); - -static struct usb_eth_dev usb_dev_id[] = { - {"Billionton USB-100", 0x08dd, 0x0986, DEFAULT_GPIO_RESET}, - {"Corega FEter USB-TX", 0x7aa, 0x0004, DEFAULT_GPIO_RESET}, - {"MELCO/BUFFALO LUA-TX", 0x0411, 0x0001, DEFAULT_GPIO_RESET}, - {"D-Link DSB-650TX", 0x2001, 0x4001, LINKSYS_GPIO_RESET}, - {"D-Link DSB-650TX", 0x2001, 0x4002, LINKSYS_GPIO_RESET}, - {"D-Link DSB-650TX(PNA)", 0x2001, 0x4003, - HAS_HOME_PNA | DEFAULT_GPIO_RESET}, - {"D-Link DSB-650", 0x2001, 0xabc1, DEFAULT_GPIO_RESET}, - {"D-Link DU-E10", 0x07b8, 0xabc1, DEFAULT_GPIO_RESET}, - {"D-Link DU-E100", 0x07b8, 0x4002, DEFAULT_GPIO_RESET}, - {"Linksys USB10TX", 0x066b, 0x2202, LINKSYS_GPIO_RESET}, - {"Linksys USB100TX", 0x066b, 0x2203, LINKSYS_GPIO_RESET}, - {"Linksys USB100TX", 0x066b, 0x2204, HAS_HOME_PNA | LINKSYS_GPIO_RESET}, - {"Linksys USB Ethernet Adapter", 0x066b, 0x2206, LINKSYS_GPIO_RESET}, - {"SMC 202 USB Ethernet", 0x0707, 0x0200, DEFAULT_GPIO_RESET}, - {"ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", 0x07a6, 0x0986, - HAS_HOME_PNA | DEFAULT_GPIO_RESET}, - {"Accton USB 10/100 Ethernet Adapter", 0x083a, 0x1046, - DEFAULT_GPIO_RESET}, - {"IO DATA USB ET/TX", 0x04bb, 0x0904, DEFAULT_GPIO_RESET}, - {"LANEED USB Ethernet LD-USB/TX", 0x056e, 0x4002, DEFAULT_GPIO_RESET}, - {"SOHOware NUB100 Ethernet", 0x15e8, 0x9100, DEFAULT_GPIO_RESET}, - {"ADMtek ADM8511 \"Pegasus II\" USB Ethernet", 0x07a6, 0x8511, - PEGASUS_II | DEFAULT_GPIO_RESET}, - {NULL, 0, 0, 0} -}; +MODULE_DEVICE_TABLE (usb, pegasus_ids); static int update_eth_regs_async( pegasus_t * ); @@ -243,7 +124,7 @@ { int ret; - if ( pegasus->flags & ETH_REGS_CHANGED ) { + while ( pegasus->flags & ETH_REGS_CHANGED ) { pegasus->flags |= CTRL_URB_SLEEP; interruptible_sleep_on( &pegasus->ctrl_wait ); } @@ -274,7 +155,7 @@ { int ret; - if ( pegasus->flags & ETH_REGS_CHANGED ) { + while ( pegasus->flags & ETH_REGS_CHANGED ) { pegasus->flags |= CTRL_URB_SLEEP ; interruptible_sleep_on( &pegasus->ctrl_wait ); } @@ -305,7 +186,7 @@ { int ret; - if ( pegasus->flags & ETH_REGS_CHANGED ) { + while ( pegasus->flags & ETH_REGS_CHANGED ) { pegasus->flags |= CTRL_URB_SLEEP; interruptible_sleep_on( &pegasus->ctrl_wait ); } @@ -354,7 +235,7 @@ } -static int read_phy_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd ) +static int read_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 *regd ) { int i; __u8 data[4] = { phy, 0, 0, indx }; @@ -377,7 +258,7 @@ } -static int write_phy_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd ) +static int write_mii_word( pegasus_t *pegasus, __u8 phy, __u8 indx, __u16 regd ) { int i; __u8 data[4] = { phy, 0, 0, indx }; @@ -505,6 +386,15 @@ } if ( i == REG_TIMEOUT ) return 1; + + if ( usb_dev_id[pegasus->dev_index].vendor == VENDOR_LINKSYS || + usb_dev_id[pegasus->dev_index].vendor == VENDOR_DLINK1 ) { + __u16 auxmode; + + read_mii_word( pegasus, 0, 0x1b, &auxmode ); + write_mii_word( pegasus, 0, 0x1b, auxmode | 4 ); + } + return 0; } @@ -516,13 +406,13 @@ pegasus_t *pegasus = dev->priv; - if ( read_phy_word(pegasus, pegasus->phy, MII_BMSR, &bmsr) ) - return 2; + if ( read_mii_word(pegasus, pegasus->phy, MII_BMSR, &bmsr) ) + return 1; if ( !(bmsr & 0x20) && !loopback ) warn( "%s: link NOT established (0x%x) - check the cable.", dev->name, bmsr ); - if ( read_phy_word(pegasus, pegasus->phy, MII_ANLPA, &linkpart) ) - return 4; + if ( read_mii_word(pegasus, pegasus->phy, MII_ANLPA, &linkpart) ) + return 2; if ( !(linkpart & 1) ) warn( "link partner stat %x", linkpart ); @@ -536,7 +426,7 @@ data[1] = 0; data[2] = (loopback & 1) ? 0x09 : 0x01; - *(unsigned *)pegasus->eth_regs = *(unsigned *)data; + memcpy( pegasus->eth_regs, data, sizeof(data) ); set_registers( pegasus, EthCtrl0, 3, data ); @@ -562,23 +452,29 @@ if ( pegasus->flags & PEGASUS_RX_BUSY ) { pegasus->stats.rx_errors++; + dbg("pegasus Rx busy"); return; } pegasus->flags |= PEGASUS_RX_BUSY; - rx_status = *(int *)(pegasus->rx_buff + count - 4); - - if (urb->status) { - dbg("%s: RX status %d", net->name, urb->status); - goto goon; + switch ( urb->status ) { + case USB_ST_NOERROR: + break; + case USB_ST_NORESPONSE: + dbg( "reset MAC" ); + pegasus->flags &= ~PEGASUS_RX_BUSY; + break; + default: + dbg( "%s: RX status %d", net->name, urb->status ); + goto goon; } if ( !count ) goto goon; + rx_status = *(int *)(pegasus->rx_buff + count - 4); if ( rx_status & 0x000e0000 ) { - - dbg("%s: error receiving packet %x", net->name, rx_status & 0xe0000); + dbg("%s: RX packet error %x", net->name, rx_status & 0xe0000); pegasus->stats.rx_errors++; if ( rx_status & 0x060000 ) pegasus->stats.rx_length_errors++; @@ -586,7 +482,6 @@ pegasus->stats.rx_crc_errors++; if ( rx_status & 0x100000 ) pegasus->stats.rx_frame_errors++; - goto goon; } @@ -629,6 +524,7 @@ if ( urb->status ) info("%s: TX status %d", pegasus->net->name, urb->status); + pegasus->net->trans_start = jiffies; netif_wake_queue( pegasus->net ); } @@ -641,6 +537,16 @@ if ( !pegasus ) return; + + switch ( urb->status ) { + case USB_ST_NOERROR: + break; + case USB_ST_URB_KILLED: + return; + default: + info("intr status %d", urb->status); + } + d = urb->transfer_buffer; net = pegasus->net; if ( d[0] & 0xfc ) { @@ -654,31 +560,23 @@ if ( d[0] & (NO_CARRIER | LOSS_CARRIER) ) pegasus->stats.tx_carrier_errors++; } - switch ( urb->status ) { - case USB_ST_NOERROR: - break; - case USB_ST_URB_KILLED: - break; - default: - info("intr status %d", urb->status); - } } #endif +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,48) static void pegasus_tx_timeout( struct net_device *net ) { pegasus_t *pegasus = net->priv; if ( !pegasus ) return; - - usb_unlink_urb( &pegasus->tx_urb ); + warn("%s: Tx timed out.", net->name); + pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK; + usb_unlink_urb( &pegasus->tx_urb ); pegasus->stats.tx_errors++; - net->trans_start = jiffies; - - netif_wake_queue( net ); } +#endif static int pegasus_start_xmit( struct sk_buff *skb, struct net_device *net ) @@ -696,7 +594,6 @@ pegasus->tx_buff, PEGASUS_MAX_MTU, write_bulk_callback, pegasus ); pegasus->tx_urb.transfer_buffer_length = count; - pegasus->tx_urb.transfer_flags |= USB_ASYNC_UNLINK; if ((res = usb_submit_urb(&pegasus->tx_urb))) { warn("failed tx_urb %d", res); pegasus->stats.tx_errors++; @@ -732,6 +629,14 @@ __u8 data[2]; read_eprom_word( pegasus, 4, (__u16 *)data ); + if ( data[1] < 0x80 ) { + info( "intr interval will be changed from %ums to %ums", + data[1], 0x80 ); + data[1] = 0x80; +#ifdef PEGASUS_WRITE_EEPROM + write_eprom_word( pegasus, 4, *(__u16 *)data ); +#endif + } pegasus->intr_interval = data[1]; } @@ -754,7 +659,6 @@ if ( (res = usb_submit_urb(&pegasus->rx_urb)) ) warn( __FUNCTION__ " failed rx_urb %d", res ); #ifdef PEGASUS_USE_INTR - get_interrupt_interval( pegasus ); FILL_INT_URB( &pegasus->intr_urb, pegasus->usb, usb_rcvintpipe(pegasus->usb, 3), pegasus->intr_buff, sizeof(pegasus->intr_buff), @@ -781,8 +685,9 @@ usb_unlink_urb( &pegasus->rx_urb ); usb_unlink_urb( &pegasus->tx_urb ); usb_unlink_urb( &pegasus->ctrl_urb ); +#ifdef PEGASUS_USE_INTR usb_unlink_urb( &pegasus->intr_urb ); - +#endif MOD_DEC_USE_COUNT; return 0; @@ -798,12 +703,12 @@ case SIOCDEVPRIVATE: data[0] = pegasus->phy; case SIOCDEVPRIVATE+1: - read_phy_word(pegasus, data[0], data[1]&0x1f, &data[3]); + read_mii_word(pegasus, data[0], data[1]&0x1f, &data[3]); return 0; case SIOCDEVPRIVATE+2: if ( !capable(CAP_NET_ADMIN) ) return -EPERM; - write_phy_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]); + write_mii_word(pegasus, pegasus->phy, data[1] & 0x1f, data[2]); return 0; default: return -EOPNOTSUPP; @@ -838,34 +743,20 @@ } -static int check_device_ids( __u16 vendor, __u16 product ) -{ - int i=0; - - while ( usb_dev_id[i].name ) { - if ( (usb_dev_id[i].vendor == vendor) && - (usb_dev_id[i].device == product) ) - return i; - i++; - } - return -1; -} - - static __u8 mii_phy_probe( pegasus_t *pegasus ) { int i; __u16 tmp; for ( i=0; i < 32; i++ ) { - read_phy_word( pegasus, i, MII_BMSR, &tmp ); + read_mii_word( pegasus, i, MII_BMSR, &tmp ); if ( tmp == 0 || tmp == 0xffff || (tmp & BMSR_MEDIA) == 0 ) continue; else return i; } - return 0; + return 0xff; } @@ -880,15 +771,12 @@ } -static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum ) +static void * pegasus_probe( struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { - struct net_device *net; - pegasus_t *pegasus; - int dev_indx; - - if ( (dev_indx = check_device_ids(dev->descriptor.idVendor, dev->descriptor.idProduct)) == -1 ) { - return NULL; - } + struct net_device *net; + pegasus_t *pegasus; + int dev_index = id - pegasus_ids; if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) { err("usb_set_configuration() failed"); @@ -902,7 +790,7 @@ usb_inc_dev_use( dev ); memset(pegasus, 0, sizeof(struct pegasus)); - init_MUTEX( &pegasus-> ctrl_sem ); + pegasus->dev_index = dev_index; init_waitqueue_head( &pegasus->ctrl_wait ); net = init_etherdev( NULL, 0 ); @@ -926,7 +814,10 @@ net->get_stats = pegasus_netdev_stats; net->mtu = PEGASUS_MTU; - pegasus->features = usb_dev_id[dev_indx].private; + pegasus->features = usb_dev_id[dev_index].private; +#ifdef PEGASUS_USE_INTR + get_interrupt_interval( pegasus ); +#endif if ( reset_mac(pegasus) ) { err("can't reset MAC"); unregister_netdev( pegasus->net ); @@ -935,21 +826,21 @@ return NULL; } + info( "%s: %s", net->name, usb_dev_id[dev_index].name ); + set_ethernet_addr( pegasus ); - + if ( pegasus->features & PEGASUS_II ) { info( "setup Pegasus II specific registers" ); setup_pegasus_II( pegasus ); } pegasus->phy = mii_phy_probe( pegasus ); - if ( !pegasus->phy ) { + if ( pegasus->phy == 0xff ) { warn( "can't locate MII phy, using default" ); pegasus->phy = 1; } - info( "%s: %s", net->name, usb_dev_id[dev_indx].name ); - return pegasus; } @@ -975,6 +866,7 @@ name: "pegasus", probe: pegasus_probe, disconnect: pegasus_disconnect, + id_table: pegasus_ids, }; int __init pegasus_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/pegasus.h linux/drivers/usb/pegasus.h --- v2.4.0-test10/linux/drivers/usb/pegasus.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/pegasus.h Tue Nov 14 12:57:50 2000 @@ -0,0 +1,198 @@ +/* + * Copyright (c) 1999,2000 Petko Manolov - Petkan (petkan@dce.bg) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +#ifndef PEGASUS_DEV + +#define PEGASUS_II 0x80000000 +#define HAS_HOME_PNA 0x40000000 + +#define PEGASUS_MTU 1500 +#define PEGASUS_MAX_MTU 1536 + +#define EPROM_WRITE 0x01 +#define EPROM_READ 0x02 +#define EPROM_DONE 0x04 +#define EPROM_WR_ENABLE 0x10 +#define EPROM_LOAD 0x20 + +#define MII_BMCR 0x00 +#define MII_BMSR 0x01 +#define BMSR_MEDIA 0x7808 +#define MII_ANLPA 0x05 +#define ANLPA_100TX_FD 0x0100 +#define ANLPA_100TX_HD 0x0080 +#define ANLPA_10T_FD 0x0040 +#define ANLPA_10T_HD 0x0020 +#define PHY_DONE 0x80 +#define PHY_READ 0x40 +#define PHY_WRITE 0x20 +#define DEFAULT_GPIO_RESET 0x24 +#define LINKSYS_GPIO_RESET 0x24 +#define DEFAULT_GPIO_SET 0x26 + +#define PEGASUS_PRESENT 0x00000001 +#define PEGASUS_RUNNING 0x00000002 +#define PEGASUS_TX_BUSY 0x00000004 +#define PEGASUS_RX_BUSY 0x00000008 +#define CTRL_URB_RUNNING 0x00000010 +#define CTRL_URB_SLEEP 0x00000020 +#define PEGASUS_UNPLUG 0x00000040 +#define ETH_REGS_CHANGE 0x40000000 +#define ETH_REGS_CHANGED 0x80000000 + +#define RX_MULTICAST 2 +#define RX_PROMISCUOUS 4 + +#define REG_TIMEOUT (HZ) +#define PEGASUS_TX_TIMEOUT (HZ*10) + +#define TX_UNDERRUN 0x80 +#define EXCESSIVE_COL 0x40 +#define LATE_COL 0x20 +#define NO_CARRIER 0x10 +#define LOSS_CARRIER 0x08 +#define JABBER_TIMEOUT 0x04 + +#define PEGASUS_REQT_READ 0xc0 +#define PEGASUS_REQT_WRITE 0x40 +#define PEGASUS_REQ_GET_REGS 0xf0 +#define PEGASUS_REQ_SET_REGS 0xf1 +#define PEGASUS_REQ_SET_REG PEGASUS_REQ_SET_REGS +#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES))) + +enum pegasus_registers { + EthCtrl0 = 0, + EthCtrl1 = 1, + EthCtrl2 = 2, + EthID = 0x10, + Reg1d = 0x1d, + EpromOffset = 0x20, + EpromData = 0x21, /* 0x21 low, 0x22 high byte */ + EpromCtrl = 0x23, + PhyAddr = 0x25, + PhyData = 0x26, /* 0x26 low, 0x27 high byte */ + PhyCtrl = 0x28, + UsbStst = 0x2a, + EthTxStat0 = 0x2b, + EthTxStat1 = 0x2c, + EthRxStat = 0x2d, + Reg7b = 0x7b, + Gpio0 = 0x7e, + Gpio1 = 0x7f, + Reg81 = 0x81, +}; + + +typedef struct pegasus { + struct usb_device *usb; + struct net_device *net; + struct net_device_stats stats; + unsigned flags; + unsigned features; + int dev_index; + int intr_interval; + struct urb ctrl_urb, rx_urb, tx_urb, intr_urb; + devrequest dr; + wait_queue_head_t ctrl_wait; + struct semaphore ctrl_sem; + unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]); + unsigned char ALIGN(tx_buff[PEGASUS_MAX_MTU]); + unsigned char ALIGN(intr_buff[8]); + __u8 eth_regs[4]; + __u8 phy; + __u8 gpio_res; +} pegasus_t; + + +struct usb_eth_dev { + char *name; + __u16 vendor; + __u16 device; + __u32 private; /* LSB is gpio reset value */ +}; + + +#define VENDOR_ACCTON 0x083a +#define VENDOR_ADMTEK 0x07a6 +#define VENDOR_BILLIONTON 0x08dd +#define VENDOR_COREGA 0x07aa +#define VENDOR_DLINK1 0x2001 +#define VENDOR_DLINK2 0x07b8 +#define VENDOR_IODATA 0x04bb +#define VENDOR_LANEED 0x056e +#define VENDOR_LINKSYS 0x066b +#define VENDOR_MELCO 0x0411 +#define VENDOR_SMC 0x0707 +#define VENDOR_SOHOWARE 0x15e8 + + +#else /* PEGASUS_DEV */ + + +PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus II\" USB Ethernet", + VENDOR_ADMTEK, 0x8511, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (eval board)", + VENDOR_ADMTEK, 0x0986, + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987, + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "Billionton USBEL-100", VENDOR_BILLIONTON, 0x0988, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "Billionton USBE-100", VENDOR_BILLIONTON, 0x8511, + DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "Corega FEter USB-TX", VENDOR_COREGA, 0x0004, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK1, 0x4001, + LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "D-Link DSB-650TX", VENDOR_DLINK1, 0x4002, + LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "D-Link DSB-650TX(PNA)", VENDOR_DLINK1, 0x4003, + DEFAULT_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "D-Link DSB-650", VENDOR_DLINK1, 0xabc1, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "D-Link DU-E10", VENDOR_DLINK2, 0xabc1, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "D-Link DU-E100", VENDOR_DLINK2, 0x4002, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "LANEED USB Ethernet LD-USB/TX", VENDOR_LANEED, 0x4002, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "Linksys USB10TX", VENDOR_LINKSYS, 0x2202, + LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2203, + LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "Linksys USB100TX", VENDOR_LINKSYS, 0x2204, + LINKSYS_GPIO_RESET | HAS_HOME_PNA ) +PEGASUS_DEV( "Linksys USB Ethernet Adapter", VENDOR_LINKSYS, 0x2206, + LINKSYS_GPIO_RESET ) +PEGASUS_DEV( "MELCO/BUFFALO LUA-TX", VENDOR_MELCO, 0x0001, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, + DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "SOHOware NUB100 Ethernet", VENDOR_SOHOWARE, 0x9100, + DEFAULT_GPIO_RESET ) + + +#endif /* PEGASUS_DEV */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/plusb.c linux/drivers/usb/plusb.c --- v2.4.0-test10/linux/drivers/usb/plusb.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/plusb.c Wed Nov 8 17:03:09 2000 @@ -1,9 +1,11 @@ /*****************************************************************************/ /* - * plusb.c -- prolific pl-2302 driver. + * plusb.c -- prolific pl-2301/pl-2302 driver. * * Copyright (C) 2000 Deti Fliegl (deti@fliegl.de) + * Copyright (C) 2000 Pavel Machek (pavel@suse.cz) + * Copyright (C) 2000 Eric Z. Ayers (eric@compgen.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 @@ -20,9 +22,100 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * + * This driver creates a network interface (plusb0, plusb1, ...) that will + * send messages over a USB host-host cable based on the Prolific ASIC. + * It works a lot like plip or PP over an RS-232C null modem cable. + * + * 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) * * $Id: plusb.c,v 1.18 2000/02/14 10:38:58 fliegl Exp $ * + * Changelog: + * + * v0.1 deti + * Original Version of driver. + * v0.2 15 Sep 2000 pavel + * Patches to decrease latency by rescheduling the bottom half of + * interrupt code. + * v0.3 10 Oct 2000 eric + * Patches to work in v2.2 backport (v2.4 changes the way net_dev.name + * is allocated) + * v0.4 19 Oct 2000 eric + * Some more performance fixes. Lock re-submitting urbs. + * Lower the number of sk_buff's to queue. + * v0.5 25 Oct 2000 eric + * Removed use of usb_bulk_msg() all together. This caused + * the driver to block in an interrupt context. + * Consolidate read urb submission into read_urb_submit(). + * Performance is the same as v0.4. + * v0.5.1 27 Oct 2000 eric + * Extra debugging messages to help diagnose problem with uchi.o stack. + * v0.5.2 27 Oct 2000 eric + * Set the 'start' flag for the network device in plusb_net_start() + * and plusb_net_stop() (doesn't help) + * v0.5.3 27 Oct 2000 pavel + * Commented out handlers when -EPIPE is received, + * (remove calls to usb_clear_halt()) Since the callback is in + * an interrupt context, it doesn't help, it just panics + * the kernel. (what do we do?) + * Under high load, dev_alloc_skb() fails, the read URB must + * be re-submitted. + * Added plusb_change_mtu() and increased the size of _BULK_DATA_LEN + * v0.5.4 31 Oct 2000 eric + * Fix race between plusb_net_xmit() and plusb_bulk_write_complete() + * v0.5.5 1 Nov 2000 eric + * Remove dev->start field, otherwise, it won't compile in 2.4 + * Use dev_kfree_skb_any(). (important in 2.4 kernel) + * v0.5.6 2 Nov 2000 pavel,eric + * Add calls to netif_stop_queue() and netif_start_queue() + * Drop packets that come in while the free list is empty. + * (This version is being submitted after the release of 2.4-test10) + * v0.5.7 6 Nov 2000 + * Fix to not re-submit the urb on error to help when cables + * are yanked (not tested) + * + * + * KNOWN PROBLEMS: (Any suggestions greatfully accepted!) + * + * 2 Nov 2000 + * - The shutdown for this may not be entirely clean. Sometimes, the + * kernel will Oops when the cable is unplugged, or + * if the plusb module is removed. + * - If you ifdown a device and then ifup it again, the link will not + * always work. You have to 'rmmod plusb ; modprobe plusb' on + * both machines to get it to work again. Something must be wrong with + * plusb_net_open() and plusb_net_start() ? Maybe + * the 'suspend' and 'resume' entry points need to be + * implemented? + * - Needs to handle -EPIPE correctly in bulk complete handlers. + * (replace usb_clear_halt() function with async urbs?) + * - I think this code relies too much on one spinlock and does + * too much in the interrupt handler. The net1080 code is + * much more elegant, and should work for this chip. Its + * only drawback is that it is going to be tough to backport + * it to v2.2. + * - Occasionally the device will hang under the 'uhci.o' + * driver. The workaround is to ifdown the device and + * remove the modules, then re-insert them. You may have + * better luck with the 'usb-uhci.o' driver. + * - After using ifconfig down ; ifconfig up, sometimes packets + * continue to be received, but there is a framing problem. + * + * FUTURE DIRECTIONS: + * + * - Fix the known problems. + * - There isn't much functional difference between the net1080 + * driver and this one. It would be neat if the same driver + * could handle both types of chips. Or if both drivers + * could handle both types of chips - this one is easier to + * backport to the 2.2 kernel. + * - Get rid of plusb_add_buf_tail and the single spinlock. + * Use a separate spinlock for the 2 lists, and use atomic + * operators for writeurb_submitted and readurb_submitted members. + * + * */ /*****************************************************************************/ @@ -40,23 +133,102 @@ #include #include #include -//#define DEBUG +//#define DEBUG 1 #include -#include "plusb.h" +/* Definitions formerly in plusb.h relocated. No need to export them -EZA */ + +#define _PLUSB_INTPIPE 0x1 +#define _PLUSB_BULKOUTPIPE 0x2 +#define _PLUSB_BULKINPIPE 0x3 + +#define _SKB_NUM 32 + +/* increase size of BULK_DATA_LEN so we can use bigger MTU's*/ +#define _BULK_DATA_LEN 32768 + + +typedef struct +{ + int connected; /* indicates if this structure is active */ + struct usb_device *usbdev; + /* keep track of USB structure */ + int status; /* Prolific status byte returned from interrupt */ + int in_bh; /* flag to indicate that we are in the bulk handler */ + int opened; /* flag to indicate that network dev is open */ + + spinlock_t lock; /* Lock for the buffer list. re-used for + locking around submitting the readurb member. + */ + urb_t *inturb; /* Read buffer for the interrupt callback */ + unsigned char * interrupt_in_buffer; + /* holds data for the inturb*/ + urb_t *readurb; /* Read buffer for the bulk data callback */ + unsigned char * bulk_in_buffer; + /* kmalloc'ed data for the readurb */ + int readurb_submitted; + /* Flag to indicate that readurb already sent */ + urb_t *writeurb; /* Write buffer for the bulk data callback */ + int writeurb_submitted; + /* Flag to indicate that writeurb already sent */ + + struct list_head tx_skb_list; + /* sk_buff's read from net device */ + struct list_head free_skb_list; + /* free sk_buff list */ + struct net_device net_dev; + /* handle to linux network device */ + struct net_device_stats net_stats; + /* stats to return for ifconfig output */ +} plusb_t,*pplusb_t; + +/* + * skb_list - queue of packets from the network driver to be delivered to USB + */ +typedef struct +{ + struct list_head skb_list; + struct sk_buff *skb; + int state; + plusb_t *s; +} skb_list_t,*pskb_list_t; + /* --------------------------------------------------------------------- */ #define NRPLUSB 4 +/* + * Interrupt endpoint status byte, from Prolific PL-2301 docs + * Check the 'download' link at www.prolifictech.com + */ +#define _PL_INT_RES1 0x80 /* reserved */ +#define _PL_INT_RES2 0x40 /* reserved */ +#define _PL_INT_RXD _PL_INT_RES2 /* Read data ready - Not documented by Prolific, but seems to work! */ +#define _PL_INT_TX_RDY 0x20 /* OK to transmit data */ +#define _PL_INT_RESET_O 0x10 /* reset output pipe */ +#define _PL_INT_RESET_I 0x08 /* reset input pipe */ +#define _PL_INT_TX_C 0x04 /* transmission complete */ +#define _PL_INT_TX_REQ 0x02 /* transmission received */ +#define _PL_INT_PEER_E 0x01 /* peer exists */ + /*-------------------------------------------------------------------*/ static plusb_t plusb[NRPLUSB]; +static void plusb_write_bulk_complete(urb_t *purb); +static void plusb_read_bulk_complete(urb_t *purb); +static void plusb_int_complete(urb_t *purb); + /* --------------------------------------------------------------------- */ + +/* + * plusb_add_buf_tail - Take the head of the src list and append it to + * the tail of the dest list + */ static int plusb_add_buf_tail (plusb_t *s, struct list_head *dst, struct list_head *src) { - unsigned long flags; + unsigned long flags = 0; struct list_head *tmp; int ret = 0; @@ -76,126 +248,227 @@ } /*-------------------------------------------------------------------*/ -static int plusb_my_bulk(plusb_t *s, int pipe, void *data, int size, int *actual_length) +/* + * dequeue_next_skb - submit the first thing on the tx_skb_list to the + * USB stack. This function should be called each time we get a new + * message to send to the other host, or each time a message is sucessfully + * sent. + */ +static void dequeue_next_skb(char * func, plusb_t * s) { - int ret; + skb_list_t * skb_list; + unsigned long flags = 0; - dbg("plusb_my_bulk: len:%d",size); + if (!s->connected) + return; + + spin_lock_irqsave (&s->lock, flags); + + if (!list_empty (&s->tx_skb_list) && !s->writeurb_submitted) { + int submit_ret; + skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list); - ret=usb_bulk_msg(s->usbdev, pipe, data, size, actual_length, 500); - if(ret<0) { - err("plusb: usb_bulk_msg failed(%d)",ret); + if (skb_list->skb) { + s->writeurb_submitted = 1; + + /* Use the buffer inside the sk_buff directly. why copy? */ + FILL_BULK_URB_TO(s->writeurb, s->usbdev, + usb_sndbulkpipe(s->usbdev, _PLUSB_BULKOUTPIPE), + skb_list->skb->data, skb_list->skb->len, + plusb_write_bulk_complete, skb_list, 500); + + dbg ("%s: %s: submitting urb. skb_list %p", s->net_dev.name, func, skb_list); + + submit_ret = usb_submit_urb(s->writeurb); + if (submit_ret) { + s->writeurb_submitted = 0; + printk (KERN_CRIT "%s: %s: can't submit writeurb: %d\n", + s->net_dev.name, func, submit_ret); + } + } /* end if the skb value has been filled in */ } - if( ret == -EPIPE ) { - warn("CLEAR_FEATURE request to remove STALL condition."); - if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) - err("request failed"); - } - - dbg("plusb_my_bulk: finished act: %d", *actual_length); - return ret; + spin_unlock_irqrestore (&s->lock, flags); } -/* --------------------------------------------------------------------- */ - -static void plusb_bh(void *context) +/* + * submit_read_urb - re-submit the read URB to the stack + */ +void submit_read_urb(char * func, plusb_t * s) { - plusb_t *s=context; - struct net_device_stats *stats=&s->net_stats; - int ret=0; - int actual_length; - skb_list_t *skb_list; - struct sk_buff *skb; - - dbg("plusb_bh: i:%d",in_interrupt()); - - while(!list_empty(&s->tx_skb_list)) { - - if(!(s->status&_PLUSB_TXOK)) - break; - - skb_list = list_entry (s->tx_skb_list.next, skb_list_t, skb_list); - if(!skb_list->state) { - dbg("plusb_bh: not yet ready"); - schedule(); - continue; - } - - skb=skb_list->skb; - ret=plusb_my_bulk(s, usb_sndbulkpipe (s->usbdev, _PLUSB_BULKOUTPIPE), - skb->data, skb->len, &actual_length); - - if(ret || skb->len != actual_length ||!(skb->len%64)) { - plusb_my_bulk(s, usb_sndbulkpipe (s->usbdev, _PLUSB_BULKOUTPIPE), - NULL, 0, &actual_length); - } + unsigned long flags=0; - if(!ret) { - stats->tx_packets++; - stats->tx_bytes+=skb->len; - } - else { - stats->tx_errors++; - stats->tx_aborted_errors++; + if (!s->connected) + return; + + spin_lock_irqsave (&s->lock, flags); + + if (!s->readurb_submitted) { + int ret; + s->readurb_submitted=1; + s->readurb->dev=s->usbdev; + ret = usb_submit_urb(s->readurb); + if (ret) { + printk (KERN_CRIT "%s: %s: error %d submitting read URB\n", + s->net_dev.name, func, ret); + s->readurb_submitted=0; } - - dbg("plusb_bh: dev_kfree_skb"); - - dev_kfree_skb(skb); - skb_list->state=0; - plusb_add_buf_tail (s, &s->free_skb_list, &s->tx_skb_list); } - dbg("plusb_bh: finished"); - s->in_bh=0; + spin_unlock_irqrestore (&s->lock, flags); + } - /* --------------------------------------------------------------------- */ +/* + * plusb_net_xmit - callback from the network device driver for outgoing data + * + * Data has arrived to the network device from the local machine and needs + * to be sent over the USB cable. This is in an interrupt, so we don't + * want to spend too much time in this function. + * + */ static int plusb_net_xmit(struct sk_buff *skb, struct net_device *dev) { plusb_t *s=dev->priv; skb_list_t *skb_list; - int ret=NET_XMIT_SUCCESS; + unsigned int flags; dbg("plusb_net_xmit: len:%d i:%d",skb->len,in_interrupt()); - if(!s->connected || list_empty(&s->free_skb_list)) { - ret=NET_XMIT_CN; - goto lab; - } + if(!s->connected || !s->opened) { + /* + NOTE: If we get to this point, you'll return the error + kernel: virtual device plusb0 asks to queue packet + + Other things we could do: + 1) just drop this packet + 2) drop other packets in the queue + */ + return 1; + } + + spin_lock_irqsave (&s->lock, flags); - plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list); + if (list_empty(&s->free_skb_list) + || plusb_add_buf_tail (s, &s->tx_skb_list, &s->free_skb_list)) { + /* The buffers on this side are full. DROP the packet + I think that this shouldn't happen with the correct + use of the netif_XXX functions -EZA + */ + dbg ("plusb: Free list is empty."); + kfree_skb(skb); + s->net_stats.tx_dropped++; + spin_unlock_irqrestore (&s->lock, flags); + return 0; + } + skb_list = list_entry (s->tx_skb_list.prev, skb_list_t, skb_list); skb_list->skb=skb; skb_list->state=1; + skb_list->s=s; + + if (list_empty(&s->free_skb_list)) { + /* apply "backpressure". Tell the net layer to stop sending + the driver packets. + */ + netif_stop_queue(dev); + } + + spin_unlock_irqrestore (&s->lock, flags); + + /* If there is no write urb outstanding, pull the first thing + off of the list and submit it to the USB stack + */ + dequeue_next_skb("plusb_net_xmit", s); + + return 0; +} -lab: - if(s->in_bh) - return ret; +/* --------------------------------------------------------------------- */ - dbg("plusb_net_xmit: queue_task"); +/* + * plusb_write_bulk_complete () - callback after the data has been + * sent to the USB device, or a timeout occured. + */ +static void plusb_write_bulk_complete(urb_t *purb) +{ + skb_list_t * skb_list=purb->context; + plusb_t *s=skb_list->s; - s->in_bh=1; - queue_task(&s->bh, &tq_scheduler); + dbg ("%s: plusb_write_bulk_complete: status:%d skb_list:%p\n", + s->net_dev.name, purb->status, skb_list); - dbg("plusb_net_xmit: finished"); - return ret; + skb_list->state=0; -} + 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++; + s->net_stats.tx_bytes+=skb_list->skb->len; + } + else { + err ("%s: plusb_write_bulk_complete: returned ERROR status:%d\n", + s->net_dev.name, purb->status); -/* --------------------------------------------------------------------- */ + s->net_stats.tx_errors++; + s->net_stats.tx_aborted_errors++; + } + + 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)) { + err ("plusb: tx list empty. This shouldn't happen."); + } + + purb->status = 0; + s->writeurb_submitted = 0; + + netif_wake_queue((&s->net_dev)); + + dequeue_next_skb("plusb_write_bulk_complete", s); -static void plusb_bulk_complete(urb_t *purb) + +} + +/* + * plusb_read_bulk_complete - Callback for data arriving from the USB device + * + * This gets called back when a full 'urb' is received from the remote system. + * This urb was allocated by this driver and is kept in the member: s->readurb + * + */ +static void plusb_read_bulk_complete(urb_t *purb) { + plusb_t *s=purb->context; - dbg("plusb_bulk_complete: status:%d length:%d",purb->status,purb->actual_length); + dbg("plusb_read_bulk_complete: status:%d length:%d", purb->status,purb->actual_length); + if(!s->connected) return; - if( !purb->status) { + 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) { struct sk_buff *skb; unsigned char *dst; int len=purb->transfer_buffer_length; @@ -204,31 +477,69 @@ skb=dev_alloc_skb(len); if(!skb) { - err("plusb_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame",len); + printk (KERN_CRIT "%s: plusb_read_bulk_complete: dev_alloc_skb(%d)=NULL, dropping frame\n", s->net_dev.name, len); stats->rx_dropped++; - return; + } else { + dst=(char *)skb_put(skb, len); + memcpy( dst, purb->transfer_buffer, len); + + skb->dev=&s->net_dev; + skb->protocol=eth_type_trans(skb, skb->dev); + stats->rx_packets++; + stats->rx_bytes+=len; + netif_rx(skb); } + + } + + s->readurb_submitted = 0; + + if (purb->status) { + /* Give the system a chance to "catch its breath". Shortcut + re-submitting the read URB> It will be re-submitted if + another interrupt comes back. The problem scenario is that + the plub is pulled and the read returns an error. + You don't want to resumbit in this case. + */ + err ("%s: plusb_read_bulk_complete: returned status %d\n", + s->net_dev.name, purb->status); + return; + } - dst=(char *)skb_put(skb, len); - memcpy( dst, purb->transfer_buffer, len); - skb->dev=&s->net_dev; - skb->protocol=eth_type_trans(skb, skb->dev); - stats->rx_packets++; - stats->rx_bytes+=len; - netif_rx(skb); - } - else - purb->status=0; + purb->status=0; + + /* Keep it coming! resubmit the URB for reading.. Make sure + we aren't in contention with the interrupt callback. + */ + submit_read_urb("plusb_read_bulk_complete", s); } /* --------------------------------------------------------------------- */ - +/* + * plusb_int_complete - USB driver callback for interrupt msg from the device + * + * Interrupts are scheduled to go off on a periodic basis (see FILL_INT_URB) + * For the prolific device, this is basically just returning a register + * filled with bits. See the macro definitions for _PL_INT_XXX above. + * Most of these bits are for implementing a machine-machine protocol + * and can be set with a special message (described as the "Quicklink" + * feature in the prolific documentation.) + * + * I don't think we need any of that to work as a network device. If a + * message is lost, big deal - that's what UNIX networking expects from + * the physical layer. + * + */ static void plusb_int_complete(urb_t *purb) { plusb_t *s=purb->context; s->status=((unsigned char*)purb->transfer_buffer)[0]&255; + #if 0 + /* This isn't right because 0x20 is TX_RDY and + sometimes will not be set + */ if((s->status&0x3f)!=0x20) { warn("invalid device status %02X", s->status); return; @@ -237,67 +548,95 @@ if(!s->connected) return; - if(s->status&_PLUSB_RXD) { - int ret; - - if(s->bulkurb->status) { - err("plusb_int_complete: URB still in use"); - return; - } - - s->bulkurb->dev = s->usbdev; - ret=usb_submit_urb(s->bulkurb); - if(ret && ret!=-EBUSY) { - err("plusb_int_complete: usb_submit_urb failed"); - } - } - - if(purb->status || s->status!=160) - dbg("status: %p %d buf: %02X", purb->dev, purb->status, s->status); + /* Don't turn this on unless you want to see the log flooded. */ +#if 0 + printk("plusb_int_complete: PEER_E:%d TX_REQ:%d TX_C:%d RESET_IN:%d RESET_O: %d TX_RDY:%d RES1:%d RES2:%d\n", + s->status & _PL_INT_PEER_E ? 1 : 0, + s->status & _PL_INT_TX_REQ ? 1 : 0, + s->status & _PL_INT_TX_C ? 1 : 0, + s->status & _PL_INT_RESET_I ? 1 : 0, + s->status & _PL_INT_RESET_O ? 1 : 0, + s->status & _PL_INT_TX_RDY ? 1 : 0, + s->status & _PL_INT_RES1 ? 1 : 0, + s->status & _PL_INT_RES2 ? 1 : 0); +#endif + +#if 1 + /* At first glance, this logic appears to not really be needed, but + it can help recover from intermittent problems where the + usb_submit_urb() fails in the read callback. -EZA + */ + + /* Try to submit the read URB again. Make sure + we aren't in contention with the bulk read callback + */ + submit_read_urb ("plusb_int_complete", s); + + /* While we are at it, why not check to see if the + write urb should be re-submitted? + */ + dequeue_next_skb("plusb_int_complete", s); + +#endif + } /* --------------------------------------------------------------------- */ - +/* + * plusb_free_all - deallocate all memory kept for an instance of the device. + */ static void plusb_free_all(plusb_t *s) { struct list_head *skb; skb_list_t *skb_list; dbg("plusb_free_all"); + + /* set a flag to tell all callbacks to cease and desist */ + s->connected = 0; + + /* If the interrupt handler is about to fire, let it finish up */ run_task_queue(&tq_immediate); if(s->inturb) { dbg("unlink inturb"); usb_unlink_urb(s->inturb); - } - - if(s->inturb && s->inturb->transfer_buffer) { - dbg("kfree inturb->transfer_buffer"); - kfree(s->inturb->transfer_buffer); - s->inturb->transfer_buffer=NULL; - } - - if(s->inturb) { dbg("free_urb inturb"); usb_free_urb(s->inturb); s->inturb=NULL; } + + if(s->interrupt_in_buffer) { + dbg("kfree s->interrupt_in_buffer"); + kfree(s->interrupt_in_buffer); + s->interrupt_in_buffer=NULL; + } + + if(s->readurb) { + dbg("unlink readurb"); + usb_unlink_urb(s->readurb); + dbg("free_urb readurb:"); + usb_free_urb(s->readurb); + s->readurb=NULL; + } - if(s->bulkurb) { - dbg("unlink bulkurb"); - usb_unlink_urb(s->bulkurb); + if(s->bulk_in_buffer) { + dbg("kfree s->bulk_in_buffer"); + kfree(s->bulk_in_buffer); + s->bulk_in_buffer=NULL; } - if(s->bulkurb && s->bulkurb->transfer_buffer) { - dbg("kfree bulkurb->transfer_buffer"); - kfree(s->bulkurb->transfer_buffer); - s->bulkurb->transfer_buffer=NULL; - } - if(s->bulkurb) { - dbg("free_urb bulkurb"); - usb_free_urb(s->bulkurb); - s->bulkurb=NULL; + s->readurb_submitted = 0; + + if(s->writeurb) { + dbg("unlink writeurb"); + usb_unlink_urb(s->writeurb); + dbg("free_urb writeurb:"); + usb_free_urb(s->writeurb); + s->writeurb=NULL; } + + s->writeurb_submitted = 0; while(!list_empty(&s->free_skb_list)) { skb=s->free_skb_list.next; @@ -310,20 +649,34 @@ skb=s->tx_skb_list.next; list_del(skb); skb_list = list_entry (skb, skb_list_t, skb_list); - kfree(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); } + + s->in_bh=0; + dbg("plusb_free_all: finished"); } /*-------------------------------------------------------------------*/ - +/* + * plusb_alloc - allocate memory associated with one instance of the device + */ static int plusb_alloc(plusb_t *s) { int i; skb_list_t *skb; dbg("plusb_alloc"); - + for(i=0 ; i < _SKB_NUM ; i++) { skb=kmalloc(sizeof(skb_list_t), GFP_KERNEL); if(!skb) { @@ -341,47 +694,63 @@ goto reject; } - dbg("bulkurb allocation:"); - s->bulkurb=usb_alloc_urb(0); - if(!s->bulkurb) { + dbg("bulk read urb allocation:"); + s->readurb=usb_alloc_urb(0); + if(!s->readurb) { err("alloc_urb failed"); goto reject; } - dbg("bulkurb/inturb init:"); - s->inturb->dev=s->usbdev; - s->inturb->pipe=usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE); - s->inturb->transfer_buffer=kmalloc(64, GFP_KERNEL); - if(!s->inturb->transfer_buffer) { - err("kmalloc failed"); + dbg("bulk write urb allocation:"); + s->writeurb=usb_alloc_urb(0); + if(!s->writeurb) { + err("alloc_urb for writeurb failed"); goto reject; } - s->inturb->transfer_buffer_length=1; - s->inturb->complete=plusb_int_complete; - s->inturb->context=s; - s->inturb->interval=10; + dbg("readurb/inturb init:"); + s->interrupt_in_buffer=kmalloc(64, GFP_KERNEL); + if(!s->interrupt_in_buffer) { + err("kmalloc failed"); + goto reject; + } + + /* The original value of '10' makes this interrupt fire off a LOT. + It was set so low because the callback determined when to + sumbit the buld read URB. I've lowered it to 100 - the driver + doesn't depend on that logic anymore. -EZA + */ + FILL_INT_URB(s->inturb, s->usbdev, + usb_rcvintpipe (s->usbdev, _PLUSB_INTPIPE), + s->interrupt_in_buffer, 1, + plusb_int_complete, s, HZ); dbg("inturb submission:"); if(usb_submit_urb(s->inturb)<0) { err("usb_submit_urb failed"); goto reject; } - - dbg("bulkurb init:"); - s->bulkurb->dev=s->usbdev; - s->bulkurb->pipe=usb_rcvbulkpipe (s->usbdev, _PLUSB_BULKINPIPE); - s->bulkurb->transfer_buffer=kmalloc(_BULK_DATA_LEN, GFP_KERNEL); - if(!s->bulkurb->transfer_buffer) { - err("kmalloc failed"); - goto reject; - } - - s->bulkurb->transfer_buffer_length=_BULK_DATA_LEN; - s->bulkurb->complete=plusb_bulk_complete; - s->bulkurb->context=s; - dbg("plusb_alloc: finished"); + dbg("readurb init:"); + s->bulk_in_buffer = kmalloc(_BULK_DATA_LEN, GFP_KERNEL); + if (!s->bulk_in_buffer) { + err("kmalloc %d bytes for bulk in buffer failed", _BULK_DATA_LEN); + } + + FILL_BULK_URB(s->readurb, s->usbdev, + usb_rcvbulkpipe(s->usbdev, _PLUSB_BULKINPIPE), + s->bulk_in_buffer, _BULK_DATA_LEN, + plusb_read_bulk_complete, s); + + /* The write urb will be initialized inside the network + interrupt. + */ + + /* get the bulk read going */ + submit_read_urb("plusb_alloc", s); + + dbg ("plusb_alloc: finished. readurb=%p writeurb=%p inturb=%p", + s->readurb, s->writeurb, s->inturb); return 0; @@ -404,8 +773,11 @@ return -ENOMEM; s->opened=1; - MOD_INC_USE_COUNT; + MOD_INC_USE_COUNT; + + netif_start_queue(dev); + dbg("plusb_net_open: success"); return 0; @@ -417,11 +789,14 @@ static int plusb_net_stop(struct net_device *dev) { plusb_t *s=dev->priv; + + netif_stop_queue(dev); dbg("plusb_net_stop"); - plusb_free_all(s); s->opened=0; + plusb_free_all(s); + MOD_DEC_USE_COUNT; dbg("plusb_net_stop:finished"); return 0; @@ -459,7 +834,6 @@ plusb_t *s = ptr; dbg("plusb_disconnect"); - s->connected = 0; plusb_free_all(s); @@ -467,6 +841,11 @@ dbg("unregistering netdev: %s",s->net_dev.name); unregister_netdev(&s->net_dev); s->net_dev.name[0] = '\0'; +#if (LINUX_VERSION_CODE < 0x020300) + dbg("plusb_disconnect: About to free name"); + kfree (s->net_dev.name); + s->net_dev.name = NULL; +#endif } dbg("plusb_disconnect: finished"); @@ -475,6 +854,22 @@ /* --------------------------------------------------------------------- */ +static int plusb_change_mtu(struct net_device *dev, int new_mtu) +{ + if ((new_mtu < 68) || (new_mtu > _BULK_DATA_LEN)) + return -EINVAL; + + printk("plusb: changing mtu to %d\n", new_mtu); + dev->mtu = new_mtu; + + /* NOTE: Could we change the size of the READ URB here dynamically + to save kernel memory? + */ + return 0; +} + +/* --------------------------------------------------------------------- */ + int plusb_net_init(struct net_device *dev) { dbg("plusb_net_init"); @@ -484,7 +879,14 @@ dev->hard_start_xmit=plusb_net_xmit; dev->get_stats = plusb_net_get_stats; ether_setup(dev); - dev->tx_queue_len = 0; + dev->change_mtu = plusb_change_mtu; + /* Setting the default MTU to 16K gives good performance for + me, and keeps the ping latency low too. Setting it up + to 32K made performance go down. -EZA + Pavel says it would be best not to do this... + */ + /*dev->mtu=16384; */ + dev->tx_queue_len = 0; dev->flags = IFF_POINTOPOINT|IFF_NOARP; @@ -524,6 +926,42 @@ return NULL; } +#if (LINUX_VERSION_CODE < 0x020300) + { + int i; + + /* For Kernel version 2.2, the driver is responsible for + allocating this memory. For version 2.4, the rules + have apparently changed, but there is a nifty function + 'init_netdev' that might make this easier... It's in + ../net/net_init.c - but can we get there from here? (no) + -EZA + */ + + /* Find the device number... we seem to have lost it... -EZA */ + for (i=0; inet_dev.name) { + s->net_dev.name = kmalloc(strlen("plusbXXXX"), GFP_KERNEL); + sprintf (s->net_dev.name, "plusb%d", i); + s->net_dev.init=plusb_net_init; + s->net_dev.priv=s; + + printk ("plusb_probe: Registering Device\n"); + if(!register_netdev(&s->net_dev)) + info("registered: %s", s->net_dev.name); + else { + err("register_netdev failed"); + s->net_dev.name[0] = '\0'; + } + dbg ("plusb_probe: Connected!"); + } + } +#else + /* Kernel version 2.3+ works a little bit differently than 2.2 */ if(!s->net_dev.name[0]) { strcpy(s->net_dev.name, "plusb%d"); s->net_dev.init=plusb_net_init; @@ -535,7 +973,8 @@ s->net_dev.name[0] = '\0'; } } - +#endif + s->connected = 1; if(s->opened) { @@ -567,8 +1006,6 @@ for (u = 0; u < NRPLUSB; u++) { plusb_t *s = &plusb[u]; memset (s, 0, sizeof (plusb_t)); - s->bh.routine = (void (*)(void *))plusb_bh; - s->bh.data = s; INIT_LIST_HEAD (&s->tx_skb_list); INIT_LIST_HEAD (&s->free_skb_list); spin_lock_init (&s->lock); @@ -591,10 +1028,21 @@ dbg("plusb_cleanup"); for (u = 0; u < NRPLUSB; u++) { plusb_t *s = &plusb[u]; +#if (LINUX_VERSION_CODE < 0x020300) + if(s->net_dev.name) { + dbg("unregistering netdev: %s",s->net_dev.name); + unregister_netdev(&s->net_dev); + s->net_dev.name[0] = '\0'; + kfree (s->net_dev.name); + s->net_dev.name = NULL; + } +#else if(s->net_dev.name[0]) { dbg("unregistering netdev: %s",s->net_dev.name); unregister_netdev(&s->net_dev); + s->net_dev.name[0] = '\0'; } +#endif } usb_deregister (&plusb_driver); dbg("plusb_cleanup: finished"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/plusb.h linux/drivers/usb/plusb.h --- v2.4.0-test10/linux/drivers/usb/plusb.h Tue Feb 15 11:37:33 2000 +++ linux/drivers/usb/plusb.h Wed Dec 31 16:00:00 1969 @@ -1,48 +0,0 @@ -#define _PLUSB_INTPIPE 0x1 -#define _PLUSB_BULKOUTPIPE 0x2 -#define _PLUSB_BULKINPIPE 0x3 - -#define _SKB_NUM 1000 -// 7 6 5 4 3 2 1 0 -// tx rx 1 0 -// 1110 0000 rxdata -// 1010 0000 idle -// 0010 0000 tx over -// 0110 tx over + rxd - -#define _PLUSB_RXD 0x40 -#define _PLUSB_TXOK 0x80 - -#ifdef __KERNEL__ -#define _BULK_DATA_LEN 16384 - -typedef struct -{ - struct list_head skb_list; - struct sk_buff *skb; - int state; -} skb_list_t,*pskb_list_t; - -typedef struct -{ - struct usb_device *usbdev; - - int status; - int connected; - int in_bh; - int opened; - - spinlock_t lock; - - urb_t *inturb; - urb_t *bulkurb; - - struct list_head tx_skb_list; - struct list_head free_skb_list; - struct tq_struct bh; - - struct net_device net_dev; - struct net_device_stats net_stats; -} plusb_t,*pplusb_t; - -#endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/printer.c linux/drivers/usb/printer.c --- v2.4.0-test10/linux/drivers/usb/printer.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/printer.c Tue Nov 14 11:34:42 2000 @@ -393,15 +393,18 @@ return count; } -static void *usblp_probe(struct usb_device *dev, unsigned int ifnum) +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, alts = -1, bidir = 0; + int minor, i, bidir = 0; + int alts = dev->actconfig->interface[ifnum].act_altsetting; int length, err; char *buf; + /* If a bidirectional interface exists, use it. */ for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) { interface = &dev->actconfig->interface[ifnum].altsetting[i]; @@ -411,18 +414,13 @@ (interface->bInterfaceProtocol > 1 && interface->bNumEndpoints < 2)) continue; - if (alts == -1) - alts = i; - - if (!bidir && interface->bInterfaceProtocol > 1) { + if (interface->bInterfaceProtocol > 1) { bidir = 1; alts = i; + break; } } - if (alts == -1) - return NULL; - interface = &dev->actconfig->interface[ifnum].altsetting[alts]; if (usb_set_interface(dev, ifnum, alts)) err("can't set desired altsetting %d on interface %d", alts, ifnum); @@ -500,7 +498,7 @@ } #ifdef DEBUG - usblp_check_status(usblp); + usblp_check_status(usblp, 0); #endif info("usblp%d: USB %sdirectional printer dev %d if %d alt %d", @@ -544,12 +542,22 @@ release: usblp_release, }; +static struct usb_device_id usblp_ids [] = { + { bInterfaceClass: 7, bInterfaceSubClass: 1, bInterfaceProtocol: 1}, + { bInterfaceClass: 7, bInterfaceSubClass: 1, bInterfaceProtocol: 2}, + { bInterfaceClass: 7, bInterfaceSubClass: 1, bInterfaceProtocol: 3}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usblp_ids); + static struct usb_driver usblp_driver = { name: "usblp", probe: usblp_probe, disconnect: usblp_disconnect, fops: &usblp_fops, - minor: USBLP_MINOR_BASE + minor: USBLP_MINOR_BASE, + id_table: usblp_ids, }; static int __init usblp_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c --- v2.4.0-test10/linux/drivers/usb/rio500.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/rio500.c Sat Nov 11 18:17:09 2000 @@ -407,19 +407,11 @@ return read_count; } -static void *probe_rio(struct usb_device *dev, unsigned int ifnum) +static void *probe_rio(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct rio_usb_data *rio = &rio_instance; - if (dev->descriptor.idVendor != 0x841) { - return NULL; - } - - if (dev->descriptor.idProduct != 0x1 /* RIO 500 */ ) { - warn(KERN_INFO "Rio player model not supported/tested."); - return NULL; - } - info("USB Rio found at address %d", dev->devnum); rio->present = 1; @@ -470,14 +462,20 @@ release: close_rio, }; -static struct -usb_driver rio_driver = { - "rio500", - probe_rio, - disconnect_rio, - {NULL, NULL}, - &usb_rio_fops, - RIO_MINOR +static struct usb_device_id rio_table [] = { + { idVendor: 0x0841, idProduct: 1 }, /* Rio 500 */ + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, rio_table); + +static struct usb_driver rio_driver = { + name: "rio500", + probe: probe_rio, + disconnect: disconnect_rio, + fops: &usb_rio_fops, + minor: RIO_MINOR, + id_table: rio_table, }; int usb_rio_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/scanner.c linux/drivers/usb/scanner.c --- v2.4.0-test10/linux/drivers/usb/scanner.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/scanner.c Sat Nov 11 18:17:09 2000 @@ -244,6 +244,82 @@ */ #include "scanner.h" +/* Table of scanners that may work with this driver */ +static struct usb_device_id scanner_device_ids [] = { + /* Acer */ + { idVendor: 0x04a5, idProduct: 0x2060 },/* Prisa Acerscan 620U & 640U (!)*/ + { idVendor: 0x04a5, idProduct: 0x2040 },/* Prisa AcerScan 620U (!) */ + { idVendor: 0x04a5, idProduct: 0x2022 },/* Vuego Scan Brisa 340U */ + /* Agfa */ + { idVendor: 0x06bd, idProduct: 0x0001 }, /* SnapScan 1212U */ + { idVendor: 0x06bd, idProduct: 0x2061 }, /* Another SnapScan 1212U (?)*/ + { idVendor: 0x06bd, idProduct: 0x0100 }, /* SnapScan Touch */ + /* Colorado -- See Primax/Colorado below */ + /* Epson -- See Seiko/Epson below */ + /* Genius */ + { idVendor: 0x0458, idProduct: 0x2001 }, /* ColorPage-Vivid Pro */ + /* Hewlett Packard */ + { idVendor: 0x03f0, idProduct: 0x0205 }, /* 3300C */ + { idVendor: 0x03f0, idProduct: 0x0101 }, /* 4100C */ + { idVendor: 0x03f0, idProduct: 0x0105 }, /* 4200C */ + { idVendor: 0x03f0, idProduct: 0x0102 }, /* PhotoSmart S20 */ + { idVendor: 0x03f0, idProduct: 0x0401 }, /* 5200C */ + { idVendor: 0x03f0, idProduct: 0x0701 }, /* 5300C */ + { idVendor: 0x03f0, idProduct: 0x0201 }, /* 6200C */ + { idVendor: 0x03f0, idProduct: 0x0601 }, /* 6300C */ + /* iVina */ + { idVendor: 0x0638, idProduct: 0x0268 }, /* 1200U */ + /* Microtek */ + { idVendor: 0x05da, idProduct: 0x0099 }, /* ScanMaker X6 - X6U */ + { idVendor: 0x05da, idProduct: 0x0094 }, /* Phantom 336CX - C3 */ + { idVendor: 0x05da, idProduct: 0x00a0 }, /* Phantom 336CX - C3 #2 */ + { idVendor: 0x05da, idProduct: 0x009a }, /* Phantom C6 */ + { idVendor: 0x05da, idProduct: 0x00a3 }, /* ScanMaker V6USL */ + { idVendor: 0x05da, idProduct: 0x80a3 }, /* ScanMaker V6USL #2 */ + { idVendor: 0x05da, idProduct: 0x80ac }, /* ScanMaker V6UL - SpicyU */ + /* Mustek */ + { idVendor: 0x055f, idProduct: 0x0001 }, /* 1200 CU */ + { idVendor: 0x0400, idProduct: 0x1000 }, /* BearPaw 1200 */ + { idVendor: 0x055f, idProduct: 0x0002 }, /* 600 CU */ + { idVendor: 0x055f, idProduct: 0x0003 }, /* 1200 USB */ + { idVendor: 0x055f, idProduct: 0x0006 }, /* 1200 UB */ + /* Primax/Colorado */ + { idVendor: 0x0461, idProduct: 0x0300 }, /* G2-300 #1 */ + { idVendor: 0x0461, idProduct: 0x0380 }, /* G2-600 #1 */ + { idVendor: 0x0461, idProduct: 0x0301 }, /* G2E-300 #1 */ + { idVendor: 0x0461, idProduct: 0x0381 }, /* ReadyScan 636i */ + { idVendor: 0x0461, idProduct: 0x0302 }, /* G2-300 #2 */ + { idVendor: 0x0461, idProduct: 0x0382 }, /* G2-600 #2 */ + { idVendor: 0x0461, idProduct: 0x0303 }, /* G2E-300 #2 */ + { idVendor: 0x0461, idProduct: 0x0383 }, /* G2E-600 */ + { idVendor: 0x0461, idProduct: 0x0340 }, /* Colorado USB 9600 */ + { idVendor: 0x0461, idProduct: 0x0360 }, /* Colorado USB 19200 */ + { idVendor: 0x0461, idProduct: 0x0341 }, /* Colorado 600u */ + { idVendor: 0x0461, idProduct: 0x0361 }, /* Colorado 1200u */ + /* Seiko/Epson Corp. */ + { 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: 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 */ + { idVendor: 0x04a7, idProduct: 0x0221 }, /* OneTouch 5300 USB */ + { idVendor: 0x04a7, idProduct: 0x0211 }, /* OneTouch 7600 USB */ + { idVendor: 0x04a7, idProduct: 0x0231 }, /* 6100 USB */ + { idVendor: 0x04a7, idProduct: 0x0311 }, /* 6200 EPP/USB */ + { idVendor: 0x04a7, idProduct: 0x0321 }, /* OneTouch 8100 EPP/USB */ + { idVendor: 0x04a7, idProduct: 0x0331 }, /* OneTouch 8600 EPP/USB */ + + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, scanner_device_ids); + + static void irq_scanner(struct urb *urb) { @@ -548,7 +624,8 @@ } static void * -probe_scanner(struct usb_device *dev, unsigned int ifnum) +probe_scanner(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct scn_usb_data *scn; struct usb_interface_descriptor *interface; @@ -591,7 +668,7 @@ * Until we detect a device which is pleasing, we silently punt. */ - for (ix = 0; ix < sizeof (scanner_device_ids) / sizeof (struct scanner_device); ix++) { + for (ix = 0; ix < sizeof (scanner_device_ids) / sizeof (struct usb_device_id); ix++) { if ((dev->descriptor.idVendor == scanner_device_ids [ix].idVendor) && (dev->descriptor.idProduct == scanner_device_ids [ix].idProduct)) { valid_device = 1; @@ -875,12 +952,14 @@ static struct usb_driver scanner_driver = { - "usbscanner", - probe_scanner, - disconnect_scanner, - { NULL, NULL }, - &usb_scanner_fops, - SCN_BASE_MNR + name: "usbscanner", + probe: probe_scanner, + disconnect: disconnect_scanner, + fops: &usb_scanner_fops, + minor: SCN_BASE_MNR, + id_table: NULL, /* This would be scanner_device_ids, but we + need to check every USB device, in case + we match a user defined vendor/product ID. */ }; void __exit diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h --- v2.4.0-test10/linux/drivers/usb/scanner.h Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/scanner.h Sat Nov 11 18:17:09 2000 @@ -100,79 +100,4 @@ static struct scn_usb_data *p_scn_table[SCN_MAX_MNR] = { NULL, /* ... */}; -/* table of scanners that may work with this driver */ -static const struct scanner_device { - __u16 idVendor; - __u16 idProduct; -} scanner_device_ids [] = { - /* Acer */ - { 0x04a5, 0x2060 }, /* Prisa Acerscan 620U & 640U (!) */ - { 0x04a5, 0x2040 }, /* Prisa AcerScan 620U (!) */ - { 0x04a5, 0x2022 }, /* Vuego Scan Brisa 340U */ - /* Agfa */ - { 0x06bd, 0x0001 }, /* SnapScan 1212U */ - { 0x06bd, 0x2061 }, /* Another SnapScan 1212U (?) */ - { 0x06bd, 0x0100 }, /* SnapScan Touch */ - /* Colorado -- See Primax/Colorado below */ - /* Epson -- See Seiko/Epson below */ - /* Genius */ - { 0x0458, 0x2001 }, /* ColorPage-Vivid Pro */ - /* Hewlett Packard */ - { 0x03f0, 0x0205 }, /* 3300C */ - { 0x03f0, 0x0101 }, /* 4100C */ - { 0x03f0, 0x0105 }, /* 4200C */ - { 0x03f0, 0x0102 }, /* PhotoSmart S20 */ - { 0x03f0, 0x0401 }, /* 5200C */ - { 0x03f0, 0x0701 }, /* 5300C */ - { 0x03f0, 0x0201 }, /* 6200C */ - { 0x03f0, 0x0601 }, /* 6300C */ - /* iVina */ - { 0x0638, 0x0268 }, /* 1200U */ - /* Microtek */ - { 0x05da, 0x0099 }, /* ScanMaker X6 - X6U */ - { 0x05da, 0x0094 }, /* Phantom 336CX - C3 */ - { 0x05da, 0x00a0 }, /* Phantom 336CX - C3 #2 */ - { 0x05da, 0x009a }, /* Phantom C6 */ - { 0x05da, 0x00a3 }, /* ScanMaker V6USL */ - { 0x05da, 0x80a3 }, /* ScanMaker V6USL #2 */ - { 0x05da, 0x80ac }, /* ScanMaker V6UL - SpicyU */ - /* Mustek */ - { 0x055f, 0x0001 }, /* 1200 CU */ - { 0x0400, 0x1000 }, /* BearPaw 1200 */ - { 0x055f, 0x0002 }, /* 600 CU */ - { 0x055f, 0x0003 }, /* 1200 USB */ - { 0x055f, 0x0006 }, /* 1200 UB */ - /* Primax/Colorado */ - { 0x0461, 0x0300 }, /* G2-300 #1 */ - { 0x0461, 0x0380 }, /* G2-600 #1 */ - { 0x0461, 0x0301 }, /* G2E-300 #1 */ - { 0x0461, 0x0381 }, /* ReadyScan 636i */ - { 0x0461, 0x0302 }, /* G2-300 #2 */ - { 0x0461, 0x0382 }, /* G2-600 #2 */ - { 0x0461, 0x0303 }, /* G2E-300 #2 */ - { 0x0461, 0x0383 }, /* G2E-600 */ - { 0x0461, 0x0340 }, /* Colorado USB 9600 */ - { 0x0461, 0x0360 }, /* Colorado USB 19200 */ - { 0x0461, 0x0341 }, /* Colorado 600u */ - { 0x0461, 0x0361 }, /* Colorado 1200u */ - /* Seiko/Epson Corp. */ - { 0x04b8, 0x0101 }, /* Perfection 636U and 636Photo */ - { 0x04b8, 0x0103 }, /* Perfection 610 */ - { 0x04b8, 0x0104 }, /* Perfection 1200U and 1200Photo */ - { 0x04b8, 0x0107 }, /* Expression 1600 */ - /* Umax */ - { 0x1606, 0x0010 }, /* Astra 1220U */ - { 0x1606, 0x0002 }, /* Astra 1236U */ - { 0x1606, 0x0030 }, /* Astra 2000U */ - { 0x1606, 0x0230 }, /* Astra 2200U */ - /* Visioneer */ - { 0x04a7, 0x0221 }, /* OneTouch 5300 USB */ - { 0x04a7, 0x0211 }, /* OneTouch 7600 USB */ - { 0x04a7, 0x0231 }, /* 6100 USB */ - { 0x04a7, 0x0311 }, /* 6200 EPP/USB */ - { 0x04a7, 0x0321 }, /* OneTouch 8100 EPP/USB */ - { 0x04a7, 0x0331 }, /* OneTouch 8600 EPP/USB */ -}; - -/* Forward declarations */ static struct usb_driver scanner_driver; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile --- v2.4.0-test10/linux/drivers/usb/serial/Makefile Sun Aug 6 11:23:40 2000 +++ linux/drivers/usb/serial/Makefile Sat Nov 11 18:51:18 2000 @@ -21,6 +21,7 @@ obj-$(CONFIG_USB_SERIAL_KEYSPAN) += keyspan.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o +obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o # Objects that export symbols. export-objs := usbserial.o diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c --- v2.4.0-test10/linux/drivers/usb/serial/belkin_sa.c Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/belkin_sa.c Sun Nov 12 20:45:18 2000 @@ -0,0 +1,576 @@ +/* + * Belkin USB Serial Adapter Driver + * + * Copyright (C) 2000 + * William Greathouse (wgreathouse@smva.com) + * + * This program is largely derived from work by the linux-usb group + * and associated source files. Please see the usb/serial files for + * individual credits and copyrights. + * + * 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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * TODO: + * -- Add true modem contol line query capability. Currently we track the + * states reported by the interrupt and the states we request. + * -- Add error reporting back to application for UART error conditions. + * Just point me at how to implement this and I'll do it. I've put the + * framework in, but haven't analyzed the "tty_flip" interface yet. + * -- Add support for flush commands + * -- Add everything that is missing :) + * + * (11/06/2000) gkh + * - Added support for the old Belkin and Peracom devices. + * - Made the port able to be opened multiple times. + * - Added some defaults incase the line settings are things these devices + * can't support. + * + * 18-Oct-2000 William Greathouse + * Released into the wild (linux-usb-devel) + * + * 17-Oct-2000 William Greathouse + * Add code to recognize firmware version and set hardware flow control + * appropriately. Belkin states that firmware prior to 3.05 does not + * operate correctly in hardware handshake mode. I have verified this + * on firmware 2.05 -- for both RTS and DTR input flow control, the control + * line is not reset. The test performed by the Belkin Win* driver is + * to enable hardware flow control for firmware 2.06 or greater and + * for 1.00 or prior. I am only enabling for 2.06 or greater. + * + * 12-Oct-2000 William Greathouse + * First cut at supporting Belkin USB Serial Adapter F5U103 + * I did not have a copy of the original work to support this + * adapter, so pardon any stupid mistakes. All of the information + * I am using to write this driver was acquired by using a modified + * UsbSnoop on Windows2000 and from examining the other USB drivers. + */ + +#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 "belkin_sa.h" + +/* function prototypes for a Belkin USB Serial Adapter F5U103 */ +static int belkin_sa_startup (struct usb_serial *serial); +static void belkin_sa_shutdown (struct usb_serial *serial); +static int belkin_sa_open (struct usb_serial_port *port, struct file *filp); +static void belkin_sa_close (struct usb_serial_port *port, struct file *filp); +static void belkin_sa_read_int_callback (struct urb *urb); +static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios * old); +static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); +static void belkin_sa_break_ctl (struct usb_serial_port *port, int break_state ); + + +static __devinitdata struct usb_device_id id_table_combined [] = { + { idVendor: BELKIN_SA_VID, idProduct: BELKIN_SA_PID }, + { idVendor: BELKIN_OLD_VID, idProduct: BELKIN_OLD_PID }, + { idVendor: PERACOM_VID, idProduct: PERACOM_PID }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id belkin_sa_table [] = { + { idVendor: BELKIN_SA_VID, idProduct: BELKIN_SA_PID }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id belkin_old_table [] = { + { idVendor: BELKIN_OLD_VID, idProduct: BELKIN_OLD_PID }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id peracom_table [] = { + { idVendor: PERACOM_VID, idProduct: PERACOM_PID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table_combined); + +/* All of the device info needed for the Belkin serial converter */ +struct usb_serial_device_type belkin_sa_device = { + name: "Belkin F5U103 USB Serial Adapter", + id_table: belkin_sa_table, /* the Belkin F5U103 device */ + needs_interrupt_in: MUST_HAVE, /* this device must 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 */ + num_interrupt_in: 1, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: belkin_sa_open, + close: belkin_sa_close, + read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */ + ioctl: belkin_sa_ioctl, + set_termios: belkin_sa_set_termios, + break_ctl: belkin_sa_break_ctl, + startup: belkin_sa_startup, + shutdown: belkin_sa_shutdown, +}; + + +/* This driver also supports the "old" school Belkin single port adaptor */ +struct usb_serial_device_type belkin_old_device = { + name: "Belkin USB Serial Adapter", + id_table: belkin_old_table, /* the old Belkin device */ + needs_interrupt_in: MUST_HAVE, /* this device must 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 */ + num_interrupt_in: 1, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: belkin_sa_open, + close: belkin_sa_close, + read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */ + ioctl: belkin_sa_ioctl, + set_termios: belkin_sa_set_termios, + break_ctl: belkin_sa_break_ctl, + startup: belkin_sa_startup, + shutdown: belkin_sa_shutdown, +}; + +/* this driver also works for the Peracom single port adapter */ +struct usb_serial_device_type peracom_device = { + name: "Peracom single port USB Serial Adapter", + id_table: peracom_table, /* the Peracom device */ + needs_interrupt_in: MUST_HAVE, /* this device must 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 */ + num_interrupt_in: 1, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: belkin_sa_open, + close: belkin_sa_close, + read_int_callback: belkin_sa_read_int_callback, /* How we get the status info */ + ioctl: belkin_sa_ioctl, + set_termios: belkin_sa_set_termios, + break_ctl: belkin_sa_break_ctl, + startup: belkin_sa_startup, + shutdown: belkin_sa_shutdown, +}; + + +struct belkin_sa_private { + unsigned long control_state; + unsigned char last_lsr; + unsigned char last_msr; + int bad_flow_control; +}; + + +/* + * *************************************************************************** + * Belkin USB Serial Adapter F5U103 specific driver functions + * *************************************************************************** + */ + +#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ + +/* assumes that struct usb_serial *serial is available */ +#define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \ + (c), BELKIN_SA_SET_REQUEST_TYPE, \ + (v), 0, NULL, 0, WDR_TIMEOUT) + +/* do some startup allocations not currently performed by usb_serial_probe() */ +static int belkin_sa_startup (struct usb_serial *serial) +{ + struct usb_device *dev = serial->dev; + struct belkin_sa_private *priv; + + /* allocate the private data structure */ + serial->port->private = kmalloc(sizeof(struct belkin_sa_private), GFP_KERNEL); + if (!serial->port->private) + return (-1); /* error */ + priv = (struct belkin_sa_private *)serial->port->private; + /* set initial values for control structures */ + priv->control_state = 0; + priv->last_lsr = 0; + priv->last_msr = 0; + /* see comments at top of file */ + priv->bad_flow_control = (dev->descriptor.bcdDevice <= 0x0206) ? 1 : 0; + info("bcdDevice: %04x, bfc: %d", dev->descriptor.bcdDevice, priv->bad_flow_control); + + init_waitqueue_head(&serial->port->write_wait); + + return (0); +} + + +static void belkin_sa_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) { + belkin_sa_close (&serial->port[i], NULL); + } + /* My special items, the standard routines free my urbs */ + if (serial->port->private) + kfree(serial->port->private); + } +} + + +static int belkin_sa_open (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_INC_USE_COUNT; + + if (!port->active) { + port->active = 1; + + /*Start reading from the device*/ + /* TODO: Look at possibility of submitting mulitple URBs to device to + * enhance buffering. Win trace shows 16 initial read URBs. + */ + 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; +} /* belkin_sa_open */ + + +static void belkin_sa_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); + usb_unlink_urb (port->interrupt_in_urb); /* wgg - do I need this? I think so. */ + port->active = 0; + } + + spin_unlock_irqrestore (&port->port_lock, flags); +} /* belkin_sa_close */ + + +static void belkin_sa_read_int_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private; + struct usb_serial *serial; + unsigned char *data = urb->transfer_buffer; + + /* the urb might have been killed. */ + if (urb->status) + return; + + if (port_paranoia_check (port, "belkin_sa_read_interrupt")) return; + + serial = port->serial; + if (serial_paranoia_check (serial, "belkin_sa_read_interrupt")) return; + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + /* Handle known interrupt data */ + /* ignore data[0] and data[1] */ + + priv->last_msr = data[BELKIN_SA_MSR_INDEX]; + + /* Record Control Line states */ + if (priv->last_msr & BELKIN_SA_MSR_DSR) + priv->control_state |= TIOCM_DSR; + else + priv->control_state &= ~TIOCM_DSR; + + if (priv->last_msr & BELKIN_SA_MSR_CTS) + priv->control_state |= TIOCM_CTS; + else + priv->control_state &= ~TIOCM_CTS; + + if (priv->last_msr & BELKIN_SA_MSR_RI) + priv->control_state |= TIOCM_RI; + else + priv->control_state &= ~TIOCM_RI; + + if (priv->last_msr & BELKIN_SA_MSR_CD) + priv->control_state |= TIOCM_CD; + else + priv->control_state &= ~TIOCM_CD; + + /* Now to report any errors */ + priv->last_lsr = data[BELKIN_SA_LSR_INDEX]; +#if 0 + /* + * 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 & BELKIN_SA_LSR_ERR) { + tty = port->tty; + /* Overrun Error */ + if (priv->last_lsr & BELKIN_SA_LSR_OE) { + } + /* Parity Error */ + if (priv->last_lsr & BELKIN_SA_LSR_PE) { + } + /* Framing Error */ + if (priv->last_lsr & BELKIN_SA_LSR_FE) { + } + /* Break Indicator */ + if (priv->last_lsr & BELKIN_SA_LSR_BI) { + } + } +#endif + + /* INT urbs are automatically re-submitted */ +} + +static void belkin_sa_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ + struct usb_serial *serial = port->serial; + struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private; + unsigned int iflag = port->tty->termios->c_iflag; + unsigned int cflag = port->tty->termios->c_cflag; + unsigned int old_iflag = old_termios->c_iflag; + unsigned int old_cflag = old_termios->c_cflag; + __u16 urb_value = 0; /* Will hold the new flags */ + + /* Set the baud rate */ + if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { + /* reassert DTR and (maybe) RTS on transition from B0 */ + if( (old_cflag&CBAUD) == B0 ) { + priv->control_state |= (TIOCM_DTR|TIOCM_RTS); + if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 1) < 0) + err("Set DTR error"); + /* don't set RTS if using hardware flow control */ + if (!(old_cflag&CRTSCTS) ) + if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 1) < 0) + err("Set RTS error"); + } + + switch(cflag & CBAUD) { + case B0: /* handled below */ break; + case B300: urb_value = BELKIN_SA_BAUD(300); break; + case B600: urb_value = BELKIN_SA_BAUD(600); break; + case B1200: urb_value = BELKIN_SA_BAUD(1200); break; + case B2400: urb_value = BELKIN_SA_BAUD(2400); break; + case B4800: urb_value = BELKIN_SA_BAUD(4800); break; + case B9600: urb_value = BELKIN_SA_BAUD(9600); break; + case B19200: urb_value = BELKIN_SA_BAUD(19200); break; + case B38400: urb_value = BELKIN_SA_BAUD(38400); break; + case B57600: urb_value = BELKIN_SA_BAUD(57600); break; + case B115200: urb_value = BELKIN_SA_BAUD(115200); break; + case B230400: urb_value = BELKIN_SA_BAUD(230400); break; + default: err("BELKIN USB Serial Adapter: unsupported baudrate request, using default of 9600"); + urb_value = BELKIN_SA_BAUD(9600); break; + } + if ((cflag & CBAUD) != B0 ) { + if (BSA_USB_CMD(BELKIN_SA_SET_BAUDRATE_REQUEST, urb_value) < 0) + err("Set baudrate error"); + } else { + /* Disable flow control */ + if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, BELKIN_SA_FLOW_NONE) < 0) + err("Disable flowcontrol error"); + + /* Drop RTS and DTR */ + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + if (BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, 0) < 0) + err("DTR LOW error"); + if (BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, 0) < 0) + err("RTS LOW error"); + } + } + + /* set the parity */ + if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { + if (cflag & PARENB) + urb_value = (cflag & PARODD) ? BELKIN_SA_PARITY_ODD : BELKIN_SA_PARITY_EVEN; + else + urb_value = BELKIN_SA_PARITY_NONE; + if (BSA_USB_CMD(BELKIN_SA_SET_PARITY_REQUEST, urb_value) < 0) + err("Set parity error"); + } + + /* set the number of data bits */ + if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { + switch (cflag & CSIZE) { + case CS5: urb_value = BELKIN_SA_DATA_BITS(5); break; + case CS6: urb_value = BELKIN_SA_DATA_BITS(6); break; + case CS7: urb_value = BELKIN_SA_DATA_BITS(7); break; + case CS8: urb_value = BELKIN_SA_DATA_BITS(8); break; + default: err("CSIZE was not CS5-CS8, using default of 8"); + urb_value = BELKIN_SA_DATA_BITS(8); + break; + } + if (BSA_USB_CMD(BELKIN_SA_SET_DATA_BITS_REQUEST, urb_value) < 0) + err("Set data bits error"); + } + + /* set the number of stop bits */ + if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) { + urb_value = (cflag & CSTOPB) ? BELKIN_SA_STOP_BITS(2) : BELKIN_SA_STOP_BITS(1); + if (BSA_USB_CMD(BELKIN_SA_SET_STOP_BITS_REQUEST, urb_value) < 0) + err("Set stop bits error"); + } + + /* Set flow control */ + if( (iflag&IXOFF) != (old_iflag&IXOFF) + || (iflag&IXON) != (old_iflag&IXON) + || (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { + urb_value = 0; + if ((iflag & IXOFF) || (iflag & IXON)) + urb_value |= (BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON); + else + urb_value &= ~(BELKIN_SA_FLOW_OXON | BELKIN_SA_FLOW_IXON); + + if (cflag & CRTSCTS) + urb_value |= (BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS); + else + urb_value &= ~(BELKIN_SA_FLOW_OCTS | BELKIN_SA_FLOW_IRTS); + + if (priv->bad_flow_control) + urb_value &= ~(BELKIN_SA_FLOW_IRTS); + + if (BSA_USB_CMD(BELKIN_SA_SET_FLOW_CTRL_REQUEST, urb_value) < 0) + err("Set flow control error"); + } +} /* belkin_sa_set_termios */ + + +static void belkin_sa_break_ctl( struct usb_serial_port *port, int break_state ) +{ + struct usb_serial *serial = port->serial; + + if (BSA_USB_CMD(BELKIN_SA_SET_BREAK_REQUEST, break_state ? 1 : 0) < 0) + err("Set break_ctl %d", break_state); +} + + +static int belkin_sa_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +{ + struct usb_serial *serial = port->serial; + __u16 urb_value; /* Will hold the new flags */ + struct belkin_sa_private *priv = (struct belkin_sa_private *)port->private; + int ret, mask; + + /* 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 */ + urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) || (cmd == TIOCMBIS) ? 1 : 0; + if (urb_value) + priv->control_state |= TIOCM_RTS; + else + priv->control_state &= ~TIOCM_RTS; + + if ((ret = BSA_USB_CMD(BELKIN_SA_SET_RTS_REQUEST, urb_value)) < 0) { + err("Set RTS error %d", ret); + return(ret); + } + } + + if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) { + /* DTR needs set */ + urb_value = ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) || (cmd == TIOCMBIS) ? 1 : 0; + if (urb_value) + priv->control_state |= TIOCM_DTR; + else + priv->control_state &= ~TIOCM_DTR; + if ((ret = BSA_USB_CMD(BELKIN_SA_SET_DTR_REQUEST, urb_value)) < 0) { + err("Set DTR error %d", ret); + return(ret); + } + } + 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("belkin_sa_ioctl arg not supported - 0x%04x",cmd); + return(-ENOIOCTLCMD); + break; + } + return 0; +} /* belkin_sa_ioctl */ + + +static int __init belkin_sa_init (void) +{ + usb_serial_register (&belkin_sa_device); + usb_serial_register (&belkin_old_device); + usb_serial_register (&peracom_device); + return 0; +} + + +static void __exit belkin_sa_exit (void) +{ + usb_serial_deregister (&belkin_sa_device); + usb_serial_deregister (&belkin_old_device); + usb_serial_deregister (&peracom_device); +} + + +module_init (belkin_sa_init); +module_exit (belkin_sa_exit); + +MODULE_DESCRIPTION("USB Belkin Serial converter driver"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/belkin_sa.h linux/drivers/usb/serial/belkin_sa.h --- v2.4.0-test10/linux/drivers/usb/serial/belkin_sa.h Wed Dec 31 16:00:00 1969 +++ linux/drivers/usb/serial/belkin_sa.h Sat Nov 11 18:51:18 2000 @@ -0,0 +1,113 @@ +/* + * Definitions for Belkin USB Serial Adapter Driver + * + * Copyright (C) 2000 + * William Greathouse (wgreathouse@smva.com) + * + * This program is largely derived from work by the linux-usb group + * and associated source files. Please see the usb/serial files for + * individual credits and copyrights. + * + * 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. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (11/06/2000) gkh + * Added old Belkin and Peracom device ids, which this driver supports + * + * 12-Oct-2000 William Greathouse + * First cut at supporting Belkin USB Serial Adapter F5U103 + * I did not have a copy of the original work to support this + * adapter, so pardon any stupid mistakes. All of the information + * I am using to write this driver was acquired by using a modified + * UsbSnoop on Windows2000. + * + */ + +#ifndef __LINUX_USB_SERIAL_BSA_H +#define __LINUX_USB_SERIAL_BSA_H + +#define BELKIN_SA_VID 0x050d /* Vendor Id */ +#define BELKIN_SA_PID 0x0103 /* Product Id */ + +#define BELKIN_OLD_VID 0x056c /* Belkin's "old" vendor id */ +#define BELKIN_OLD_PID 0x8007 /* Belkin's "old" single port serial converter's id */ + +#define PERACOM_VID 0x0565 /* Peracom's vendor id */ +#define PERACOM_PID 0x0001 /* Peracom's single port serial converter's id */ + +/* Vendor Request Interface */ +#define BELKIN_SA_SET_BAUDRATE_REQUEST 0 /* Set baud rate */ +#define BELKIN_SA_SET_STOP_BITS_REQUEST 1 /* Set stop bits (1,2) */ +#define BELKIN_SA_SET_DATA_BITS_REQUEST 2 /* Set data bits (5,6,7,8) */ +#define BELKIN_SA_SET_PARITY_REQUEST 3 /* Set parity (None, Even, Odd) */ + +#define BELKIN_SA_SET_DTR_REQUEST 10 /* Set DTR state */ +#define BELKIN_SA_SET_RTS_REQUEST 11 /* Set RTS state */ +#define BELKIN_SA_SET_BREAK_REQUEST 12 /* Set BREAK state */ + +#define BELKIN_SA_SET_FLOW_CTRL_REQUEST 16 /* Set flow control mode */ + + +#ifdef WHEN_I_LEARN_THIS +#define BELKIN_SA_SET_MAGIC_REQUEST 17 /* I don't know, possibly flush */ + /* (always in Wininit sequence before flow control) */ +#define BELKIN_SA_RESET xx /* Reset the port */ +#define BELKIN_SA_GET_MODEM_STATUS xx /* Force return of modem status register */ +#endif + +#define BELKIN_SA_SET_REQUEST_TYPE 0x40 + +#define BELKIN_SA_BAUD(b) (230400/b) + +#define BELKIN_SA_STOP_BITS(b) (b-1) + +#define BELKIN_SA_DATA_BITS(b) (b-5) + +#define BELKIN_SA_PARITY_NONE 0 +#define BELKIN_SA_PARITY_EVEN 1 +#define BELKIN_SA_PARITY_ODD 2 +#define BELKIN_SA_PARITY_MARK 3 +#define BELKIN_SA_PARITY_SPACE 4 + +#define BELKIN_SA_FLOW_NONE 0x0000 /* No flow control */ +#define BELKIN_SA_FLOW_OCTS 0x0001 /* use CTS input to throttle output */ +#define BELKIN_SA_FLOW_ODSR 0x0002 /* use DSR input to throttle output */ +#define BELKIN_SA_FLOW_IDSR 0x0004 /* use DSR input to enable receive */ +#define BELKIN_SA_FLOW_IDTR 0x0008 /* use DTR output for input flow control */ +#define BELKIN_SA_FLOW_IRTS 0x0010 /* use RTS output for input flow control */ +#define BELKIN_SA_FLOW_ORTS 0x0020 /* use RTS to indicate data available to send */ +#define BELKIN_SA_FLOW_ERRSUB 0x0040 /* ???? guess ???? substitute inline errors */ +#define BELKIN_SA_FLOW_OXON 0x0080 /* use XON/XOFF for output flow control */ +#define BELKIN_SA_FLOW_IXON 0x0100 /* use XON/XOFF for input flow control */ + +/* + * It seems that the interrupt pipe is closely modelled after the + * 16550 register layout. This is probably because the adapter can + * be used in a "DOS" environment to simulate a standard hardware port. + */ +#define BELKIN_SA_LSR_INDEX 2 /* Line Status Register */ +#define BELKIN_SA_LSR_RDR 0x01 /* receive data ready */ +#define BELKIN_SA_LSR_OE 0x02 /* overrun error */ +#define BELKIN_SA_LSR_PE 0x04 /* parity error */ +#define BELKIN_SA_LSR_FE 0x08 /* framing error */ +#define BELKIN_SA_LSR_BI 0x10 /* break indicator */ +#define BELKIN_SA_LSR_THE 0x20 /* transmit holding register empty */ +#define BELKIN_SA_LSR_TE 0x40 /* transmit register empty */ +#define BELKIN_SA_LSR_ERR 0x80 /* OE | PE | FE | BI */ + +#define BELKIN_SA_MSR_INDEX 3 /* Modem Status Register */ +#define BELKIN_SA_MSR_DCTS 0x01 /* Delta CTS */ +#define BELKIN_SA_MSR_DDSR 0x02 /* Delta DSR */ +#define BELKIN_SA_MSR_DRI 0x04 /* Delta RI */ +#define BELKIN_SA_MSR_DCD 0x08 /* Delta CD */ +#define BELKIN_SA_MSR_CTS 0x10 /* Current CTS */ +#define BELKIN_SA_MSR_DSR 0x20 /* Current DSR */ +#define BELKIN_SA_MSR_RI 0x40 /* Current RI */ +#define BELKIN_SA_MSR_CD 0x80 /* Current CD */ + +#endif /* __LINUX_USB_SERIAL_BSA_H */ + diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c --- v2.4.0-test10/linux/drivers/usb/serial/digi_acceleport.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/digi_acceleport.c Sat Nov 11 19:06:01 2000 @@ -1,5 +1,5 @@ /* -* Digi AccelePort USB-4 Serial Converter +* Digi AccelePort USB-4 and USB-2 Serial Converters * * Copyright 2000 by Digi International * @@ -14,6 +14,16 @@ * Peter Berger (pberger@brimson.com) * Al Borchers (borchers@steinerpoint.com) * +* (11/01/2000) Adam J. Richter +* usb_device_id table support +* +* (11/01/2000) pberger and borchers +* -- Turned off the USB_DISABLE_SPD flag for write bulk urbs--it caused +* USB 4 ports to hang on startup. +* -- Serialized access to write urbs by adding the dp_write_urb_in_use +* flag; otherwise, the driver caused SMP system hangs. Watching the +* urb status is not sufficient. +* * (10/05/2000) gkh * -- Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -213,7 +223,7 @@ * - Following Documentation/DocBook/kernel-locking.pdf no spin locks * are held when calling copy_to/from_user or printk. * -* $Id: digi_acceleport.c,v 1.80 2000/08/09 06:36:18 root Exp $ +* $Id: digi_acceleport.c,v 1.80.1.2 2000/11/02 05:45:08 root Exp $ */ #include @@ -411,6 +421,7 @@ int dp_in_buf_len; unsigned char dp_in_buf[DIGI_IN_BUF_SIZE]; unsigned char dp_in_flag_buf[DIGI_IN_BUF_SIZE]; + int dp_write_urb_in_use; unsigned int dp_modem_signals; wait_queue_head_t dp_modem_change_wait; int dp_open_count; /* inc on open, dec on close */ @@ -461,15 +472,29 @@ /* Statics */ +static __devinitdata struct usb_device_id id_table_combined [] = { + { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_2_ID }, + { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_4_ID }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id id_table_2 [] = { + { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_2_ID }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id id_table_4 [] = { + { idVendor: DIGI_VENDOR_ID, idProduct: DIGI_4_ID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table_combined); + /* device info needed for the Digi serial converter */ -static u16 digi_vendor_id = DIGI_VENDOR_ID; -static u16 digi_product_2_id = DIGI_2_ID; /* USB 2 */ -static u16 digi_product_4_id = DIGI_4_ID; /* USB 4 */ static struct usb_serial_device_type digi_acceleport_2_device = { name: "Digi USB", - idVendor: &digi_vendor_id, - idProduct: &digi_product_2_id, + id_table: id_table_2, needs_interrupt_in: DONT_CARE, needs_bulk_in: MUST_HAVE, needs_bulk_out: MUST_HAVE, @@ -495,8 +520,7 @@ static struct usb_serial_device_type digi_acceleport_4_device = { name: "Digi USB", - idVendor: &digi_vendor_id, - idProduct: &digi_product_4_id, + id_table: id_table_4, needs_interrupt_in: DONT_CARE, needs_bulk_in: MUST_HAVE, needs_bulk_out: MUST_HAVE, @@ -629,7 +653,8 @@ while( count > 0 ) { - while( oob_port->write_urb->status == -EINPROGRESS ) { + while( oob_port->write_urb->status == -EINPROGRESS + || oob_priv->dp_write_urb_in_use ) { cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, &oob_priv->dp_port_lock, flags ); @@ -647,8 +672,9 @@ memcpy( oob_port->write_urb->transfer_buffer, buf, len ); oob_port->write_urb->transfer_buffer_length = len; oob_port->write_urb->dev = port->serial->dev; - + if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) { + oob_priv->dp_write_urb_in_use = 1; count -= len; buf += len; } @@ -702,8 +728,8 @@ while( count > 0 && ret == 0 ) { - while( port->write_urb->status == -EINPROGRESS - && jiffies < timeout ) { + while( (port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use) && jiffies < timeout ) { cond_wait_interruptible_timeout_irqrestore( &port->write_wait, DIGI_RETRY_TIMEOUT, &priv->dp_port_lock, flags ); @@ -736,6 +762,7 @@ port->write_urb->dev = port->serial->dev; if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { + priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; count -= len; buf += len; @@ -783,7 +810,8 @@ spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); spin_lock( &port_priv->dp_port_lock ); - while( oob_port->write_urb->status == -EINPROGRESS ) { + while( oob_port->write_urb->status == -EINPROGRESS + || oob_priv->dp_write_urb_in_use ) { spin_unlock( &port_priv->dp_port_lock ); cond_wait_interruptible_timeout_irqrestore( &oob_port->write_wait, DIGI_RETRY_TIMEOUT, @@ -811,6 +839,7 @@ oob_port->write_urb->dev = port->serial->dev; if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) { + oob_priv->dp_write_urb_in_use = 1; port_priv->dp_modem_signals = (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) | (modem_signals&(TIOCM_DTR|TIOCM_RTS)); @@ -1249,7 +1278,8 @@ spin_lock_irqsave( &priv->dp_port_lock, flags ); /* wait for urb status clear to submit another urb */ - if( port->write_urb->status == -EINPROGRESS ) { + if( port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use ) { /* buffer data if count is 1 (probably put_char) if possible */ if( count == 1 ) { @@ -1292,6 +1322,7 @@ memcpy( data, from_user ? user_buf : buf, new_len ); if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { + priv->dp_write_urb_in_use = 1; ret = new_len; priv->dp_out_buf_len = 0; } @@ -1337,6 +1368,7 @@ == ((digi_serial_t *)(serial->private))->ds_oob_port_num ) { dbg( "digi_write_bulk_callback: oob callback" ); spin_lock( &priv->dp_port_lock ); + priv->dp_write_urb_in_use = 0; wake_up_interruptible( &port->write_wait ); spin_unlock( &priv->dp_port_lock ); return; @@ -1349,6 +1381,7 @@ /* try to send any buffered data on this port, if it is open */ spin_lock( &priv->dp_port_lock ); + priv->dp_write_urb_in_use = 0; if( priv->dp_open_count && port->write_urb->status != -EINPROGRESS && priv->dp_out_buf_len > 0 ) { @@ -1365,6 +1398,7 @@ priv->dp_out_buf_len ); if( (ret=usb_submit_urb(port->write_urb)) == 0 ) { + priv->dp_write_urb_in_use = 1; priv->dp_out_buf_len = 0; } @@ -1397,7 +1431,8 @@ spin_lock_irqsave( &priv->dp_port_lock, flags ); - if( port->write_urb->status == -EINPROGRESS ) + if( port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use ) room = 0; else room = port->bulk_out_size - 2 - priv->dp_out_buf_len; @@ -1416,7 +1451,8 @@ digi_port_t *priv = (digi_port_t *)(port->private); - if( port->write_urb->status == -EINPROGRESS ) { + if( port->write_urb->status == -EINPROGRESS + || priv->dp_write_urb_in_use ) { dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 ); /* return( port->bulk_out_size - 2 ); */ return( 256 ); @@ -1601,6 +1637,7 @@ spin_lock_irqsave( &priv->dp_port_lock, flags ); port->active = 0; + priv->dp_write_urb_in_use = 0; priv->dp_in_close = 0; --priv->dp_open_count; MOD_DEC_USE_COUNT; @@ -1641,7 +1678,6 @@ port = &serial->port[i]; - port->write_urb->transfer_flags |= USB_DISABLE_SPD; port->write_urb->dev = port->serial->dev; if( (ret=usb_submit_urb(port->read_urb)) != 0 ) { @@ -1689,6 +1725,7 @@ priv->dp_port_num = i; priv->dp_out_buf_len = 0; priv->dp_in_buf_len = 0; + priv->dp_write_urb_in_use = 0; priv->dp_modem_signals = 0; init_waitqueue_head( &priv->dp_modem_change_wait ); priv->dp_open_count = 0; @@ -2047,5 +2084,5 @@ MODULE_AUTHOR("Peter Berger , Al Borchers "); -MODULE_DESCRIPTION("Digi AccelePort USB-4 Serial Converter driver"); +MODULE_DESCRIPTION("Digi AccelePort USB-2/USB-4 Serial Converter driver"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c --- v2.4.0-test10/linux/drivers/usb/serial/ftdi_sio.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/ftdi_sio.c Wed Nov 15 00:41:03 2000 @@ -12,6 +12,16 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (11/13/2000) Bill Ryder + * Added spinlock protected open code and close code. + * Multiple opens work (sort of - see webpage). + * Cleaned up comments. Removed multiple PID/VID definitions. + * Factorised cts/dtr code + * Made use of __FUNCTION__ in dbg's + * + * (11/01/2000) Adam J. Richter + * usb_device_id table support + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -68,8 +78,17 @@ #include "ftdi_sio.h" -#define FTDI_VENDOR_ID 0x0403 -#define FTDI_SIO_SERIAL_CONVERTER_ID 0x8372 +#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); + /* function prototypes for a FTDI serial converter */ static int ftdi_sio_startup (struct usb_serial *serial); @@ -82,12 +101,9 @@ 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 */ -static __u16 ftdi_vendor_id = FTDI_VENDOR_ID; -static __u16 ftdi_sio_product_id = FTDI_SIO_SERIAL_CONVERTER_ID; struct usb_serial_device_type ftdi_sio_device = { name: "FTDI SIO", - idVendor: &ftdi_vendor_id, /* the FTDI vendor ID */ - idProduct: &ftdi_sio_product_id, /* the FTDI SIO product id */ + 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 */ @@ -105,63 +121,55 @@ startup: ftdi_sio_startup, }; - /* * *************************************************************************** * FTDI SIO Serial Converter specific driver functions * *************************************************************************** * - * Bill Ryder bryder@sgi.com of Silicon Graphics, Inc. did the FTDI_SIO code - * Thanx to FTDI for so kindly providing details of the protocol required - * to talk to the device - http://www.ftdi.co.uk - * - * Tested as at this version - other stuff might work - * 23 March 2000 - * Works: - * Baudrates - 9600, 38400,19200, 57600, 115200 - * TIOCMBIC - TIOCM_DTR / TIOCM_RTS - * TIOCMBIS - TIOCM_DTR / TIOCM_RTS - * TIOCMSET - DTR on/RTSon / DTR off, RTS off - * no parity:CS8 even parity:CS7 odd parity:CS7 - * CRTSCTS flow control - * - * Pilot-xfer zillions of times - * - * cu works with dir option - * - * Not Tested (ie might not work): - * xon/xoff flow control - * ppp (modem handling in general) - * - * KNOWN BUGS: - * Multiple Opens - * ============== - * Seems to have problem when opening an already open port, - * Get I/O error on first attempt, then it lets you in. - * Need to do proper usage counting - keep registered callbacks for first opener. - * - * Reproduce with: - * cu -l /dev/ttyUSB0 dir - * whilst cu is running do: - * stty -a < /dev/ttyUSB0 - * - * from stty get: 'bash: /dev/ttyUSB0: Invalid argument ' - * from cu get - * write: Invalid argument - * - * Initialisation Problem - * ====================== - * Pilot transfer required me to run the serial_loopback program before it would work. - * Still working on this. See the webpage http://reality.sgi.com/bryder_wellington/ftdi_sio + * See the webpage http://reality.sgi.com/bryder_wellington/ftdi_sio for upto date + * testing information + * * */ #define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */ +/* utility functions to set and unset dtr and rts */ +#define HIGH 1 +#define LOW 0 +static int set_rts(struct usb_device *dev, + unsigned int pipe, + int high_or_low) +{ + static char buf[1]; + unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_RTS_HIGH : + FTDI_SIO_SET_RTS_LOW); + return(usb_control_msg(dev, pipe, + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + ftdi_high_or_low, 0, + buf, 0, WDR_TIMEOUT)); +} +static int set_dtr(struct usb_device *dev, + unsigned int pipe, + int high_or_low) +{ + static char buf[1]; + unsigned ftdi_high_or_low = (high_or_low? FTDI_SIO_SET_DTR_HIGH : + FTDI_SIO_SET_DTR_LOW); + return(usb_control_msg(dev, pipe, + FTDI_SIO_SET_MODEM_CTRL_REQUEST, + FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, + ftdi_high_or_low, 0, + buf, 0, WDR_TIMEOUT)); +} + + /* do some startup allocations not currently performed by usb_serial_probe() */ static int ftdi_sio_startup (struct usb_serial *serial) { init_waitqueue_head(&serial->port[0].write_wait); + return (0); } @@ -170,65 +178,55 @@ { /* ftdi_sio_open */ struct termios tmp_termios; struct usb_serial *serial = port->serial; + unsigned long flags; /* Used for spinlock */ int result; char buf[1]; /* Needed for the usb_control_msg I think */ - dbg("ftdi_sio_open port %d", port->number); + dbg(__FUNCTION__ " port %d", port->number); - /* FIXME - multiple concurrent opens cause trouble */ - if (port->active) { - err ("port already open"); - return -EINVAL; - } - port->active = 1; /* FIXME - For multiple open this should increment */ + spin_lock_irqsave (&port->port_lock, flags); + + MOD_INC_USE_COUNT; + ++port->open_count; - /* 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); + if (!port->active){ + port->active = 1; + spin_unlock_irqrestore (&port->port_lock, flags); - /* Setup termios */ - port->tty->termios->c_cflag = - B9600 | CS8 | CREAD | HUPCL | CLOCAL; + /* 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); - - ftdi_sio_set_termios(port, &tmp_termios); + /* Setup termios */ + port->tty->termios->c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; - /* Disable flow control */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, - FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("error from flowcontrol urb"); - return(-EINVAL); - } + /* 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*/ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_DTR_HIGH, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("Error from DTR HIGH urb"); + /* Turn on RTS and DTR since we are not flow controlling*/ + if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0) { + err("Error from DTR HIGH urb"); + } + if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),HIGH) < 0){ + err("Error from RTS HIGH urb"); + } + + /* 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, + ftdi_sio_read_bulk_callback, port); + 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 */ + spin_unlock_irqrestore (&port->port_lock, flags); } - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_RTS_HIGH, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("Error from RTS HIGH urb"); - } - - /* 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, - ftdi_sio_read_bulk_callback, port); - result = usb_submit_urb(port->read_urb); - if (result) - err(__FUNCTION__ " - failed submitting read urb, error %d", result); return (0); } /* ftdi_sio_open */ @@ -239,41 +237,48 @@ struct usb_serial *serial = port->serial; unsigned int c_cflag = port->tty->termios->c_cflag; char buf[1]; + unsigned long flags; - dbg("ftdi_sio_close port %d", port->number); - - if (c_cflag & HUPCL){ - /* Disable flow control */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_FLOW_CTRL_REQUEST, - FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, - 0, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("error from flowcontrol urb"); - } + dbg( __FUNCTION__ " port %d", port->number); - /* drop DTR */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_DTR_LOW, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("Error from DTR LOW urb"); - } - /* drop RTS */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_RTS_LOW, 0, - buf, 0, WDR_TIMEOUT) < 0) { - err("Error from RTS LOW urb"); - } + spin_lock_irqsave (&port->port_lock, flags); + --port->open_count; + + if (port->open_count <= 0) { + spin_unlock_irqrestore (&port->port_lock, flags); + if (c_cflag & HUPCL){ + /* Disable flow control */ + if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + FTDI_SIO_SET_FLOW_CTRL_REQUEST, + FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, + 0, 0, + buf, 0, WDR_TIMEOUT) < 0) { + err("error from flowcontrol urb"); + } + + /* drop DTR */ + if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0), LOW) < 0){ + err("Error from DTR LOW urb"); + } + /* drop RTS */ + if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0) { + err("Error from RTS LOW urb"); + } + } /* Note change no line is hupcl is off */ + + /* shutdown our bulk reads and writes */ + usb_unlink_urb (port->write_urb); + usb_unlink_urb (port->read_urb); + port->active = 0; + port->open_count = 0; + } else { + spin_unlock_irqrestore (&port->port_lock, flags); } - /* shutdown our bulk reads and writes */ - usb_unlink_urb (port->write_urb); - usb_unlink_urb (port->read_urb); - port->active = 0; + MOD_DEC_USE_COUNT; + + + } /* ftdi_sio_close */ @@ -292,7 +297,7 @@ int result; DECLARE_WAITQUEUE(wait, current); - dbg("ftdi_sio_serial_write port %d, %d bytes", port->number, count); + dbg(__FUNCTION__ " port %d, %d bytes", port->number, count); if (count == 0) { err("write request of 0 bytes"); @@ -309,8 +314,10 @@ add_wait_queue(&port->write_wait, &wait); set_current_state (TASK_INTERRUPTIBLE); while (port->write_urb->status == -EINPROGRESS) { - dbg("ftdi_sio - write in progress - retrying"); + 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; } @@ -321,6 +328,7 @@ goto err; } schedule(); + set_current_state (TASK_INTERRUPTIBLE); } remove_wait_queue(&port->write_wait, &wait); set_current_state(TASK_RUNNING); @@ -345,7 +353,7 @@ first_byte = port->write_urb->transfer_buffer; *first_byte = 1 | ((count-data_offset) << 2) ; - dbg("Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]); + dbg(__FUNCTION__ "Bytes: %d, Control Byte: 0o%03o",count, first_byte[0]); usb_serial_debug_data (__FILE__, __FUNCTION__, count, first_byte); /* send the data out the bulk port */ @@ -360,7 +368,7 @@ return 0; } - dbg("write returning: %d", count - data_offset); + dbg(__FUNCTION__ " write returning: %d", count - data_offset); return (count - data_offset); } @@ -412,7 +420,7 @@ int i; int result; - dbg("ftdi_sio read callback"); + dbg(__FUNCTION__); if (port_paranoia_check (port, "ftdi_sio_read_bulk_callback")) { return; @@ -422,10 +430,6 @@ if (serial_paranoia_check (serial, "ftdi_sio_read_bulk_callback")) { return; } - - /* TO DO -- check for hung up line and handle appropriately: */ - /* send hangup (need to find out how to do this) */ - if (urb->status) { /* This will happen at close every time so it is a dbg not an err */ @@ -439,6 +443,12 @@ dbg("Just status"); } + /* TO DO -- check for hung up line and handle appropriately: */ + /* send hangup (need to find out how to do this) */ + /* 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 */ + + if (urb->actual_length > data_offset) { for (i = data_offset ; i < urb->actual_length ; ++i) { tty_insert_flip_char(tty, data[i], 0); @@ -468,10 +478,10 @@ { /* ftdi_sio_set_termios */ struct usb_serial *serial = port->serial; unsigned int cflag = port->tty->termios->c_cflag; - __u16 urb_value; /* Will hold the new flags */ + __u16 urb_value; /* will hold the new flags */ char buf[1]; /* Perhaps I should dynamically alloc this? */ - dbg("ftdi_sio_set_termios port %d", port->number); + dbg(__FUNCTION__ " port %d", port->number); /* FIXME -For this cut I don't care if the line is really changing or @@ -522,7 +532,7 @@ 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("FTDI_SIO does not support the baudrate requested"); + default: dbg(__FUNCTION__ "FTDI_SIO does not support the baudrate requested"); /* FIXME - how to return an error for this? */ break; } if ((cflag & CBAUD) == B0 ) { @@ -535,18 +545,10 @@ err("error from disable flowcontrol urb"); } /* Drop RTS and DTR */ - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_DTR_LOW, 0, - buf, 0, WDR_TIMEOUT) < 0) { + if (set_dtr(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){ err("Error from DTR LOW urb"); } - if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - FTDI_SIO_SET_MODEM_CTRL_REQUEST, - FTDI_SIO_SET_MODEM_CTRL_REQUEST_TYPE, - (unsigned)FTDI_SIO_SET_RTS_LOW, 0, - buf, 0, WDR_TIMEOUT) < 0) { + if (set_rts(serial->dev, usb_sndctrlpipe(serial->dev, 0),LOW) < 0){ err("Error from RTS LOW urb"); } @@ -563,7 +565,7 @@ /* Set flow control */ /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ if (cflag & CRTSCTS) { - dbg("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,7 +578,7 @@ } else { /* CHECK Assuming XON/XOFF handled by stack - not by device */ /* Disable flow control */ - dbg("Turning off hardware flow control"); + dbg(__FUNCTION__ "Turning off hardware flow control"); if (usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, @@ -597,13 +599,13 @@ char buf[1]; int ret, mask; - dbg("ftdi_sio_ioctl - cmd 0x%04x", cmd); + dbg(__FUNCTION__ " cmd 0x%04x", cmd); /* Based on code from acm.c and others */ switch (cmd) { case TIOCMGET: - dbg("TIOCMGET"); + dbg(__FUNCTION__ "TIOCMGET"); /* Request the status from the device */ if ((ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -611,7 +613,7 @@ FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, 0, buf, 1, HZ * 5)) < 0 ) { - dbg("Get not get modem status of device"); + dbg(__FUNCTION__ "Get not get modem status of device"); return(ret); } @@ -623,7 +625,7 @@ break; case TIOCMSET: /* Turns on and off the lines as specified by the mask */ - dbg("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, @@ -648,26 +650,20 @@ break; case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */ - dbg("TIOCMBIS"); + dbg(__FUNCTION__ "TIOCMBIS"); if ((ret = get_user(mask, (unsigned long *) arg))) return ret; if (mask & TIOCM_DTR){ - 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, - FTDI_SIO_SET_DTR_HIGH , 0, - buf, 0, WDR_TIMEOUT)) < 0){ + if ((ret = set_dtr(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + HIGH)) < 0) { err("Urb to set DTR failed"); return(ret); - } } - if (mask & TIOCM_RTS) { - 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, - FTDI_SIO_SET_RTS_HIGH , 0, - buf, 0, WDR_TIMEOUT)) < 0){ + } + if (mask & TIOCM_RTS) { + if ((ret = set_rts(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + HIGH)) < 0){ err("Urb to set RTS failed"); return(ret); } @@ -675,26 +671,20 @@ break; case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */ - dbg("TIOCMBIC"); + dbg(__FUNCTION__ "TIOCMBIC"); if ((ret = get_user(mask, (unsigned long *) arg))) return ret; if (mask & TIOCM_DTR){ - 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, - FTDI_SIO_SET_DTR_LOW , 0, - buf, 0, WDR_TIMEOUT)) < 0){ + if ((ret = set_dtr(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + LOW)) < 0){ err("Urb to unset DTR failed"); return(ret); } } if (mask & TIOCM_RTS) { - 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, - FTDI_SIO_SET_RTS_LOW , 0, - buf, 0, WDR_TIMEOUT)) < 0){ + if ((ret = set_rts(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + LOW)) < 0){ err("Urb to unset RTS failed"); return(ret); } @@ -714,11 +704,11 @@ /* This is not an error - turns out the higher layers will do * some ioctls itself (see comment above) */ - dbg("ftdi_sio ioctl arg not supported - it was 0x%04x",cmd); + dbg(__FUNCTION__ "arg not supported - it was 0x%04x",cmd); return(-ENOIOCTLCMD); break; } - dbg("ftdi_sio_ioctl returning 0"); + dbg(__FUNCTION__ " returning 0"); return 0; } /* ftdi_sio_ioctl */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c --- v2.4.0-test10/linux/drivers/usb/serial/keyspan.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/keyspan.c Sat Nov 11 18:17:09 2000 @@ -22,6 +22,9 @@ Tip 'o the hat to Linuxcare for supporting staff in their work on open source projects. + (11/01/2000) Adam J. Richter + usb_device_id table support. + (10/05/2000) gkh Fixed bug with urb->dev not being set properly, now that the usb core needs it. diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/keyspan.h linux/drivers/usb/serial/keyspan.h --- v2.4.0-test10/linux/drivers/usb/serial/keyspan.h Wed Jul 19 11:27:45 2000 +++ linux/drivers/usb/serial/keyspan.h Sat Nov 11 18:17:09 2000 @@ -117,28 +117,96 @@ /* Device info for the Keyspan serial converter */ #define KEYSPAN_VENDOR_ID (0x06cd) -static __u16 keyspan_vendor_id = KEYSPAN_VENDOR_ID; /* Product IDs for the five products supported, pre-renumeration */ -static __u16 keyspan_usa18x_pre_product_id = 0x0105; -static __u16 keyspan_usa19_pre_product_id = 0x0103; -static __u16 keyspan_usa19w_pre_product_id = 0x0106; -static __u16 keyspan_usa28_pre_product_id = 0x0101; -static __u16 keyspan_usa28x_pre_product_id = 0x0102; +#define keyspan_usa18x_pre_product_id 0x0105 +#define keyspan_usa19_pre_product_id 0x0103 +#define keyspan_usa19w_pre_product_id 0x0106 +#define keyspan_usa28_pre_product_id 0x0101 +#define keyspan_usa28x_pre_product_id 0x0102 /* Product IDs post-renumeration */ -static __u16 keyspan_usa18x_product_id = 0x0112; -static __u16 keyspan_usa19_product_id = 0x0107; -static __u16 keyspan_usa19w_product_id = 0x0108; -static __u16 keyspan_usa28_product_id = 0x010f; -static __u16 keyspan_usa28x_product_id = 0x0110; +#define keyspan_usa18x_product_id 0x0112 +#define keyspan_usa19_product_id 0x0107 +#define keyspan_usa19w_product_id 0x0108 +#define keyspan_usa28_product_id 0x010f +#define keyspan_usa28x_product_id 0x0110 + +static __devinitdata struct usb_device_id keyspan_ids_combined[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_pre_product_id}, + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19_pre_product_id}, + {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_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}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, keyspan_ids_combined); + +/* Eventually, we will not need separate id tables for each USB + ID pattern. But, for now, it looks like we need slightly different + behavior for each match. */ + +static __devinitdata struct usb_device_id keyspan_usa18x_pre_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa18x_pre_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa19_pre_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19_pre_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa19w_pre_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19w_pre_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa28_pre_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28_pre_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa28x_pre_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28x_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 */ +}; + +static __devinitdata struct usb_device_id keyspan_usa19_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa19w_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa19w_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa28_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28_product_id}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id keyspan_usa28x_ids[] = { + {idVendor: KEYSPAN_VENDOR_ID, idProduct: keyspan_usa28x_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)", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa18x_pre_product_id, + id_table: keyspan_usa18x_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -151,8 +219,7 @@ struct usb_serial_device_type keyspan_usa19_pre_device = { name: "Keyspan USA19 - (prerenumeration)", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa19_pre_product_id, + id_table: keyspan_usa19_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -166,8 +233,7 @@ struct usb_serial_device_type keyspan_usa19w_pre_device = { name: "Keyspan USA19W - (prerenumeration)", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa19w_pre_product_id, + id_table: keyspan_usa19w_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -181,8 +247,7 @@ struct usb_serial_device_type keyspan_usa28_pre_device = { name: "Keyspan USA28 - (prerenumeration)", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa28_pre_product_id, + id_table: keyspan_usa28_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -195,8 +260,7 @@ struct usb_serial_device_type keyspan_usa28x_pre_device = { name: "Keyspan USA28X - (prerenumeration)", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa28x_pre_product_id, + id_table: keyspan_usa28x_pre_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -210,8 +274,7 @@ struct usb_serial_device_type keyspan_usa18x_device = { name: "Keyspan USA18X", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa18x_product_id, + id_table: keyspan_usa18x_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -228,8 +291,7 @@ struct usb_serial_device_type keyspan_usa19_device = { name: "Keyspan USA19", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa19_product_id, + id_table: keyspan_usa19_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: MUST_HAVE, needs_bulk_out: MUST_HAVE, @@ -256,8 +318,7 @@ struct usb_serial_device_type keyspan_usa19w_device = { name: "Keyspan USA19W", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa19w_product_id, + id_table: keyspan_usa19w_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -275,8 +336,7 @@ struct usb_serial_device_type keyspan_usa28_device = { name: "Keyspan USA28", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa28_product_id, + id_table: keyspan_usa28_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -294,8 +354,7 @@ struct usb_serial_device_type keyspan_usa28x_device = { name: "Keyspan USA28X", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_usa28x_product_id, + id_table: keyspan_usa28x_ids, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c --- v2.4.0-test10/linux/drivers/usb/serial/keyspan_pda.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/keyspan_pda.c Sat Nov 11 18:17:09 2000 @@ -12,6 +12,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (11/01/2000) Adam J. Richter + * usb_device_id table support + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -93,12 +96,23 @@ #define KEYSPAN_PDA_FAKE_ID 0x0103 #define KEYSPAN_PDA_ID 0x0104 /* no clue */ -/* All of the device info needed for the Keyspan PDA serial converter */ -static __u16 keyspan_vendor_id = KEYSPAN_VENDOR_ID; -static __u16 keyspan_pda_fake_product_id = KEYSPAN_PDA_FAKE_ID; -static __u16 keyspan_pda_product_id = KEYSPAN_PDA_ID; +static __devinitdata struct usb_device_id id_table_combined [] = { + { idVendor: KEYSPAN_VENDOR_ID, idProduct: KEYSPAN_PDA_FAKE_ID }, + { idVendor: KEYSPAN_VENDOR_ID, idProduct: KEYSPAN_PDA_ID }, + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE (usb, id_table_combined); +static __devinitdata struct usb_device_id id_table_std [] = { + { idVendor: KEYSPAN_VENDOR_ID, idProduct: KEYSPAN_PDA_ID }, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id id_table_fake [] = { + { idVendor: KEYSPAN_VENDOR_ID, idProduct: KEYSPAN_PDA_FAKE_ID }, + { } /* Terminating entry */ +}; static void keyspan_pda_wakeup_write( struct usb_serial_port *port ) { @@ -746,8 +760,7 @@ struct usb_serial_device_type keyspan_pda_fake_device = { name: "Keyspan PDA - (prerenumeration)", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_pda_fake_product_id, + id_table: id_table_fake, needs_interrupt_in: DONT_CARE, needs_bulk_in: DONT_CARE, needs_bulk_out: DONT_CARE, @@ -760,8 +773,7 @@ struct usb_serial_device_type keyspan_pda_device = { name: "Keyspan PDA", - idVendor: &keyspan_vendor_id, - idProduct: &keyspan_pda_product_id, + id_table: id_table_std, needs_interrupt_in: MUST_HAVE, needs_bulk_in: DONT_CARE, needs_bulk_out: MUST_HAVE, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c --- v2.4.0-test10/linux/drivers/usb/serial/omninet.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/omninet.c Sat Nov 11 18:17:09 2000 @@ -10,6 +10,9 @@ * * Please report both successes and troubles to the author at omninet@kroah.com * + * (11/01/2000) Adam J. Richter + * usb_device_id table support + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -66,14 +69,17 @@ static int omninet_write_room (struct usb_serial_port *port); static void omninet_shutdown (struct usb_serial *serial); -/* All of the device info needed for the omni.net */ -static __u16 zyxel_vendor_id = ZYXEL_VENDOR_ID; -static __u16 zyxel_omninet_product_id = ZYXEL_OMNINET_ID; +static __devinitdata struct usb_device_id id_table [] = { + { idVendor: ZYXEL_VENDOR_ID, idProduct: ZYXEL_OMNINET_ID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table); + struct usb_serial_device_type zyxel_omninet_device = { name: "ZyXEL - omni.net lcd plus usb", - idVendor: &zyxel_vendor_id, - idProduct: &zyxel_omninet_product_id, + id_table: id_table, needs_interrupt_in: MUST_HAVE, needs_bulk_in: MUST_HAVE, needs_bulk_out: MUST_HAVE, diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/usb-serial.h linux/drivers/usb/serial/usb-serial.h --- v2.4.0-test10/linux/drivers/usb/serial/usb-serial.h Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/usb-serial.h Sat Nov 11 18:17:09 2000 @@ -112,8 +112,7 @@ /* This structure defines the individual serial converter. */ struct usb_serial_device_type { char *name; - __u16 *idVendor; - __u16 *idProduct; + const struct usb_device_id *id_table; char needs_interrupt_in; char needs_bulk_in; char needs_bulk_out; @@ -125,7 +124,9 @@ struct list_head driver_list; /* function call to make before accepting driver */ - int (*startup) (struct usb_serial *serial); /* return 0 to continue initialization, anything else to abort */ + /* return 0 to continue initialization, anything else to abort */ + int (*startup) (struct usb_serial *serial); + void (*shutdown) (struct usb_serial *serial); /* serial function calls */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c --- v2.4.0-test10/linux/drivers/usb/serial/usbserial.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/usbserial.c Sat Nov 11 18:17:09 2000 @@ -15,6 +15,11 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (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, + * which they usually have anyhow for use with MODULE_DEVICE_TABLE. + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -288,11 +293,12 @@ MODULE_PARM(product, "i"); MODULE_PARM_DESC(product, "User specified USB idProduct"); +static struct usb_device_id generic_device_ids[2]; /* Initially all zeroes. */ + /* All of the device info needed for the Generic Serial Converter */ static struct usb_serial_device_type generic_device = { name: "Generic", - idVendor: &vendor, /* use the user specified vendor id */ - idProduct: &product, /* use the user specified product id */ + id_table: generic_device_ids, needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ @@ -316,15 +322,25 @@ static int serial_ioctl (struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); static void serial_set_termios (struct tty_struct *tty, struct termios * old); -static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum); +static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id); static void usb_serial_disconnect(struct usb_device *dev, void *ptr); static struct usb_driver usb_serial_driver = { name: "serial", probe: usb_serial_probe, disconnect: usb_serial_disconnect, + id_table: NULL, /* check all devices */ }; +/* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead + the MODULE_DEVICE_TABLE declarations in each serial driver + cause the "hotplug" program to pull in whatever module is necessary + via modprobe, and modprobe will load usbserial because the serial + drivers depend on it. +*/ + + static int serial_refcount; static struct tty_driver serial_tty_driver; static struct tty_struct * serial_tty[SERIAL_TTY_MINORS]; @@ -957,7 +973,8 @@ -static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) +static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_serial *serial = NULL; struct usb_serial_port *port; @@ -981,19 +998,17 @@ int num_bulk_out = 0; int num_ports; int max_endpoints; + const struct usb_device_id *id_pattern = NULL; /* loop through our list of known serial converters, and see if this device matches. */ found = 0; + interface = &dev->actconfig->interface[ifnum]; list_for_each (tmp, &usb_serial_driver_list) { type = list_entry(tmp, struct usb_serial_device_type, driver_list); - dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", - type->name, *(type->idVendor), *(type->idProduct)); - - /* look at the device descriptor */ - if ((dev->descriptor.idVendor == *(type->idVendor)) && - (dev->descriptor.idProduct == *(type->idProduct))) { + id_pattern = usb_match_id(dev, interface, type->id_table); + if (id_pattern != NULL) { dbg("descriptor matches"); found = 1; break; @@ -1009,7 +1024,6 @@ interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT; /* check out the endpoints */ - interface = &dev->actconfig->interface[ifnum]; iface_desc = &interface->altsetting[0]; for (i = 0; i < iface_desc->bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i]; @@ -1335,6 +1349,8 @@ } #ifdef CONFIG_USB_SERIAL_GENERIC + generic_device_ids[0].idVendor = vendor; + generic_device_ids[0].idProduct = product; /* register our generic driver with ourselves */ usb_serial_register (&generic_device); #endif diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c --- v2.4.0-test10/linux/drivers/usb/serial/visor.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/visor.c Sat Nov 11 18:17:09 2000 @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (11/01/2000) Adam J. Richter + * usb_device_id table support + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -101,13 +104,20 @@ static void visor_write_bulk_callback (struct urb *urb); static void visor_read_bulk_callback (struct urb *urb); + +static __devinitdata struct usb_device_id id_table [] = { + { idVendor: HANDSPRING_VENDOR_ID, idProduct: HANDSPRING_VISOR_ID }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table); + + + /* All of the device info needed for the Handspring Visor */ -static __u16 handspring_vendor_id = HANDSPRING_VENDOR_ID; -static __u16 handspring_product_id = HANDSPRING_VISOR_ID; struct usb_serial_device_type handspring_device = { name: "Handspring Visor", - idVendor: &handspring_vendor_id, /* the Handspring vendor ID */ - idProduct: &handspring_product_id, /* the Handspring Visor product id */ + id_table: id_table, 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 */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c --- v2.4.0-test10/linux/drivers/usb/serial/whiteheat.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/serial/whiteheat.c Sat Nov 11 18:17:09 2000 @@ -11,6 +11,9 @@ * * See Documentation/usb/usb-serial.txt for more information on using this driver * + * (11/01/2000) Adam J. Richter + * usb_device_id table support + * * (10/05/2000) gkh * Fixed bug with urb->dev not being set properly, now that the usb * core needs it. @@ -77,6 +80,31 @@ #define CONNECT_TECH_FAKE_WHITE_HEAT_ID 0x0001 #define CONNECT_TECH_WHITE_HEAT_ID 0x8001 +/* + ID tables for whiteheat are unusual, because we want to different + things for different versions of the device. Eventually, this + will be doable from a single table. But, for now, we define two + separate ID tables, and then a third table that combines them + just for the purpose of exporting the autoloading information. +*/ +static __devinitdata struct usb_device_id id_table_std [] = { + {idVendor: CONNECT_TECH_VENDOR_ID, idProduct: CONNECT_TECH_WHITE_HEAT_ID}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id id_table_prerenumeration [] = { + {idVendor: CONNECT_TECH_VENDOR_ID, idProduct: CONNECT_TECH_WHITE_HEAT_ID}, + { } /* Terminating entry */ +}; + +static __devinitdata struct usb_device_id id_table_combined [] = { + {idVendor: CONNECT_TECH_VENDOR_ID, idProduct: CONNECT_TECH_WHITE_HEAT_ID}, + {idVendor: CONNECT_TECH_VENDOR_ID, idProduct: CONNECT_TECH_FAKE_WHITE_HEAT_ID}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, id_table_combined); + /* function prototypes for the Connect Tech WhiteHEAT serial converter */ static int whiteheat_open (struct usb_serial_port *port, struct file *filp); static void whiteheat_close (struct usb_serial_port *port, struct file *filp); @@ -87,14 +115,9 @@ static int whiteheat_startup (struct usb_serial *serial); static void whiteheat_shutdown (struct usb_serial *serial); -/* All of the device info needed for the Connect Tech WhiteHEAT */ -static __u16 connecttech_vendor_id = CONNECT_TECH_VENDOR_ID; -static __u16 connecttech_whiteheat_fake_product_id = CONNECT_TECH_FAKE_WHITE_HEAT_ID; -static __u16 connecttech_whiteheat_product_id = CONNECT_TECH_WHITE_HEAT_ID; struct usb_serial_device_type whiteheat_fake_device = { name: "Connect Tech - WhiteHEAT - (prerenumeration)", - idVendor: &connecttech_vendor_id, /* the Connect Tech vendor id */ - idProduct: &connecttech_whiteheat_fake_product_id, /* the White Heat initial product id */ + id_table: id_table_prerenumeration, needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ @@ -104,10 +127,10 @@ num_ports: 1, startup: whiteheat_startup }; + struct usb_serial_device_type whiteheat_device = { name: "Connect Tech - WhiteHEAT", - idVendor: &connecttech_vendor_id, /* the Connect Tech vendor id */ - idProduct: &connecttech_whiteheat_product_id, /* the White Heat real product id */ + id_table: id_table_std, needs_interrupt_in: DONT_CARE, /* don't have to have an interrupt in endpoint */ needs_bulk_in: DONT_CARE, /* don't have to have a bulk in endpoint */ needs_bulk_out: DONT_CARE, /* don't have to have a bulk out endpoint */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c --- v2.4.0-test10/linux/drivers/usb/storage/scsiglue.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/storage/scsiglue.c Sat Nov 11 19:04:45 2000 @@ -1,7 +1,7 @@ /* Driver for USB Mass Storage compliant devices * SCSI layer glue code * - * $Id: scsiglue.c,v 1.15 2000/10/19 18:44:11 mdharm Exp $ + * $Id: scsiglue.c,v 1.17 2000/11/02 21:27:49 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -47,6 +47,7 @@ #include "scsiglue.h" #include "usb.h" #include "debug.h" +#include "transport.h" #include @@ -105,7 +106,7 @@ /* Release all resources used by the virtual host * - * NOTE: There is no contention here, because we're allready deregistered + * NOTE: There is no contention here, because we're already deregistered * the driver and we're doing each virtual host in turn, not in parallel */ static int release(struct Scsi_Host *psh) @@ -218,6 +219,7 @@ { struct us_data *us = (struct us_data *)srb->host->hostdata[0]; int i; + int result; /* we use the usb_reset_device() function to handle this for us */ US_DEBUGP("bus_reset() called\n"); @@ -228,6 +230,15 @@ return SUCCESS; } + /* release the IRQ, if we have one */ + down(&(us->irq_urb_sem)); + if (us->irq_urb) { + US_DEBUGP("-- releasing irq URB\n"); + result = usb_unlink_urb(us->irq_urb); + US_DEBUGP("-- usb_unlink_urb() returned %d\n", result); + } + up(&(us->irq_urb_sem)); + /* attempt to reset the port */ if (usb_reset_device(us->pusb_dev) < 0) return FAILED; @@ -237,6 +248,7 @@ for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) { struct usb_interface *intf = &us->pusb_dev->actconfig->interface[i]; + struct usb_device_id *id; /* if this is an unclaimed interface, skip it */ if (!intf->driver) { @@ -254,8 +266,20 @@ US_DEBUGPX("simulating disconnect/reconnect.\n"); down(&intf->driver->serialize); intf->driver->disconnect(us->pusb_dev, intf->private_data); - intf->driver->probe(us->pusb_dev, i); + id = usb_match_id(us->pusb_dev, intf, intf->driver->id_table); + intf->driver->probe(us->pusb_dev, i, id); up(&intf->driver->serialize); + } + + /* re-allocate the IRQ URB and submit it to restore connectivity + * for CBI devices + */ + if (us->protocol == US_PR_CBI) { + down(&(us->irq_urb_sem)); + us->irq_urb->dev = us->pusb_dev; + result = usb_submit_urb(us->irq_urb); + US_DEBUGP("usb_submit_urb() returns %d\n", result); + up(&(us->irq_urb_sem)); } US_DEBUGP("bus_reset() complete\n"); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c --- v2.4.0-test10/linux/drivers/usb/storage/transport.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/storage/transport.c Tue Nov 14 23:36:01 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: transport.c,v 1.30 2000/10/24 02:01:18 mdharm Exp $ + * $Id: transport.c,v 1.32 2000/11/03 00:18:04 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -91,11 +91,11 @@ static char *lengths = - /* 0123456789ABCDEF 0123456789ABCDEF */ + /* 0123456789ABCDEF 0123456789ABCDEF */ "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */ "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */ - "M0HHB0X000H0HH0X" "XHH00HXX0TH0H0XX" /* 40-5F */ + "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */ "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */ "X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX" /* A0-BF */ @@ -185,6 +185,7 @@ SEND_MESSAGE_6 0a !!! Same as WRITE_6 - is in bytes SEND_MESSAGE_10 2a !!! Same as WRITE_10 - is in bytes SEND_MESSAGE_12 aa !!! Same as WRITE_12 - is in bytes + SEND_OPC 54 SEND_VOLUME_TAG b6 !!! Think this is in bytes SET_LIMITS 33 SET_LIMITS_12 b3 @@ -422,6 +423,7 @@ if (status) { /* something went wrong */ up(&(us->current_urb_sem)); + current->state = TASK_RUNNING; remove_wait_queue(&wqh, &wait); kfree(dr); return status; @@ -479,6 +481,7 @@ if (status) { /* something went wrong */ up(&(us->current_urb_sem)); + current->state = TASK_RUNNING; remove_wait_queue(&wqh, &wait); return status; } @@ -544,7 +547,7 @@ /* uh oh... we have an error code, so something went wrong. */ if (result) { - /* NAK - that means we've retried a few times allready */ + /* NAK - that means we've retried a few times already */ if (result == -ETIMEDOUT) { US_DEBUGP("usb_stor_transfer_partial(): device NAKed\n"); return US_BULK_TRANSFER_FAILED; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c --- v2.4.0-test10/linux/drivers/usb/storage/usb.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/storage/usb.c Wed Nov 15 00:41:03 2000 @@ -1,6 +1,6 @@ /* Driver for USB Mass Storage compliant devices * - * $Id: usb.c,v 1.51 2000/10/19 18:49:51 mdharm Exp $ + * $Id: usb.c,v 1.54 2000/10/31 21:32:10 mdharm Exp $ * * Current development and maintenance by: * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) @@ -243,6 +243,7 @@ /* handle those devices which can't do a START_STOP */ if ((us->srb->cmnd[0] == START_STOP) && (us->flags & US_FL_START_STOP)) { + US_DEBUGP("Skipping START_STOP command\n"); us->srb->result = GOOD << 1; set_current_state(TASK_INTERRUPTIBLE); @@ -311,11 +312,15 @@ US_DEBUGP("-- US_ACT_EXIT command recieved\n"); break; } + + set_current_state(TASK_INTERRUPTIBLE); } /* for (;;) */ /* notify the exit routine that we're actually exiting now */ up(&(us->notify)); + remove_wait_queue(&(us->wqh), &wait); + return 0; } @@ -423,8 +428,8 @@ { 0x054c, 0x002d, 0x0100, 0x0100, "Sony", "Memorystick MSAC-US1", - US_SC_SCSI, US_PR_CB, NULL, - US_FL_SINGLE_LUN | US_FL_START_STOP | US_FL_MODE_XLATE }, + US_SC_UFI, US_PR_CB, NULL, + US_FL_SINGLE_LUN | US_FL_START_STOP }, { 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", @@ -504,7 +509,7 @@ US_FL_SCM_MULT_TARG }, #ifdef CONFIG_USB_STORAGE_FREECOM - { 0x07ab, 0xfc01, 0x0921, 0x0921, + { 0x07ab, 0xfc01, 0x0000, 0x9999, "Freecom", "USB-IDE", US_SC_QIC, US_PR_FREECOM, freecom_init, 0}, @@ -754,7 +759,7 @@ /* * Now check if we have seen this GUID before * We're looking for a device with a matching GUID that isn't - * allready on the system + * already on the system */ ss = us_list; while ((ss != NULL) && diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c --- v2.4.0-test10/linux/drivers/usb/usb-ohci.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/usb-ohci.c Tue Nov 14 23:36:01 2000 @@ -654,6 +654,7 @@ set_current_state(TASK_UNINTERRUPTIBLE); while (timeout && (urb->status == USB_ST_URB_PENDING)) timeout = schedule_timeout (timeout); + current->state = TASK_RUNNING; remove_wait_queue (&unlink_wakeup, &wait); if (urb->status == USB_ST_URB_PENDING) { err ("unlink URB timeout"); @@ -765,6 +766,7 @@ set_current_state(TASK_UNINTERRUPTIBLE); while (timeout && dev->ed_cnt) timeout = schedule_timeout (timeout); + current->state = TASK_RUNNING; remove_wait_queue (&freedev_wakeup, &wait); if (dev->ed_cnt) { err ("free device %d timeout", usb_dev->devnum); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/usb.c linux/drivers/usb/usb.c --- v2.4.0-test10/linux/drivers/usb/usb.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/usb.c Tue Nov 14 23:36:01 2000 @@ -7,6 +7,9 @@ * (C) Copyright Gregory P. Smith 1999 * (C) Copyright Deti Fliegl 1999 (new USB architecture) * (C) Copyright Randy Dunlap 2000 + * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id) + * (C) Copyright Yggdrasil Computing, Inc. 2000 + * (usb_device_id matching changes by Adam J. Richter) * * NOTE! This is not actually a driver at all, rather this is * just a collection of helper routines that implement the @@ -460,6 +463,124 @@ iface->private_data = NULL; } + +/* usb_match_id searches an array of usb_device_id's and returns + the first one that matches the device and interface. + + Parameters: + "id" is an array of usb_device_id's is terminated by an entry + containing all zeroes. + + "dev" and "interface" are the device and interface for which + a match is sought. + + If no match is found or if the "id" pointer is NULL, then + usb_match_id returns NULL. + + + What constitutes a match: + + A zero in any element of a usb_device_id entry is a wildcard + (i.e., that field always matches). For there to be a match, + *every* nonzero element of the usb_device_id must match the + provided device and interface in. The comparison is for equality, + except for one pair of fields: usb_match_id.bcdDevice_{lo,hi} define + an inclusive range that dev->descriptor.bcdDevice must be in. + + If interface->altsettings does not exist (i.e., there are no + interfaces defined), then bInterface{Class,SubClass,Protocol} + only match if they are all zeroes. + + + What constitutes a good "usb_device_id"? + + The match algorithm is very simple, so that intelligence in + driver selection must come from smart driver id records. + Unless you have good reasons to use another selection policy, + provide match elements only in related groups: + + * device specifiers (vendor and product IDs; and maybe + a revision range for that product); + * generic device specs (class/subclass/protocol); + * interface specs (class/subclass/protocol). + + Within those groups, work from least specific to most specific. + For example, don't give a product version range without vendor + and product IDs. + + "driver_info" is not considered by the kernel matching algorithm, + but you can create a wildcard "matches anything" usb_device_id + as your driver's "modules.usbmap" entry if you provide only an + id with a nonzero "driver_info" field. +*/ + +const struct usb_device_id * +usb_match_id(struct usb_device *dev, struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_interface_descriptor *intf = 0; + + /* proc_connectinfo in devio.c may call us with id == NULL. */ + if (id == NULL) + return NULL; + + /* It is important to check that id->driver_info is nonzero, + since an entry that is all zeroes except for a nonzero + id->driver_info is the way to create an entry that + indicates that the driver want to examine every + device and interface. */ + for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || + id->driver_info; id++) { + + if (id->idVendor && + id->idVendor != dev->descriptor.idVendor) + continue; + + if (id->idProduct && + id->idProduct != dev->descriptor.idProduct) + continue; + + /* No need to test id->bcdDevice_lo != 0, since 0 is never + greater than any unsigned number. */ + if (id->bcdDevice_lo > dev->descriptor.bcdDevice) + continue; + + if (id->bcdDevice_hi && + id->bcdDevice_hi < dev->descriptor.bcdDevice) + continue; + + if (id->bDeviceClass && + id->bDeviceClass != dev->descriptor.bDeviceClass) + continue; + + if (id->bDeviceSubClass && + id->bDeviceSubClass!= dev->descriptor.bDeviceClass) + continue; + + if (id->bDeviceProtocol && + id->bDeviceProtocol != dev->descriptor.bDeviceProtocol) + continue; + + intf = &interface->altsetting [interface->act_altsetting]; + + if (id->bInterfaceClass + && id->bInterfaceClass != intf->bInterfaceClass) + continue; + + if (id->bInterfaceSubClass && + id->bInterfaceSubClass != intf->bInterfaceSubClass) + continue; + + if (id->bInterfaceProtocol + && id->bInterfaceProtocol != intf->bInterfaceProtocol) + continue; + + return id; + } + + return NULL; +} + /* * This entrypoint gets called for each new device. * @@ -478,8 +599,12 @@ */ static int usb_find_interface_driver(struct usb_device *dev, unsigned ifnum) { - struct list_head *tmp = usb_driver_list.next; + struct list_head *tmp; struct usb_interface *interface; + void *private; + const struct usb_device_id *id; + struct usb_driver *driver; + int i; if ((!dev) || (ifnum >= dev->actconfig->bNumInterfaces)) { err("bad find_interface_driver params"); @@ -491,141 +616,52 @@ if (usb_interface_claimed(interface)) return -1; - while (tmp != &usb_driver_list) { - void *private; - struct usb_driver *driver = list_entry(tmp, struct usb_driver, - driver_list); - + private = NULL; + for (tmp = usb_driver_list.next; tmp != &usb_driver_list;) { + + driver = list_entry(tmp, struct usb_driver, driver_list); tmp = tmp->next; - down(&driver->serialize); + down(&driver->serialize); + id = driver->id_table; /* new style driver? */ - if (driver->bind) { - const struct usb_device_id *id = driver->id_table; - - if (id) { - /* scan device ids for a match */ - for (;; id++) { - struct usb_interface_descriptor *intf = 0; - - /* done? */ - if (!id->idVendor && !id->bDeviceClass && !id->bInterfaceClass) { - id = 0; - break; - } - - /* Vendor match, possibly product-specific? */ - if (id->idVendor && id->idVendor == dev->descriptor.idVendor) { - if (id->idProduct && id->idProduct != dev->descriptor.idProduct) - continue; - break; - } - - /* Device class match? */ - if (id->bDeviceClass - && id->bDeviceClass == dev->descriptor.bDeviceClass) { - if (id->bDeviceSubClass && id->bDeviceSubClass - != dev->descriptor.bDeviceClass) - continue; - if (id->bDeviceProtocol && id->bDeviceProtocol - != dev->descriptor.bDeviceProtocol) - continue; - break; - } + if (id) { + for (i = 0; i < interface->num_altsetting; i++) { + interface->act_altsetting = i; + id = usb_match_id(dev, interface, id); + if (id) { + private = driver->probe(dev,ifnum,id); + if (private != NULL) + break; + } + } + /* if driver not bound, leave defaults unchanged */ + if (private == NULL) + interface->act_altsetting = 0; + } + else /* "old style" driver */ + private = driver->probe(dev, ifnum, NULL); - /* Interface class match? */ - if (!interface->altsetting || interface->num_altsetting < 1) - continue; - intf = &interface->altsetting [0]; - if (id->bInterfaceClass - && id->bInterfaceClass == intf->bInterfaceClass) { - if (id->bInterfaceSubClass && id->bInterfaceSubClass - != intf->bInterfaceClass) - continue; - if (id->bInterfaceProtocol && id->bInterfaceProtocol - != intf->bInterfaceProtocol) - continue; - break; - } - } - - /* is this driver interested in this interface? */ - if (id) - private = driver->bind(dev, ifnum, id); - else - private = 0; - } else { - /* "old style" driver, but using new interface */ - private = driver->bind(dev, ifnum, 0); - } - - /* "old style" driver */ - } else - private = driver->probe(dev, ifnum); up(&driver->serialize); - if (!private) - continue; - usb_driver_claim_interface(driver, interface, private); - - return 0; + if (private) { + usb_driver_claim_interface(driver, interface, private); + return 0; + } } - + return -1; } -#if defined(CONFIG_KMOD) && defined(CONFIG_HOTPLUG) +#ifdef CONFIG_HOTPLUG /* * USB hotplugging invokes what /proc/sys/kernel/hotplug says * (normally /sbin/hotplug) when USB devices get added or removed. - */ - -static int to_bcd (char *buf, __u16 *bcdValue) -{ - int retval = 0; - char *value = (char *) bcdValue; - int temp; - - /* digits are 0-9 then ":;<=>?" for devices using - * non-bcd (non-standard!) values here ... */ - - /* No leading (or later, trailing) zeroes since scripts do - * literal matches, and that's how they're doing them. */ - if ((temp = value [1] & 0xf0) != 0) { - temp >>= 4; - temp += '0'; - *buf++ = (char) temp; - retval++; - } - - temp = value [1] & 0x0f; - temp += '0'; - *buf++ = (char) temp; - retval++; - - *buf++ = '.'; - retval++; - - temp = value [0] & 0xf0; - temp >>= 4; - temp += '0'; - *buf++ = (char) temp; - retval++; - - if ((temp = value [0] & 0x0f) != 0) { - temp += '0'; - *buf++ = (char) temp; - retval++; - } - *buf++ = 0; - - return retval; -} - -/* + * * This invokes a user mode policy agent, typically helping to load driver - * or other modules, configure the device, or both. + * or other modules, configure the device, and more. Drivers can provide + * a MODULE_DEVICE_TABLE to help with module loading subtasks. * * Some synchronization is important: removes can't start processing * before the add-device processing completes, and vice versa. That keeps @@ -696,9 +732,7 @@ * all the device descriptors we don't tell them about. Or * even act as usermode drivers. * - * XXX how little intelligence can we hardwire? - * (a) mount point: /devfs, /dev, /proc/bus/usb etc. - * (b) naming convention: bus1/device3, 001/003 etc. + * FIXME reduce hardwired intelligence here */ envp [i++] = "DEVFS=/proc/bus/usb"; envp [i++] = scratch; @@ -706,33 +740,34 @@ dev->bus->busnum, dev->devnum) + 1; #endif - /* per-device configuration hacks are often necessary */ + /* per-device configuration hacks are common */ envp [i++] = scratch; - scratch += sprintf (scratch, "PRODUCT=%x/%x/", + scratch += sprintf (scratch, "PRODUCT=%x/%x/%x", dev->descriptor.idVendor, - dev->descriptor.idProduct); - scratch += to_bcd (scratch, &dev->descriptor.bcdDevice) + 1; + dev->descriptor.idProduct, + dev->descriptor.bcdDevice) + 1; - /* otherwise, use a simple (so far) generic driver binding model */ + /* class-based driver binding models */ envp [i++] = scratch; + scratch += sprintf (scratch, "TYPE=%d/%d/%d", + dev->descriptor.bDeviceClass, + dev->descriptor.bDeviceSubClass, + dev->descriptor.bDeviceProtocol) + 1; if (dev->descriptor.bDeviceClass == 0) { int alt = dev->actconfig->interface [0].act_altsetting; - /* simple/common case: one config, one interface, one driver - * unsimple cases: everything else + /* a simple/common case: one config, one interface, one driver + * with current altsetting being a reasonable setting. + * everything needs a smart agent and usbdevfs; or can rely on + * device-specific binding policies. */ + envp [i++] = scratch; scratch += sprintf (scratch, "INTERFACE=%d/%d/%d", dev->actconfig->interface [0].altsetting [alt].bInterfaceClass, dev->actconfig->interface [0].altsetting [alt].bInterfaceSubClass, dev->actconfig->interface [0].altsetting [alt].bInterfaceProtocol) + 1; /* INTERFACE-0, INTERFACE-1, ... ? */ - } else { - /* simple/common case: generic device, handled generically */ - scratch += sprintf (scratch, "TYPE=%d/%d/%d", - dev->descriptor.bDeviceClass, - dev->descriptor.bDeviceSubClass, - dev->descriptor.bDeviceProtocol) + 1; } envp [i++] = 0; /* assert: (scratch - buf) < sizeof buf */ @@ -753,7 +788,7 @@ call_policy (char *verb, struct usb_device *dev) { } -#endif /* KMOD && HOTPLUG */ +#endif /* KMOD */ /* @@ -916,6 +951,7 @@ if (status) { // something went wrong usb_free_urb(urb); + current->state = TASK_RUNNING; remove_wait_queue(&wqh, &wait); return status; } @@ -926,6 +962,7 @@ } else status = 1; + current->state = TASK_RUNNING; remove_wait_queue(&wqh, &wait); if (!status) { @@ -968,6 +1005,11 @@ } /*-------------------------------------------------------------------*/ +/* usb_control_msg() - builds control urb, and waits for completion */ +/* Synchronous behavior - don't use this function from within an */ +/* interrupt context, (like a bottom half handler.) In this case, */ +/* use usb_submit_urb() directly instead. */ + int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { @@ -993,8 +1035,10 @@ } /*-------------------------------------------------------------------*/ -/* compatibility wrapper, builds bulk urb, and waits for completion */ -/* synchronous behavior */ +/* usb_bulk_msg() Builds a bulk urb, and waits for completion. */ +/* Synchronous behavior - don't use this function from within an */ +/* interrupt context, (like a bottom half handler.) In this case, */ +/* use usb_submit_urb() directly instead. */ int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout) @@ -2149,6 +2193,7 @@ EXPORT_SYMBOL(usb_driver_claim_interface); EXPORT_SYMBOL(usb_interface_claimed); EXPORT_SYMBOL(usb_driver_release_interface); +EXPORT_SYMBOL(usb_match_id); EXPORT_SYMBOL(usb_root_hub_string); EXPORT_SYMBOL(usb_new_device); diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c --- v2.4.0-test10/linux/drivers/usb/usbkbd.c Tue Aug 22 15:19:52 2000 +++ linux/drivers/usb/usbkbd.c Sat Nov 11 18:48:18 2000 @@ -59,6 +59,7 @@ struct usb_kbd { struct input_dev dev; + struct usb_device *usbdev; unsigned char new[8]; unsigned char old[8]; struct urb irq, led; @@ -116,6 +117,7 @@ return 0; kbd->leds = kbd->newleds; + kbd->led.dev = kbd->usbdev; if (usb_submit_urb(&kbd->led)) err("usb_submit_urb(leds) failed"); @@ -133,6 +135,7 @@ return; kbd->leds = kbd->newleds; + kbd->led.dev = kbd->usbdev; if (usb_submit_urb(&kbd->led)) err("usb_submit_urb(leds) failed"); } @@ -144,6 +147,7 @@ if (kbd->open++) return 0; + kbd->irq.dev = kbd->usbdev; if (usb_submit_urb(&kbd->irq)) return -EIO; @@ -158,20 +162,19 @@ usb_unlink_urb(&kbd->irq); } -static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum) +static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { + struct usb_interface *iface; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_kbd *kbd; int i, pipe, maxp; char *buf; - if (dev->descriptor.bNumConfigurations != 1) return NULL; - interface = dev->config[0].interface[ifnum].altsetting + 0; + iface = &dev->actconfig->interface[ifnum]; + interface = &iface->altsetting[iface->act_altsetting]; - if (interface->bInterfaceClass != 3) return NULL; - if (interface->bInterfaceSubClass != 1) return NULL; - if (interface->bInterfaceProtocol != 1) return NULL; if (interface->bNumEndpoints != 1) return NULL; endpoint = interface->endpoint + 0; @@ -187,6 +190,8 @@ if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL; memset(kbd, 0, sizeof(struct usb_kbd)); + kbd->usbdev = dev; + kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP); kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA); @@ -251,10 +256,18 @@ kfree(kbd); } +static struct usb_device_id usb_kbd_id_table [] = { + { bInterfaceClass: 3, bInterfaceSubClass: 1, bInterfaceProtocol: 1}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_kbd_id_table); + static struct usb_driver usb_kbd_driver = { name: "keyboard", probe: usb_kbd_probe, - disconnect: usb_kbd_disconnect + disconnect: usb_kbd_disconnect, + id_table: usb_kbd_id_table, }; static int __init usb_kbd_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c --- v2.4.0-test10/linux/drivers/usb/usbmouse.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/usbmouse.c Sat Nov 11 18:48:18 2000 @@ -1,5 +1,5 @@ /* - * $Id: usbmouse.c,v 1.5 2000/05/29 09:01:52 vojtech Exp $ + * $Id: usbmouse.c,v 1.6 2000/08/14 21:05:26 vojtech Exp $ * * Copyright (c) 1999-2000 Vojtech Pavlik * @@ -41,9 +41,9 @@ struct usb_mouse { signed char data[8]; char name[128]; + struct usb_device *usbdev; struct input_dev dev; struct urb irq; - struct usb_device *my_usb_device; // for resubmitting my urb int open; }; @@ -73,7 +73,7 @@ if (mouse->open++) return 0; - mouse->irq.dev = mouse->my_usb_device; + mouse->irq.dev = mouse->usbdev; if (usb_submit_urb(&mouse->irq)) return -EIO; @@ -88,20 +88,19 @@ usb_unlink_urb(&mouse->irq); } -static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum) +static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum, + const struct usb_device_id *id) { + struct usb_interface *iface; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; struct usb_mouse *mouse; int pipe, maxp; char *buf; - if (dev->descriptor.bNumConfigurations != 1) return NULL; - interface = dev->config[0].interface[ifnum].altsetting + 0; + iface = &dev->actconfig->interface[ifnum]; + interface = &iface->altsetting[iface->act_altsetting]; - if (interface->bInterfaceClass != 3) return NULL; - if (interface->bInterfaceSubClass != 1) return NULL; - if (interface->bInterfaceProtocol != 2) return NULL; if (interface->bNumEndpoints != 1) return NULL; endpoint = interface->endpoint + 0; @@ -116,6 +115,8 @@ if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL; memset(mouse, 0, sizeof(struct usb_mouse)); + mouse->usbdev = dev; + mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL); mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y); @@ -150,7 +151,6 @@ kfree(buf); - mouse->my_usb_device = dev; FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp, usb_mouse_irq, mouse, endpoint->bInterval); @@ -170,10 +170,18 @@ kfree(mouse); } +static struct usb_device_id usb_mouse_id_table [] = { + { bInterfaceClass: 3, bInterfaceSubClass: 1, bInterfaceProtocol: 2}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, usb_mouse_id_table); + static struct usb_driver usb_mouse_driver = { name: "usb_mouse", probe: usb_mouse_probe, disconnect: usb_mouse_disconnect, + id_table: usb_mouse_id_table, }; static int __init usb_mouse_init(void) diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/uss720.c linux/drivers/usb/uss720.c --- v2.4.0-test10/linux/drivers/usb/uss720.c Thu Sep 7 08:36:40 2000 +++ linux/drivers/usb/uss720.c Sat Nov 11 18:17:09 2000 @@ -32,6 +32,7 @@ * 0.3 10.08.99 fixing merge errors * 0.4 13.08.99 Added Vendor/Product ID of Brad Hard's cable * 0.5 20.09.99 usb_control_msg wrapper used + * Nov01.00 usb_device_table support by Adam J. Richter * */ @@ -534,7 +535,8 @@ /* --------------------------------------------------------------------- */ -static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum) +static void * uss720_probe(struct usb_device *usbdev, unsigned int ifnum, + const struct usb_device_id *id) { struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; @@ -542,11 +544,6 @@ struct parport *pp; int i; - if ((usbdev->descriptor.idVendor != 0x047e || usbdev->descriptor.idProduct != 0x1001) && - (usbdev->descriptor.idVendor != 0x0557 || usbdev->descriptor.idProduct != 0x2001) && - (usbdev->descriptor.idVendor != 0x0729 || usbdev->descriptor.idProduct != 0x1284)) - return NULL; - printk(KERN_DEBUG "uss720: probe: vendor id 0x%x, device id 0x%x\n", usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); @@ -626,11 +623,22 @@ MOD_DEC_USE_COUNT; } +/* table of cables that work through this driver */ +static struct usb_device_id uss720_table [] = { + { idVendor: 0x047e, idProduct: 0x1001}, + { idVendor: 0x0557, idProduct: 0x2001}, + { idVendor: 0x0729, idProduct: 0x1284}, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, uss720_table); + + static struct usb_driver uss720_driver = { - "uss720", - uss720_probe, - uss720_disconnect, - { NULL, NULL } + name: "uss720", + probe: uss720_probe, + disconnect: uss720_disconnect, + id_table: uss720_table, }; /* --------------------------------------------------------------------- */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c --- v2.4.0-test10/linux/drivers/usb/wacom.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/usb/wacom.c Sat Nov 11 18:48:18 2000 @@ -1,10 +1,11 @@ /* - * $Id: wacom.c,v 1.9 2000/05/29 09:01:52 vojtech Exp $ + * $Id: wacom.c,v 1.11 2000/10/18 12:12:26 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 * * USB Wacom Graphire and Wacom Intuos tablet support * @@ -21,23 +22,25 @@ * v1.8 (vp) - Submit URB only when operating, moved to CVS, * use input_report_key instead of report_btn and * other cleanups + * v1.11 (vp) - Add URB ->dev setting for new kernels + * v1.11 (jb) - Add support for the 4D Mouse & Lens */ /* * 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 + * 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 - * + * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to , or by paper mail: * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic @@ -70,17 +73,17 @@ * byte 5: Y high bits * byte 6: pen pressure low bits / mouse wheel * byte 7: pen presure high bits / mouse distance - * + * * There are also two single-byte feature reports (2 and 3). * * Wacom Intuos status packet: * * byte 0: report ID (2) - * byte 1: bit7 1 - sync bit + * byte 1: bit7 1 - sync bit * bit6 pointer in range * bit5 pointer type report * bit4 0 ? - * bit3 0 ? + * bit3 mouse packet type * bit2 pen button2 * bit1 pen button1 * bit0 0 ? @@ -88,12 +91,38 @@ * byte 3: X low bits * byte 4: Y high bits * byte 5: Y low bits + * + * Pen packet: + * * byte 6: bits 0-7: pressure (bits 2-9) * byte 7: bits 6-7: pressure (bits 0-1) * byte 7: bits 0-5: X tilt (bits 1-6) * byte 8: bit 7: X tilt (bit 0) * byte 8: bits 0-6: Y tilt (bits 0-6) * byte 9: bits 4-7: distance + * + * Mouse packet type 0: + * + * byte 6: bits 0-7: wheel (bits 2-9) + * byte 7: bits 6-7: wheel (bits 0-1) + * byte 7: bits 0-5: 0 + * byte 8: bits 6-7: 0 + * byte 8: bit 5: left extra button + * byte 8: bit 4: right extra button + * byte 8: bit 3: wheel (sign) + * byte 8: bit 2: right button + * byte 8: bit 1: middle button + * byte 8: bit 0: left button + * byte 9: bits 4-7: distance + * + * Mouse packet type 1: + * + * byte 6: bits 0-7: rotation (bits 2-9) + * byte 7: bits 6-7: rotation (bits 0-1) + * byte 7: bit 5: rotation (sign) + * byte 7: bits 0-4: 0 + * byte 8: bits 0-7: 0 + * byte 9: bits 4-7: distance */ #define USB_VENDOR_ID_WACOM 0x056a @@ -192,7 +221,7 @@ case 0x0fa: wacom->tool = BTN_TOOL_RUBBER; break; /* Eraser */ case 0x112: wacom->tool = BTN_TOOL_AIRBRUSH; break; /* Airbrush */ default: wacom->tool = BTN_TOOL_PEN; break; /* Unknown tool */ - } + } input_report_key(dev, wacom->tool, 1); return; } @@ -205,31 +234,63 @@ input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]); input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]); - input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); input_report_abs(dev, ABS_DISTANCE, data[9] >> 4); - input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); - input_report_key(dev, BTN_STYLUS, data[1] & 2); - input_report_key(dev, BTN_STYLUS2, data[1] & 4); - input_report_key(dev, BTN_TOUCH, t > 10); + switch (wacom->tool) { + + case BTN_TOOL_PENCIL: + case BTN_TOOL_PEN: + case BTN_TOOL_BRUSH: + case BTN_TOOL_RUBBER: + case BTN_TOOL_AIRBRUSH: + + input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7)); + input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f); + input_report_key(dev, BTN_STYLUS, data[1] & 2); + input_report_key(dev, BTN_STYLUS2, data[1] & 4); + input_report_key(dev, BTN_TOUCH, t > 10); + break; + + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + + if (data[1] & 0x02) { /* Rotation packet */ + input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? + ((__u32)data[6] << 2) | ((data[7] >> 6) & 3): + (-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1); + break; + } + + input_report_key(dev, BTN_LEFT, data[8] & 0x01); + input_report_key(dev, BTN_MIDDLE, data[8] & 0x02); + input_report_key(dev, BTN_RIGHT, data[8] & 0x04); + input_report_key(dev, BTN_SIDE, data[8] & 0x20); + input_report_key(dev, BTN_EXTRA, data[8] & 0x10); + input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? + ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) : + -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)); + break; + } } #define WACOM_INTUOS_TOOLS (BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS)) +#define WACOM_INTUOS_BUTTONS (BIT(BTN_SIDE) | BIT(BTN_EXTRA)) +#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, BIT(REL_WHEEL), BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE), 0 }, + BIT(EV_REL), 0, 0, 0 }, { "Wacom Intuos 4x5", 0x20, 10, 12700, 10360, 1023, 15, wacom_intuos_irq, - 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, + 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { "Wacom Intuos 6x8", 0x21, 10, 20320, 15040, 1023, 15, wacom_intuos_irq, - 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, + 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { "Wacom Intuos 9x12", 0x22, 10, 30480, 23060, 1023, 15, wacom_intuos_irq, - 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, + 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { "Wacom Intuos 12x12", 0x23, 10, 30480, 30480, 1023, 15, wacom_intuos_irq, - 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, + 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { "Wacom Intuos 12x18", 0x24, 10, 47720, 30480, 1023, 15, wacom_intuos_irq, - 0, BIT(ABS_TILT_X) | BIT(ABS_TILT_Y), 0, 0, WACOM_INTUOS_TOOLS }, + 0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS }, { NULL , 0 } }; @@ -275,7 +336,7 @@ 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; wacom->dev.relbit[0] |= wacom->features->relbit; - wacom->dev.keybit[LONG(BTN_LEFT)] |= wacom->features->btnbit; + wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | wacom->features->btnbit; wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit; @@ -285,6 +346,14 @@ wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max; wacom->dev.absmax[ABS_TILT_X] = 127; wacom->dev.absmax[ABS_TILT_Y] = 127; + + wacom->dev.absmin[ABS_RZ] = -900; + wacom->dev.absmax[ABS_RZ] = 899; + wacom->dev.absmin[ABS_THROTTLE] = -1023; + wacom->dev.absmax[ABS_THROTTLE] = 1023; + + wacom->dev.absfuzz[ABS_X] = 4; + wacom->dev.absfuzz[ABS_Y] = 4; wacom->dev.private = wacom; wacom->dev.open = wacom_open; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/Makefile linux/drivers/video/Makefile --- v2.4.0-test10/linux/drivers/video/Makefile Sun Oct 8 10:50:31 2000 +++ linux/drivers/video/Makefile Wed Nov 8 17:15:04 2000 @@ -89,7 +89,6 @@ obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o -obj-$(CONFIG_FB_SIS) += sisfb.o ifeq ($(CONFIG_FB_MATROX),y) SUB_DIRS += matrox @@ -109,6 +108,16 @@ MOD_SUB_DIRS += riva endif endif + +ifeq ($(CONFIG_FB_SIS),y) +SUB_DIRS += sis +obj-y += sis/sisfb.o +else + ifeq ($(CONFIG_FB_SIS),m) + MOD_SUB_DIRS += sis + endif +endif + obj-$(CONFIG_FB_SUN3) += sun3fb.o obj-$(CONFIG_FB_BWTWO) += bwtwofb.o diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c --- v2.4.0-test10/linux/drivers/video/S3triofb.c Fri Aug 4 18:06:34 2000 +++ linux/drivers/video/S3triofb.c Tue Nov 7 10:59:43 2000 @@ -60,8 +60,6 @@ #define IO_OUT16VAL(v, r) (((v) << 8) | (r)) -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - static int currcon = 0; static struct display disp; static struct fb_info fb_info; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/amifb.c linux/drivers/video/amifb.c --- v2.4.0-test10/linux/drivers/video/amifb.c Tue Jun 20 14:14:51 2000 +++ linux/drivers/video/amifb.c Tue Nov 7 10:59:43 2000 @@ -598,8 +598,6 @@ #define highw(x) ((u_long)(x)>>16 & 0xffff) #define loww(x) ((u_long)(x) & 0xffff) -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER #define VBlankOff() custom.intena = IF_COPER @@ -921,7 +919,7 @@ #endif }; -#define NUM_TOTAL_MODES arraysize(ami_modedb) +#define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb) static const char *mode_option __initdata = NULL; static int round_down_bpp = 1; /* for mode probing */ diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/atafb.c linux/drivers/video/atafb.c --- v2.4.0-test10/linux/drivers/video/atafb.c Tue Jun 20 14:14:51 2000 +++ linux/drivers/video/atafb.c Tue Nov 7 10:59:43 2000 @@ -86,8 +86,6 @@ #define SWITCH_NONE 0x00 -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define up(x, r) (((x) + (r) - 1) & ~((r)-1)) @@ -429,7 +427,7 @@ 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }, }; -static int num_atafb_predefined=arraysize(atafb_predefined); +static int num_atafb_predefined=ARRAY_SIZE(atafb_predefined); static int diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c --- v2.4.0-test10/linux/drivers/video/clgenfb.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/video/clgenfb.c Tue Nov 7 10:59:43 2000 @@ -99,8 +99,6 @@ #define assert(expr) #endif -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #ifdef TRUE #undef TRUE #endif @@ -450,7 +448,7 @@ } }; -#define NUM_TOTAL_MODES arraysize(clgenfb_predefined) +#define NUM_TOTAL_MODES ARRAY_SIZE(clgenfb_predefined) static struct fb_var_screeninfo clgenfb_default; /* @@ -2431,7 +2429,7 @@ DPRINTK ("ENTER\n"); - for (i = 0; i < arraysize(clgen_pci_probe_list); i++) { + for (i = 0; i < ARRAY_SIZE(clgen_pci_probe_list); i++) { pdev = NULL; while ((pdev = pci_find_device (PCI_VENDOR_ID_CIRRUS, clgen_pci_probe_list[i].device, pdev)) != NULL) { @@ -2582,7 +2580,7 @@ assert (z_o != NULL); assert (btype != NULL); - for (i = 0; i < arraysize(clgen_zorro_probe_list); i++) + for (i = 0; i < ARRAY_SIZE(clgen_zorro_probe_list); i++) if ((z = zorro_find_device(clgen_zorro_probe_list[i].id, NULL))) break; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c --- v2.4.0-test10/linux/drivers/video/cyberfb.c Tue Oct 31 12:42:27 2000 +++ linux/drivers/video/cyberfb.c Tue Nov 7 10:59:43 2000 @@ -107,8 +107,6 @@ #define DPRINTK(fmt, args...) #endif -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define wb_64(regs,reg,dat) (*(((volatile unsigned char *)regs) + reg) = dat) #define rb_64(regs, reg) (*(((volatile unsigned char *)regs) + reg)) @@ -221,7 +219,7 @@ }} }; -#define NUM_TOTAL_MODES arraysize(cyberfb_predefined) +#define NUM_TOTAL_MODES ARRAY_SIZE(cyberfb_predefined) static int Cyberfb_inverse = 0; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/fm2fb.c linux/drivers/video/fm2fb.c --- v2.4.0-test10/linux/drivers/video/fm2fb.c Wed Jul 26 11:08:40 2000 +++ linux/drivers/video/fm2fb.c Tue Nov 7 10:59:43 2000 @@ -144,8 +144,6 @@ static unsigned long fm2fb_reg_phys; static volatile unsigned char *fm2fb_reg; -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - static int currcon = 0; static struct display disp; static struct fb_info fb_info; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/g364fb.c linux/drivers/video/g364fb.c --- v2.4.0-test10/linux/drivers/video/g364fb.c Wed Jul 26 11:08:40 2000 +++ linux/drivers/video/g364fb.c Tue Nov 7 10:59:43 2000 @@ -77,8 +77,6 @@ #define MON_ID_REG 0xe4100000 /* unused */ #define RESET_REG 0xe4180000 /* Write only */ -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - static int currcon = 0; static struct display disp; static struct fb_info fb_info; diff -u --recursive --new-file v2.4.0-test10/linux/drivers/video/hpfb.c linux/drivers/video/hpfb.c --- v2.4.0-test10/linux/drivers/video/hpfb.c Sun Aug 6 11:25:46 2000 +++ linux/drivers/video/hpfb.c Tue Nov 7 10:59:43 2000 @@ -28,8 +28,6 @@ #include