From: Alan Cox Date: Fri, 23 Nov 2007 20:23:02 +0000 (-0500) Subject: Linux 2.2.19pre3 X-Git-Tag: 2.2.19pre3 X-Git-Url: http://git.neil.brown.name/?a=commitdiff_plain;h=8c0a2492e2f448ce27c2bb0e3f7868a7a16b8f75;p=history.git Linux 2.2.19pre3 o Merge ADMtek-comet tulip support (Jim McQuillan) o Update microcode driver (Tigran Aivazian) o Merge Don Becker's NE2K full duplex support (Juan Lacarta) o Optimise kernel compiler detect, kgcc before (Peter Samuelson) gcc272 also o Fix compile combination problems (Arjan van de Ven) o Update via-rhine driver to include Don's changes(Urban Widmark) for VT6102 o Documentation updates (Tim Waugh) o Add ISDN PCI defines to pci.h (Kai Germaschewski) o Fix smb/fat handling for pre 1980 dates (Igor Zhbanov) o SyncLink updates (Paul Fulghum) o ICP vortex driver updates (Andreas Köpf) o mdacon clean up (Pavel Rabel) o Fix bugs in es1370/es1371/sonicvibes/solo1/ (Thomas Sailer) dabusb o Speed up x86 irq/fault paths by avoiding xchg (Mikael Pettersson) locked cycles (from Brian Gerst's 2.4test change) o Tighten up K6 check in bug tests (Mikael Pettersson) o Backport configure scripts bug fixes (Mikael Pettersson) o Fix duplicat help entries (Riley Williams) o Fix small asm bug in constant size uaccess (David Kutz) o Update ymfpci driver to handle legacy audio (Daisuke Nagano) o Remove ymfsb driver now no longer needed (Daisuke Nagano) o Add Empeg support to usb-serial (Gary Brubaker) o Fix e820 handling (Andrea Arcangeli) o Fix lanstreamer SMP locking (George Staikos) o Fix S/390 non SMP build (Kurt Roeckx) o Fix the PCI syscall on PowerMac (Benjamin Herrenschmidt) o Fix IPC_RMID behaviour (Christoph Rohland) o Fix NETCTL_GETFD on sparc64 (Dave Miller) o Tidy unneeded restore_flags/save sequence (Arnaldo Carvalho de Melo) on the ultrastor o Fix resource clean up on error in 89xo (Arnaldo Carvalho de Melo) driver o Update wireless headers (Jean Tourrilhes) o Fix non modular emu10k init (Mikael Pettersson) o Fix cpuid/msr driver crashes (Andrew Morton) o Write core files sparse (Christoph Rohland) o Merge the i810 tco (watchdog) timer (Alan Cox) | original by Jeff Garzik --- diff --git a/Documentation/Changes b/Documentation/Changes index 371eb98e7c7f..84157c85c028 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -542,6 +542,28 @@ alias char-major-10-184 microcode to your /etc/modules.conf file. +Intel IA32 microcode +==================== + +A driver has been added to allow updating of Intel IA32 microcode, +accessible as both a devfs regular file and as a normal (misc) +character device. If you are not using devfs you may need to: + +mkdir /dev/cpu +mknod /dev/cpu/microcode c 10 184 +chmod 0644 /dev/cpu/microcode + +as root before you can use this. You'll probably also want to +get the user-space microcode_ctl utility to use with this. + +If you have compiled the driver as a module you may need to add +the following line: + +alias char-major-10-184 microcode + +to your /etc/modules.conf file. + + Where to get the files ********************** diff --git a/Documentation/Configure.help b/Documentation/Configure.help index f9c2acc4a052..83d751d191af 100644 --- a/Documentation/Configure.help +++ b/Documentation/Configure.help @@ -5895,6 +5895,25 @@ CONFIG_COMX_HW_MIXCOM If you want to compile this as a module, say M and read Documentation/modules.txt. The module will be called comx-hw-mixcom.o. +i810 TCO support +CONFIG_I810_TCO + Hardware driver for the TCO timer built into the Intel i810 and i815 + chipset family. The TCO (Total Cost of Ownership) timer is a watchdog + timer that will reboot the machine after it's second expiration. The + expiration time can be configured by commandline argument + "i810_margin=" where is the counter initial value. It is + decremented every 0.6 secs, the default is 50 which gives a timeout + of 30 seconds and one minute until reset. + + On some motherboards the driver may fail to reset the chipset's + NO_REBOOT flag which prevents the watchdog from rebooting the machine. + If this is the case you will get a kernel message like + "i810tco init: failed to reset NO_REBOOT flag". + + If you want to compile this as a module, say M and read + Documentation/modules.txt. The module will be called + i810-tco.o. + MultiGate Cisco-HDLC and synchronous PPP protocol support CONFIG_COMX_PROTO_PPP Cisco-HDLC and synchronous PPP protocol driver for all MultiGate boards. @@ -7511,13 +7530,6 @@ CONFIG_QUOTA ftp://metalab.unc.edu/pub/Linux/docs/HOWTO/mini. Probably the quota support is only useful for multi user systems. If unsure, say N. -Acorn's ADFS filesystem support (read only) (EXPERIMENTAL) -CONFIG_ADFS_FS - The Advanced Disk File System is the filesystem used on floppy and - hard disks by Acorn Systems. Currently in development, as a read- - only driver for hard disks. These should be the first partition - (eg. /dev/[sh]d?1) on each of your drives. If unsure, say N. - Support for USB CONFIG_USB Universal Serial Bus (USB) is a specification for a serial bus @@ -7890,6 +7902,16 @@ CONFIG_USB_SERIAL_DIGI_ACCELEPORT The module will be called digi_acceleport.o. If you want to compile it as a module, say M here and read Documentation/modules.txt. +USB Empeg empeg-car Mark I/II Driver +CONFIG_USB_SERIAL_EMPEG + Say Y here if you want to connect to your Empeg empeg-car Mark I/II + mp3 player via USB. + + This code is also available as a module ( = code which can be + inserted in and removed from the running kernel whenever you want). + The module will be called empeg.o. If you want to compile it as a + module, say M here and read Documentation/modules.txt. + USB Serial Converter verbose debug CONFIG_USB_SERIAL_DEBUG Say Y here if you want verbose debug messages from the USB Serial @@ -9696,6 +9718,24 @@ CONFIG_PRINTER If you have more than 3 printers, you need to increase the LP_NO variable in lp.c. +Amiga built-in parallel port support +CONFIG_PARPORT_AMIGA + Say Y here if you need support for the parallel port hardware on + Amiga machines. This code is also available as a module (say M), + called parport_amiga.o. If in doubt, saying N is the safe plan. + +Atari built-in parallel port support +CONFIG_PARPORT_ATARI + Say Y here if you need support for the parallel port hardware on + Atari machines. This code is also available as a module (say M), + called parport_atari.o. If in doubt, saying N is the safe plan. + +Multiface 3 parallel port card support +CONFIG_PARPORT_MFC3 + Say Y here if you need parallel port support for the MFC3 card. + This code is also available as a module (say M), called + parport_mfc3.o. If in doubt, saying N is the safe plan. + Support IEEE1284 status readback CONFIG_PRINTER_READBACK If your printer conforms to IEEE 1284, it may be able to provide a @@ -10742,17 +10782,6 @@ CONFIG_JOY_AMIGA to it. For more information on how to use the driver please read Documentation/joystick.txt -Atomwide Serial Support -CONFIG_ATOMWIDE_SERIAL - If you have an Atomwide Serial card for an Acorn system, say Y to - this option. The driver can handle 1, 2, or 3 port cards. - If unsure, say N - -The Serial Port Dual Serial Port -CONFIG_DUALSP_SERIAL - If you have the Serial Port's dual serial card for an Acorn system, - say Y to this option. If unsure, say N - NetWinder Button CONFIG_NWBUTTON If you enable this driver and create a character device node @@ -12815,22 +12844,6 @@ ZOLTRIX I/O port (0x20c or 0x30c) CONFIG_RADIO_ZOLTRIX_PORT Enter the I/O port of your Zoltrix radio card. -ADS Cadet AM/FM Tuner -CONFIG_RADIO_CADET - Say Y here if this is your AM/FM radio card. - - In order to control your radio card, you will need to use programs - that are compatible with the Video for Linux API. Information on - this API and pointers to "v4l" programs may be found on the WWW at - http://roadrunner.swansea.uk.linux.org/v4l.shtml; to browse the WWW, - you need to have access to a machine on the Internet that has a - program like lynx or netscape. - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read Documentation/modules.txt. The module will be - called radio-cadet.o - Miro PCM20 Radio CONFIG_RADIO_MIROPCM20 Choose Y here if you have this FM radio card. You also need to say Y diff --git a/Documentation/sound/ChangeLog.ymfsb b/Documentation/sound/ChangeLog.ymfsb deleted file mode 100644 index 11fede8f51c0..000000000000 --- a/Documentation/sound/ChangeLog.ymfsb +++ /dev/null @@ -1,19 +0,0 @@ -Sun May 21 15:14:37 2000 Daisuke Nagano - - * ymf_sb.c: Add 'master_vol' module parameter to change - 'PCM out Vol" of AC'97. - Should I support AC'97 mixer by implementing original mixer - codes... ? - - * ymf_sb.c: remove native UART401 support. External MIDI port - should be supported by sb_midi driver. - - *ymf_sb.c: add support for SPDIF OUT. Module parameter - 'spdif_out' is now available. - - -Tue May 16 19:29:29 2000 Daisuke Nagano - - * ymf_sb.c (checkCodec): add a little delays for reset devices. - - * ymf_sb.c (readRegWord): fixed addressing bug. diff --git a/Documentation/sound/README.ymfsb b/Documentation/sound/README.ymfsb deleted file mode 100644 index 3218d1d32bbb..000000000000 --- a/Documentation/sound/README.ymfsb +++ /dev/null @@ -1,127 +0,0 @@ -Legacy audio driver for YMF7xx PCI cards. - - -FIRST OF ALL -============ - - This code references YAMAHA's sample codes and data sheets. - I respect and thank for all people they made open the informations - about YMF7xx cards. - - And this codes heavily based on Jeff Garzik 's - old VIA 82Cxxx driver (via82cxxx.c). I also respect him. - - -DISCLIMER -========= - - This driver is currently at early ALPHA stage. It may cause serious - damage to your computer when used. - PLEASE USE IT AT YOUR OWN RISK. - - -ABOUT THIS DRIVER -================= - - This code enables you to use your YMF724[A-F], YMF740[A-C], YMF744, YMF754 - cards as "SoundBlaster Pro" compatible card. It can only play 22.05kHz / - 8bit / Stereo samples, control external MIDI port. - And it can handle AC'97 mixer of these cards. - - If you want to use your card as recent "16-bit" card, you should use - Alsa or OSS/Linux driver. Ofcource you can write native PCI driver for - your cards :) - - -INSTALL -======= - - First, it requires some sound driver modules in Linux kernel - (soundcore.o , sound.o, sb.o and uart401.o), so you should enable - these modules at kernel configuration (please refer some other - documentations for configuration of kernel). - And add the following line in /etc/modules.conf: - - options sb support=1 - - (NOTE: There are no need any configuration of sb modules) - - To compile ymfsb module, type 'make'. - And copy it to /lib/modules/(kernel_version)/misc, type 'depmod -a'. - - This module also requires /usr/src/linux/drivers/sound/ac97.[ch]. - If your kernel doesn't have these files, you should upgrade your kernel. - - -USAGE -===== - - # modprobe ymfsb (options) - - -OPTIONS FOR YMFSB -================= - - io : SB base address (0x220, 0x240, 0x260, 0x280) - synth_io : OPL3 base address (0x388, 0x398, 0x3a0, 0x3a8) - dma : DMA number (0,1,3) - spdif_out : SPDIF-out flag (0:disable 1:enable) - - These options will change in future... - - -FREQUENCY -========= - - When playing sounds via this driver, you will hear its pitch is slightly - lower than original sounds. Since this driver recognizes your card acts - with 21.739kHz sample rates rather than 22.050kHz (I think it must be - hardware restriction). So many players become tone deafness. - To prevent this, you should express some options to your sound player - that specify correct sample frequency. For example, to play your MP3 file - correctly with mpg123, specify the frequency like following: - - % mpg123 -r 21739 foo.mp3 - - -SPDIF OUT -========= - - With installing modules with option 'spdif_out=1', you can enjoy your - sounds from SPDIF-out of your card (if it had). - Its Fs is fixed to 48kHz (It never means the sample frequency become - up to 48kHz. All sounds via SPDIF-out also 22kHz samples). So your - digital-in capable components has to be able to handle 48kHz Fs. - - -COPYING -======= - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - -TODO -==== - * support for multiple cards - (set the different SB_IO,MPU_IO,OPL_IO for each cards) - - * support for OPL (dmfm) : There will be no requirements... :-< - - -AUTHOR -====== - - Daisuke Nagano - diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 1be7b76b59e7..c12592e642eb 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -185,6 +185,15 @@ TO DO List: -- Add everything else that is missing :) +Empeg empeg-car Mark I/II Driver (empeg.c) + + This is an experimental driver to provide connectivity support for the + client synchronization tools for an Empeg empeg-car mp3 player. + + The driver is still pretty new, so some testing 'in the wild' would be + helpful. :) + + Generic Serial driver If your device is not one of the above listed devices, compatible with diff --git a/Makefile b/Makefile index a751970a0f59..aec27f60880b 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 2 SUBLEVEL = 19 -EXTRAVERSION = pre2 +EXTRAVERSION = pre3 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) @@ -24,12 +24,14 @@ AS =$(CROSS_COMPILE)as LD =$(CROSS_COMPILE)ld # # foo-bar-gcc for cross builds -# gcc272 for Debian's old compiler for kernels -# kgcc for Conectiva and Red Hat 7 +# kgcc for Conectiva, Red Hat, Mandrake +# gcc272 for Debian # otherwise 'cc' # -CC =$(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else \ - $(CONFIG_SHELL) scripts/kwhich gcc272 2>/dev/null || $(CONFIG_SHELL) scripts/kwhich kgcc 2>/dev/null || echo cc; fi) \ +CCFOUND :=$(shell $(CONFIG_SHELL) scripts/kwhich kgcc gcc272 cc gcc) +## Faster, but requires GNU make 3.78, which postdates Linux 2.2.0 +##CC =$(if $(CROSS_COMPILE),$(CROSS_COMPILE)gcc,$(CCFOUND)) -D__KERNEL__ -I$(HPATH) +CC =$(shell if [ -n "$(CROSS_COMPILE)" ]; then echo $(CROSS_COMPILE)gcc; else echo $(CCFOUND); fi) \ -D__KERNEL__ -I$(HPATH) CPP =$(CC) -E AR =$(CROSS_COMPILE)ar diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index 0f3a95106ec1..f05e0994d1ab 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -152,6 +152,7 @@ int __init cpuid_init(void) static void cpuid_exit(void) { + unregister_chrdev(CPUID_MAJOR, "cpu/cpuid"); } module_init(cpuid_init); diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index 474b9d6d9fd3..419752f90834 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -267,16 +267,18 @@ error_code: pushl %ebx cld movl %es,%cx - xchgl %eax, ORIG_EAX(%esp) # orig_eax (get the error code. ) + movl ORIG_EAX(%esp), %esi # get the error code + movl ES(%esp), %edi # get the function address + movl %eax, ORIG_EAX(%esp) + movl %ecx, ES(%esp) movl %esp,%edx - xchgl %ecx, ES(%esp) # get the address and save es. - pushl %eax # push the error code - pushl %edx + pushl %esi # push the error code + pushl %edx # push the pt_regs pointer movl $(__KERNEL_DS),%edx movl %dx,%ds movl %dx,%es GET_CURRENT(%ebx) - call *%ecx + call *%edi addl $8,%esp jmp ret_from_exception @@ -333,11 +335,6 @@ ENTRY(coprocessor_segment_overrun) 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 diff --git a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c index 27f1c8c90fdc..61ca27d34a13 100644 --- a/arch/i386/kernel/microcode.c +++ b/arch/i386/kernel/microcode.c @@ -33,6 +33,8 @@ * Messages for error cases (non intel & no suitable microcode). * 1.06 07 Dec 2000, Tigran Aivazian * Pentium 4 support + backported fixes from 2.4 + * 1.07 13 Dec 2000, Tigran Aivazian + * More bugfixes backported from 2.4 */ #include @@ -47,7 +49,7 @@ #include #include -#define MICROCODE_VERSION "1.06" +#define MICROCODE_VERSION "1.07" MODULE_DESCRIPTION("Intel CPU (IA-32) microcode update driver"); MODULE_AUTHOR("Tigran Aivazian "); @@ -87,13 +89,10 @@ static struct miscdevice microcode_dev = { int __init microcode_init(void) { - int error = 0; - if (misc_register(µcode_dev) < 0) { - printk(KERN_WARNING - "microcode: can't misc_register on minor=%d\n", + printk(KERN_ERR "microcode: can't misc_register on minor=%d\n", MICROCODE_MINOR); - error = 1; + return -EINVAL; } printk(KERN_INFO "IA-32 Microcode Update Driver: v%s \n", MICROCODE_VERSION); @@ -234,18 +233,21 @@ static void do_update_one(void *arg) static ssize_t microcode_read(struct file *file, char *buf, size_t len, loff_t *ppos) { - if (*ppos >= mc_fsize) - return 0; + ssize_t err = 0; + down(µcode_sem); + if (*ppos >= mc_fsize) + goto out; if (*ppos + len > mc_fsize) len = mc_fsize - *ppos; - if (copy_to_user(buf, mc_applied + *ppos, len)) { - up(µcode_sem); - return -EFAULT; - } + err = -EFAULT; + if (copy_to_user(buf, mc_applied + *ppos, len)) + goto out; *ppos += len; + err = len; +out: up(µcode_sem); - return len; + return err; } static ssize_t microcode_write(struct file *file, const char *buf, size_t len, loff_t *ppos) @@ -300,11 +302,12 @@ static int microcode_ioctl(struct inode *inode, struct file *file, case MICROCODE_IOCFREE: down(µcode_sem); if (mc_applied) { + int bytes = smp_num_cpus * sizeof(struct microcode); + memset(mc_applied, 0, mc_fsize); kfree(mc_applied); mc_applied = NULL; - printk(KERN_WARNING - "microcode: freed %d bytes\n", mc_fsize); + printk(KERN_WARNING "microcode: freed %d bytes\n", bytes); mc_fsize = 0; up(µcode_sem); return 0; diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index 3e0acbf5055e..dc8c97da690e 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -260,6 +260,7 @@ int __init msr_init(void) static void msr_exit(void) { + unregister_chrdev(MSR_MAJOR, "cpu/msr"); } module_init(msr_init); diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index 7b771822b4f5..bf9a830a7c62 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -104,7 +104,7 @@ struct sys_desc_table_struct { unsigned short length; unsigned char table[0]; }; -struct e820map e820; +struct e820map e820 __initdata = { 0, }; unsigned char aux_device_present; @@ -272,8 +272,9 @@ visws_get_board_type_and_rev(void) visws_board_rev); } #endif -void __init add_memory_region(unsigned long long start, - unsigned long long size, int type) + +static void __init add_memory_region(unsigned long long start, + unsigned long long size, int type) { int x = e820.nr_map; @@ -288,6 +289,8 @@ void __init add_memory_region(unsigned long long start, e820.nr_map++; } /* add_memory_region */ +unsigned long i386_endbase __initdata = 0; + static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) { /* Only one memory region (or negative)? Ignore it */ @@ -309,10 +312,10 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) * Not right. Fix it up. */ if (type == E820_RAM) { - if (start < 0x100000ULL && end > 0xA0000ULL) { - if (start < 0xA0000ULL) - add_memory_region(start, 0xA0000ULL-start, type); - if (end < 0x100000ULL) + if (start < 0x100000ULL && end > i386_endbase) { + if (start < i386_endbase) + add_memory_region(start, i386_endbase-start, type); + if (end <= 0x100000ULL) continue; start = 0x100000ULL; size = end - start; @@ -323,9 +326,33 @@ static int __init copy_e820_map(struct e820entry * biosmap, int nr_map) return 0; } -#define LOWMEMSIZE() (0x9f000) +static void __init print_memory_map(char *who) +{ + int i; + + for (i = 0; i < e820.nr_map; i++) { + printk(" %s: %08lx @ %08lx ", who, + (unsigned long) e820.map[i].size, + (unsigned long) e820.map[i].addr); + switch (e820.map[i].type) { + case E820_RAM: printk("(usable)\n"); + break; + case E820_RESERVED: + printk("(reserved)\n"); + break; + case E820_ACPI: + printk("(ACPI data)\n"); + break; + case E820_NVS: + printk("(ACPI NVS)\n"); + break; + default: printk("type %lu\n", e820.map[i].type); + break; + } + } +} -void __init setup_memory_region(void) +static void __init setup_memory_region(void) { char *who = "BIOS-e820"; @@ -348,26 +375,27 @@ void __init setup_memory_region(void) } e820.nr_map = 0; - add_memory_region(0, LOWMEMSIZE(), E820_RAM); - add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM); + add_memory_region(0, i386_endbase, E820_RAM); + add_memory_region(HIGH_MEMORY, (mem_size << 10)-HIGH_MEMORY, + E820_RAM); } printk("BIOS-provided physical RAM map:\n"); + print_memory_map(who); } /* setup_memory_region */ static char command_line[COMMAND_LINE_SIZE] = { 0, }; char saved_command_line[COMMAND_LINE_SIZE]; -unsigned long i386_endbase __initdata = 0; __initfunc(void setup_arch(char **cmdline_p, unsigned long * memory_start_p, unsigned long * memory_end_p)) { - unsigned long memory_start, memory_end; - unsigned long max_pfn; + unsigned long memory_start, memory_end = 0; char c = ' ', *to = command_line, *from = COMMAND_LINE; int len = 0; int read_endbase_from_BIOS = 1; int i; + unsigned long user_mem = 0; #ifdef CONFIG_VISWS visws_get_board_type_and_rev(); @@ -402,26 +430,6 @@ __initfunc(void setup_arch(char **cmdline_p, memcpy(saved_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); saved_command_line[COMMAND_LINE_SIZE-1] = '\0'; - setup_memory_region(); - -#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) -#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) - max_pfn = 0; - for (i = 0; i < e820.nr_map; i++) { - unsigned long start, end; - /* RAM? */ - if (e820.map[i].type != E820_RAM) - continue; - start = PFN_UP(e820.map[i].addr); - end = PFN_DOWN(e820.map[i].addr + e820.map[i].size); - if (start >= end) - continue; - if (end > max_pfn) - max_pfn = end; - } - memory_end = (max_pfn << PAGE_SHIFT); - - for (;;) { /* * "mem=nopentium" disables the 4MB page tables. @@ -434,12 +442,12 @@ __initfunc(void setup_arch(char **cmdline_p, from += 9+4; boot_cpu_data.x86_capability &= ~X86_FEATURE_PSE; } else { - memory_end = simple_strtoul(from+4, &from, 0); + user_mem = simple_strtoul(from+4, &from, 0); if ( *from == 'K' || *from == 'k' ) { - memory_end = memory_end << 10; + user_mem = user_mem << 10; from++; } else if ( *from == 'M' || *from == 'm' ) { - memory_end = memory_end << 20; + user_mem = user_mem << 20; from++; } } @@ -448,7 +456,6 @@ __initfunc(void setup_arch(char **cmdline_p, { if (to != command_line) to--; i386_endbase = simple_strtoul(from+8, &from, 0); - i386_endbase += PAGE_OFFSET; read_endbase_from_BIOS = 0; } c = *(from++); @@ -484,7 +491,35 @@ __initfunc(void setup_arch(char **cmdline_p, } i386_endbase = BIOS_ENDBASE; } - i386_endbase += PAGE_OFFSET; + } + + if (!user_mem) + setup_memory_region(); + else { + e820.nr_map = 0; + add_memory_region(0, i386_endbase, E820_RAM); + add_memory_region(HIGH_MEMORY, user_mem-HIGH_MEMORY, E820_RAM); + printk("USER-provided physical RAM map:\n"); + print_memory_map("USER"); + } + +#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT) +#define PFN_DOWN(x) ((x) >> PAGE_SHIFT) + for (i = 0; i < e820.nr_map; i++) { + unsigned long long start, end; + /* RAM? */ + if (e820.map[i].type != E820_RAM) + continue; + start = e820.map[i].addr; + if (start >= 0xffffffff) + continue; + end = e820.map[i].addr + e820.map[i].size; + if (start >= end) + continue; + if (end > 0xffffffff) + end = 0xffffffff; + if (end > memory_end) + memory_end = end; } #define VMALLOC_RESERVE (64 << 20) /* 64MB for vmalloc */ diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index cbcbf45c4d1d..bad8514d60cd 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -680,7 +680,7 @@ extern unsigned long i386_endbase; */ unsigned long __init smp_alloc_memory(unsigned long mem_base) { - if (mem_base + PAGE_SIZE > i386_endbase) + if (mem_base + PAGE_SIZE > i386_endbase + PAGE_OFFSET) panic("smp_alloc_memory: Insufficient low memory for kernel trampoline 0x%lx.", mem_base); trampoline_base = (void *)mem_base; return mem_base + PAGE_SIZE; diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index c15ade35b23a..5bd458b0b74c 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -106,7 +106,6 @@ asmlinkage void stack_segment(void); asmlinkage void general_protection(void); asmlinkage void page_fault(void); asmlinkage void coprocessor_error(void); -asmlinkage void reserved(void); asmlinkage void alignment_check(void); asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); @@ -246,7 +245,6 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present, current) DO_ERROR(12, SIGBUS, "stack segment", stack_segment, current) DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current) -DO_ERROR(18, SIGSEGV, "reserved", reserved, current) /* I don't have documents for this but it does seem to cover the cache flush from user space exception some people get. */ DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current) diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 757e59cef8fb..9de0d67c0dcc 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -27,6 +27,7 @@ #include #include #include +#include extern void show_net_buffers(void); extern unsigned long init_smp_mappings(unsigned long); @@ -384,8 +385,6 @@ __initfunc(void test_wp_bit(void)) printk(".\n"); } -extern unsigned long i386_endbase; - __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) { unsigned long start_low_mem = PAGE_SIZE; @@ -417,15 +416,36 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem)) #endif start_mem = PAGE_ALIGN(start_mem); - while (start_low_mem < i386_endbase) { - clear_bit(PG_reserved, &mem_map[MAP_NR(start_low_mem)].flags); - start_low_mem += PAGE_SIZE; - } + for (tmp = __pa(start_low_mem); tmp < __pa(end_mem); + tmp += PAGE_SIZE) { + struct page * page = mem_map + (tmp >> PAGE_SHIFT); + int i; + extern struct e820map e820; - while (start_mem < end_mem) { - clear_bit(PG_reserved, &mem_map[MAP_NR(start_mem)].flags); - start_mem += PAGE_SIZE; + /* don't include kernel memory and bootmem allocations */ + if (tmp >= 0x100000 && tmp < __pa(start_mem)) + continue; + + for (i = 0; i < e820.nr_map; i++) { + unsigned long long start, end; + /* RAM? */ + if (e820.map[i].type != E820_RAM) + continue; + start = e820.map[i].addr; + if (start >= 0xffffffff) + continue; + end = e820.map[i].addr + e820.map[i].size; + if (start >= end) + continue; + if (end > 0xffffffff) + end = 0xffffffff; + + /* start and end are valid here */ + if (start <= tmp && tmp+PAGE_SIZE <= end) + clear_bit(PG_reserved, &page->flags); + } } + for (tmp = PAGE_OFFSET ; tmp < end_mem ; tmp += PAGE_SIZE) { if (tmp >= MAX_DMA_ADDRESS) clear_bit(PG_DMA, &mem_map[MAP_NR(tmp)].flags); diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index 42d1cfee68a2..f85aa8d4a26d 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -658,6 +658,10 @@ pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, ppc_md.get_rtc_time = pmac_get_rtc_time; ppc_md.calibrate_decr = pmac_calibrate_decr; + ppc_md.pci_dev_root_bridge = pmac_pci_dev_root_bridge; + ppc_md.pci_dev_mem_base = pmac_pci_dev_mem_base; + ppc_md.pci_dev_io_base = pmac_pci_dev_io_base; + #ifdef CONFIG_VT #ifdef CONFIG_MAC_KEYBOARD ppc_md.kbd_setkeycode = mackbd_setkeycode; diff --git a/arch/s390/config.in b/arch/s390/config.in index e1d357979d3c..f9155b285192 100644 --- a/arch/s390/config.in +++ b/arch/s390/config.in @@ -44,11 +44,14 @@ tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF endmenu source drivers/s390/Config.in + +mainmenu_option next_comment comment 'Character devices' bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256 fi +endmenu if [ "$CONFIG_NET" = "y" ]; then source net/Config.in diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 2477b5878a16..410cd597b094 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c @@ -41,7 +41,9 @@ EXPORT_SYMBOL(s390_request_irq_special); EXPORT_SYMBOL(s390_device_register); EXPORT_SYMBOL(s390_device_unregister); +#ifdef __SMP__ EXPORT_SYMBOL(s390_bh_lock); +#endif EXPORT_SYMBOL(ccw_alloc_request); EXPORT_SYMBOL(ccw_free_request); diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index ec0eff9e4bfa..9980903cc458 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -36,6 +36,9 @@ #include #include #include +#include "cpcmd.h" + +extern void reipl(int ipl_device); /* * Machine setup.. diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index b77c8e643e41..f5314b95de39 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -1,4 +1,4 @@ -/* $Id: sys_sparc32.c,v 1.107.2.14 2000/10/10 04:50:50 davem Exp $ +/* $Id: sys_sparc32.c,v 1.107.2.16 2000/12/20 02:45:00 anton Exp $ * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls. * * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) @@ -3462,7 +3462,7 @@ asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table) set_fs (KERNEL_DS); sys_get_kernel_syms(tbl); set_fs (old_fs); - for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) { + for (i = 0; i < len; i++, table++) { if (put_user (tbl[i].value, &table->value) || copy_to_user (table->name, tbl[i].name, 60)) break; @@ -3553,6 +3553,12 @@ struct nfsctl_fhparm32 { s32 gf32_version; }; +struct nfsctl_fdparm32 { + struct sockaddr gd32_addr; + s8 gd32_path[NFS_MAXPATHLEN+1]; + s32 gd32_version; +}; + struct nfsctl_arg32 { s32 ca32_version; /* safeguard */ union { @@ -3561,6 +3567,7 @@ struct nfsctl_arg32 { struct nfsctl_export32 u32_export; struct nfsctl_uidmap32 u32_umap; struct nfsctl_fhparm32 u32_getfh; + struct nfsctl_fdparm32 u32_getfd; u32 u32_debug; } u; #define ca32_svc u.u32_svc @@ -3569,6 +3576,7 @@ struct nfsctl_arg32 { #define ca32_umap u.u32_umap #define ca32_getfh u.u32_getfh #define ca32_authd u.u32_authd +#define ca32_getfd u.u32_getfd #define ca32_debug u.u32_debug }; @@ -3698,6 +3706,22 @@ static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32 return err; } +static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32) +{ + int err; + + err = __get_user(karg->ca_version, &arg32->ca32_version); + err |= copy_from_user(&karg->ca_getfd.gd_addr, + &arg32->ca32_getfd.gd32_addr, + (sizeof(struct sockaddr))); + err |= copy_from_user(&karg->ca_getfd.gd_path, + &arg32->ca32_getfd.gd32_path, + (NFS_MAXPATHLEN+1)); + err |= __get_user(karg->ca_getfd.gd_version, + &arg32->ca32_getfd.gd32_version); + return err; +} + static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32) { int err; @@ -3739,6 +3763,7 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct err = nfs_clnt32_trans(karg, arg32); break; case NFSCTL_EXPORT: + case NFSCTL_UNEXPORT: err = nfs_exp32_trans(karg, arg32); break; /* This one is unimplemented, be we're ready for it. */ @@ -3748,6 +3773,9 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct case NFSCTL_GETFH: err = nfs_getfh32_trans(karg, arg32); break; + case NFSCTL_GETFD: + err = nfs_getfd32_trans(karg, arg32); + break; case NFSCTL_LOCKD: /* We still have to copy over the version * because nfsctl still checks that. @@ -3765,7 +3793,11 @@ int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsct err = sys_nfsservctl(cmd, karg, kres); set_fs(oldfs); - if(!err && cmd == NFSCTL_GETFH) + if (err) + goto done; + + if((cmd == NFSCTL_GETFH) || + (cmd == NFSCTL_GETFD)) err = nfs_getfh32_res_trans(kres, res32); done: diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 28e8de47fcea..76a4ec56c0b9 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -102,6 +102,7 @@ if [ "$CONFIG_WATCHDOG" != "n" ]; then tristate ' Acquire SBC Watchdog Timer' CONFIG_ACQUIRE_WDT tristate ' Advantech SBC Watchdog Timer' CONFIG_ADVANTECH_WDT tristate ' Berkshire Products PC Watchdog' CONFIG_PCWATCHDOG + tristate ' Intel i810 TCO timer / Watchdog' CONFIG_I810_TCO tristate ' Mixcom Watchdog' CONFIG_MIXCOMWD tristate ' SBC-60XX Watchdog Timer' CONFIG_60XX_WDT tristate ' Software Watchdog' CONFIG_SOFT_WATCHDOG diff --git a/drivers/char/Makefile b/drivers/char/Makefile index b20ee607885d..acc8e533e7c6 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -689,6 +689,14 @@ else endif endif +ifeq ($(CONFIG_I810_TCO),y) +O_OBJS += i810-tco.o +else + ifeq ($(CONFIG_I810_TCO),m) + M_OBJS += i810-tco.o + endif +endif + # remove objects from modular that are also built in obj-m := $(filter-out $(obj-y), $(obj-m)) diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c new file mode 100644 index 000000000000..1d6c42fd541e --- /dev/null +++ b/drivers/char/i810-tco.c @@ -0,0 +1,343 @@ +/* + * i810-tco 0.02: TCO timer driver for i810 chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.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. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i810/i815 chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the 82801AA (82801AB) chip, + * see intel documentation from http://developer.intel.com, + * order number 290655-003 + * + * 20000710 Nils Faerber + * Initial Version 0.01 + * 20000728 Nils Faerber + * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "i810-tco.h" + + +/* Just in case that the PCI vendor and device IDs are not yet defined */ +#ifndef PCI_DEVICE_ID_INTEL_82801AA_0 +#define PCI_DEVICE_ID_INTEL_82801AA_0 0x2410 +#endif + +/* Default expire timeout */ +#define TIMER_MARGIN 50 /* steps of 0.6sec, 2 0x3f || tmrval < 0x03) + return -1; + + spin_lock(&tco_lock); + val = inb (TCO1_TMR); + val &= 0xc0; + val |= tmrval; + outb (val, TCO1_TMR); + val = inb (TCO1_TMR); + spin_unlock(&tco_lock); + + if ((val & 0x3f) != tmrval) + return -1; + + return 0; +} + +/* + * Reload (trigger) the timer. Lock is needed so we dont reload it during + * a reprogramming event + */ + +static void tco_timer_reload (void) +{ + spin_lock(&tco_lock); + outb (0x01, TCO1_RLD); + spin_unlock(&tco_lock); +} + +/* + * Read the current timer value + */ +static unsigned char tco_timer_read (void) +{ + return (inb (TCO1_RLD)); +} + + +/* + * Allow only one person to hold it open + */ + +static int i810tco_open (struct inode *inode, struct file *file) +{ + if (timer_alive) + return -EBUSY; + + /* + * Reload and activate timer + */ + tco_timer_reload (); + tco_timer_start (); + timer_alive = 1; + MOD_INC_USE_COUNT; + return 0; +} + +static int i810tco_release (struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + MOD_INC_USE_COUNT; + tco_timer_stop (); + timer_alive = 0; + MOD_DEC_USE_COUNT; + return 0; +} + +static ssize_t i810tco_write (struct file *file, const char *data, + size_t len, loff_t * ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* + * Refresh the timer. + */ + if (len) { + tco_timer_reload (); + return 1; + } + return 0; +} + +static int i810tco_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + 0, + 0, + "i810 TCO timer" + }; + switch (cmd) { + default: + return -ENOIOCTLCMD; + case WDIOC_GETSUPPORT: + if (copy_to_user + ((struct watchdog_info *) arg, &ident, sizeof (ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + return put_user (tco_timer_read (), + (unsigned int *) (int) arg); + case WDIOC_GETBOOTSTATUS: + return put_user (boot_status, (int *) arg); + case WDIOC_KEEPALIVE: + tco_timer_reload (); + return 0; + } +} + +static struct pci_dev *i810tco_pci; + +static unsigned char i810tco_getdevice (void) +{ + u8 val1, val2; + u16 badr; + /* + * Find the PCI device which has vendor id 0x8086 + * and device ID 0x2410 + */ + i810tco_pci = pci_find_device (PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82801AA_0, NULL); + if (i810tco_pci) { + /* + * Find the ACPI base I/O address which is the base + * for the TCO registers (TCOBASE=ACPIBASE + 0x60) + * ACPIBASE is bits [15:7] from 0x40-0x43 + */ + pci_read_config_byte (i810tco_pci, 0x40, &val1); + pci_read_config_byte (i810tco_pci, 0x41, &val2); + badr = ((val2 << 1) | (val1 >> 7)) << 7; + ACPIBASE = badr; + /* Something's wrong here, ACPIBASE has to be set */ + if (badr == 0x0001 || badr == 0x0000) { + printk (KERN_ERR "i810tco init: failed to get TCOBASE address\n"); + return 0; + } + /* + * Check chipset's NO_REBOOT bit + */ + pci_read_config_byte (i810tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + val1 &= 0xfd; + pci_write_config_byte (i810tco_pci, 0xd4, val1); + pci_read_config_byte (i810tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + printk (KERN_ERR "i810tco init: failed to reset NO_REBOOT flag\n"); + return 0; /* Cannot reset NO_REBOOT bit */ + } + } + /* Set the TCO_EN bit in SMI_EN register */ + val1 = inb (SMI_EN + 1); + val1 &= 0xdf; + outb (val1, SMI_EN + 1); + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + boot_status = (int) inb (TCO2_STS); + outb (3, TCO2_STS); + return 1; + } + return 0; +} + +static struct file_operations i810tco_fops = { + write: i810tco_write, + ioctl: i810tco_ioctl, + open: i810tco_open, + release: i810tco_release, +}; + +static struct miscdevice i810tco_miscdev = { + WATCHDOG_MINOR, + "watchdog", + &i810tco_fops +}; + +static int __init watchdog_init (void) +{ + spin_lock_init(&tco_lock); + if (!i810tco_getdevice () || i810tco_pci == NULL) + return -ENODEV; + if (!check_region (TCOBASE, 0x10)) { + printk (KERN_ERR + "i810 TCO timer: I/O address 0x%04x already in use\n", + TCOBASE); + return -EIO; + } + request_region (TCOBASE, 0x10, "i810 TCO"); + if (misc_register (&i810tco_miscdev) != 0) { + release_region (TCOBASE, 0x10); + printk (KERN_ERR "i810 TCO timer: cannot register miscdev\n"); + return -EIO; + } + tco_timer_settimer ((unsigned char) i810_margin); + tco_timer_reload (); + + printk (KERN_INFO + "i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n", + (int) (i810_margin * 6 / 10), TCOBASE); + return 0; +} + +static void watchdog_cleanup (void) +{ + u8 val; + + /* Reset the timer before we leave */ + tco_timer_reload (); + /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ + pci_read_config_byte (i810tco_pci, 0xd4, &val); + val |= 0x02; + pci_write_config_byte (i810tco_pci, 0xd4, val); + release_region (TCOBASE, 0x10); + misc_deregister (&i810tco_miscdev); +} + +module_init(watchdog_init); +module_exit(watchdog_cleanup); diff --git a/drivers/char/i810-tco.h b/drivers/char/i810-tco.h new file mode 100644 index 000000000000..a078ae8f6e81 --- /dev/null +++ b/drivers/char/i810-tco.h @@ -0,0 +1,45 @@ +/* + * i810-tco 0.02: TCO timer driver for i810 chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.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. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i810 chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the 82801AA (82801AB) chip, + * see intel documentation from http://developer.intel.com, + * order number 290655-003 + * + * For history see i810-tco.c + */ + + +/* + * Some address definitions for the i810 TCO + */ + +#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ +#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ +#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ +#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ +#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ +#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ +#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ +#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ + +#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index eddb88f7f768..abdb4baa1576 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -9,7 +9,7 @@ * Al Longyear , Paul Mackerras * * Original release 01/11/99 - * ==FILEDATE 20000515== + * $Id: n_hdlc.c,v 2.2 2000/11/08 17:08:29 paul Exp $ * * This code is released under the GNU General Public License (GPL) * @@ -78,7 +78,7 @@ */ #define HDLC_MAGIC 0x239e -#define HDLC_VERSION "1.15" +#define HDLC_VERSION "2.2" #include #include @@ -93,14 +93,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,79 +111,23 @@ #include #endif -#if LINUX_VERSION_CODE >= VERSION(2,1,4) +#if LINUX_VERSION_CODE < VERSION(2,2,18) +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 + #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 @@ -254,10 +191,8 @@ N_HDLC_BUF* n_hdlc_buf_get(N_HDLC_BUF_LIST *list); 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 @@ -274,13 +209,8 @@ static rw_ret_t n_hdlc_tty_write(struct tty_struct *, 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); @@ -653,10 +583,10 @@ static void n_hdlc_tty_receive(struct tty_struct *tty, 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 +#if LINUX_VERSION_CODE >= VERSION(2,2,14) && defined(__rh_config_h__) kill_fasync (n_hdlc->tty->fasync, SIGIO, POLL_IN); +#else + kill_fasync (n_hdlc->tty->fasync, SIGIO); #endif } /* end of n_hdlc_tty_receive() */ @@ -886,73 +816,6 @@ static int n_hdlc_tty_ioctl (struct tty_struct *tty, struct file * file, } /* 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 @@ -981,11 +844,8 @@ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, 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 */ @@ -999,8 +859,6 @@ static unsigned int n_hdlc_tty_poll (struct tty_struct *tty, return mask; } /* end of n_hdlc_tty_poll() */ -#endif - /* n_hdlc_alloc() * * Allocate an n_hdlc instance data structure @@ -1153,19 +1011,13 @@ int init_module(void) 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; diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index 0dc91c991d68..f2c44510aadd 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c @@ -1,7 +1,7 @@ /* * linux/drivers/char/synclink.c * - * ==FILEDATE 20000821== + * $Id: synclink.c,v 2.4 2000/12/11 20:08:18 paul Exp $ * * Device driver for Microgate SyncLink ISA and PCI * high speed multiprotocol serial adapters. @@ -79,17 +79,10 @@ #include #include #include - #include - -#if LINUX_VERSION_CODE >= VERSION(2,1,0) #include #include #include -#else -#include -#endif - #include #include @@ -102,90 +95,34 @@ #include #include +#if LINUX_VERSION_CODE < VERSION(2,2,18) +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" @@ -944,7 +881,6 @@ static int debug_level = 0; 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"); @@ -954,10 +890,9 @@ MODULE_PARM(dma,"1-" __MODULE_STRING(MAX_ISA_DEVICES) "i"); 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.22"; +static char *driver_version = "2.3"; static struct tty_driver serial_driver, callout_driver; static int serial_refcount; @@ -969,9 +904,9 @@ static int serial_refcount; 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)) @@ -1372,11 +1307,6 @@ void mgsl_isr_io_pin( struct mgsl_struct *info ) #endif } else info->input_signal_events.dcd_down++; -#ifdef CONFIG_HARD_PPS - if ((info->flags & ASYNC_HARDPPS_CD) && - (status & MISCSTATUS_DCD_LATCHED)) - hardpps(); -#endif } if (status & MISCSTATUS_CTS_LATCHED) { @@ -1583,14 +1513,8 @@ void mgsl_isr_receive_data( struct mgsl_struct *info ) 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() */ @@ -1787,11 +1711,7 @@ static int startup(struct mgsl_struct * info) 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; @@ -1967,19 +1887,7 @@ static void mgsl_change_params(struct mgsl_struct *info) * current data rate. */ if (info->params.data_rate <= 460800) { -#if LINUX_VERSION_CODE >= VERSION(2,1,0) 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 ) { @@ -2942,7 +2850,6 @@ static int set_modem_info(struct mgsl_struct * info, unsigned int cmd, } /* 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 @@ -2969,7 +2876,6 @@ static void mgsl_break(struct tty_struct *tty, int break_state) spin_unlock_irqrestore(&info->irq_spinlock,flags); } /* end of mgsl_break() */ -#endif /* mgsl_ioctl() Service an IOCTL request * @@ -3092,7 +2998,6 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long 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); @@ -3107,7 +3012,6 @@ int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long if (error) return error; PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun); if (error) return error; -#endif return 0; default: return -ENOIOCTLCMD; @@ -3346,7 +3250,6 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout) } } - set_current_state(TASK_RUNNING); exit: if (debug_level >= DEBUG_LEVEL_INFO) printk("%s(%d):mgsl_wait_until_sent(%s) exit\n", @@ -3589,9 +3492,7 @@ static int mgsl_open(struct tty_struct *tty, struct file * filp) 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) { @@ -3978,27 +3879,19 @@ int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) } /* 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 ) { if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI ) - kfree_s(info->buffer_list, BUFFERLISTSIZE); + kfree(info->buffer_list); info->buffer_list = NULL; info->rx_buffer_list = NULL; @@ -4072,7 +3965,7 @@ void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList for ( i = 0 ; i < Buffercount ; i++ ) { if ( BufferList[i].virt_addr ) { if ( info->bus_type != MGSL_BUS_TYPE_PCI ) - kfree_s(BufferList[i].virt_addr, DMABUFFERSIZE); + kfree(BufferList[i].virt_addr); BufferList[i].virt_addr = NULL; } } @@ -4131,19 +4024,12 @@ int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info) void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info) { if ( info->intermediate_rxbuffer ) - kfree_s( info->intermediate_rxbuffer, info->max_frame_size); + 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 */ @@ -4168,7 +4054,7 @@ int mgsl_claim_resources(struct mgsl_struct *info) info->irq_requested = 1; if ( info->bus_type == MGSL_BUS_TYPE_PCI ) { - /* claim shared memory range */ + 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", @@ -4177,7 +4063,6 @@ int mgsl_claim_resources(struct mgsl_struct *info) return -ENODEV; } - /* 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 ); @@ -4185,7 +4070,6 @@ int mgsl_claim_resources(struct mgsl_struct *info) return -ENODEV; } - /* 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", @@ -4221,13 +4105,6 @@ int mgsl_claim_resources(struct mgsl_struct *info) } /* 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 ) @@ -4380,9 +4257,7 @@ int mgsl_enumerate_devices() 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 (!(info = mgsl_allocate_device())) { if ( debug_level >= DEBUG_LEVEL_ERROR ) printk( "can't allocate device instance data.\n"); continue; @@ -4391,12 +4266,7 @@ int mgsl_enumerate_devices() /* 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; @@ -4412,73 +4282,29 @@ int mgsl_enumerate_devices() 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 (!(info = mgsl_allocate_device())) { if ( debug_level >= DEBUG_LEVEL_ERROR ) printk( "can't allocate device instance data.\n"); continue; } /* Copy user configuration info to device instance data */ + info->irq_level = pdev->irq; + info->phys_lcr_base = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK; + info->io_base = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK; + info->phys_memory_base = pdev->base_address[3] & PCI_BASE_ADDRESS_MEM_MASK; - 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); @@ -4508,30 +4334,9 @@ int mgsl_enumerate_devices() } #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__); - if (serial_table) - kfree(serial_table); - if (serial_termios) - kfree(serial_termios); - if (serial_termios_locked) - kfree(serial_termios_locked); - 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); + 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); return 0; @@ -4548,11 +4353,7 @@ int __init mgsl_init(void) { 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); @@ -4567,9 +4368,7 @@ int __init mgsl_init(void) 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; @@ -4596,12 +4395,10 @@ int __init mgsl_init(void) 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; @@ -4615,10 +4412,8 @@ int __init mgsl_init(void) 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", @@ -4645,8 +4440,7 @@ int __init mgsl_init(void) } /* end of mgsl_init() */ -#ifdef MODULE -int init_module(void) +int __init init_module(void) { /* Uncomment this to kernel debug module. * mgsl_get_text_ptr() leaves the .text address in eax @@ -4692,20 +4486,8 @@ void cleanup_module(void) tmp_buf = NULL; } - if (serial_table) - kfree_s(serial_table,sizeof(struct tty_struct*)*mgsl_device_count); - - if (serial_termios) - kfree_s(serial_termios,sizeof(struct termios*)*mgsl_device_count); - - if (serial_termios_locked) - kfree_s(serial_termios_locked,sizeof(struct termios*)*mgsl_device_count); - } /* end of cleanup_module() */ -#endif /* MODULE */ - - /* * usc_RTCmd() * @@ -6952,7 +6734,6 @@ BOOLEAN mgsl_irq_test( struct mgsl_struct *info ) 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); @@ -7575,7 +7356,7 @@ void mgsl_sppp_init(struct mgsl_struct *info) sppp_attach(&info->pppdev); d = info->netdev; - strcpy(d->name, info->netname); + d->name = info->netname; d->base_addr = info->io_base; d->irq = info->irq_level; d->dma = info->dma_level; @@ -7586,10 +7367,6 @@ void mgsl_sppp_init(struct mgsl_struct *info) 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) { @@ -7679,7 +7456,6 @@ int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev) 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 */ @@ -7687,9 +7463,6 @@ int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *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); diff --git a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c index d9b2e80e04cc..a9c7b9ecd899 100644 --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c @@ -463,5 +463,6 @@ setup_sct_quadro(struct IsdnCard *card)) return (1); #else printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n"); + return (0); #endif /* CONFIG_PCI */ } diff --git a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c index ce58ec1d08d8..4c562e37bbdf 100644 --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c @@ -148,10 +148,10 @@ setup_netjet_s(struct IsdnCard *card)) return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); +#if CONFIG_PCI for ( ;; ) { -#if CONFIG_PCI if (!pci_present()) { printk(KERN_ERR "Netjet: no PCI bus present\n"); diff --git a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c index cb7ce68f991c..8e5bc14c0645 100644 --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c @@ -150,10 +150,10 @@ setup_netjet_u(struct IsdnCard *card)) return(0); test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); +#if CONFIG_PCI for ( ;; ) { -#if CONFIG_PCI if (!pci_present()) { printk(KERN_ERR "NETspider-U: no PCI bus present\n"); diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 75e7b08328ba..528c1900938e 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -183,7 +183,7 @@ comment 'Ethernet (1000 Mbit)' tristate 'Packet Engines GNIC-II (Hamachi) support' CONFIG_HAMACHI tristate 'Packet Engines Yellowfin Gigabit-NIC support' CONFIG_YELLOWFIN fi - tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN + dep_tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN $CONFIG_PCI endmenu bool 'FDDI driver support' CONFIG_FDDI diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index 7157f5d5209d..9238b0e72e3a 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -27,6 +27,8 @@ : is running from all accounts. Alan Cox : Removed 1.2 support, added 2.1 extra counters. + + Arnaldo Melo : release resources on failure in cs89x0_probe1 */ static char *version = @@ -249,13 +251,17 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr)) struct net_local *lp; static unsigned version_printed = 0; int i; + char priv_alloced_here = 0; unsigned rev_type = 0; int eeprom_buff[CHKSUM_LEN]; /* Initialize the device structure. */ if (dev->priv == NULL) { dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); + if (!dev->priv) + return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_local)); + priv_alloced_here = 1; } lp = (struct net_local *)dev->priv; @@ -265,12 +271,12 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr)) if (ioaddr & 1) { ioaddr &= ~1; if ((inw(ioaddr + ADD_PORT) & ADD_MASK) != ADD_SIG) - return ENODEV; + goto err; outw(PP_ChipID, ioaddr + ADD_PORT); } if (inw(ioaddr + DATA_PORT) != CHIP_EISA_ID_SIG) - return ENODEV; + goto err; /* Fill in the 'dev' fields. */ dev->base_addr = ioaddr; @@ -388,6 +394,11 @@ __initfunc(static int cs89x0_probe1(struct device *dev, int ioaddr)) printk("\n"); return 0; +err: if (priv_alloced_here) { + kfree(dev->priv); + dev->priv = NULL; + } + return -ENODEV; } diff --git a/drivers/net/lanstreamer.c b/drivers/net/lanstreamer.c index bd0c3fd90b64..19af8b2da7de 100644 --- a/drivers/net/lanstreamer.c +++ b/drivers/net/lanstreamer.c @@ -58,6 +58,7 @@ * First release to the public * 03/03/00 - Merged to kernel, indented -kr -i8 -bri0, fixed some missing * malloc free checks, reviewed code. + * 12/18/00 - Made it SMP safe - George Staikos * * To Do: * @@ -108,6 +109,7 @@ #include #include +#include #include #include @@ -285,6 +287,8 @@ static int __init streamer_init(struct device *dev) streamer_priv = (struct streamer_private *) dev->priv; streamer_mmio = streamer_priv->streamer_mmio; + streamer_priv->lock = (spinlock_t) SPIN_LOCK_UNLOCKED; + printk("%s \n", version); printk(KERN_INFO "%s: IBM PCI tokenring card. I/O at %hx, MMIO at %p, using irq %d\n", dev->name, (unsigned int) dev->base_addr, @@ -823,6 +827,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs) __u16 misr; __u16 sisrmask; + spin_lock(&(streamer_priv->lock)); sisrmask = SISR_MI; writew(~sisrmask, streamer_mmio + SISR_MASK_RUM); sisr = readw(streamer_mmio + SISR); @@ -831,6 +836,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs) writew(~misr, streamer_mmio + MISR_RUM); if (!sisr) { /* Interrupt isn't for us */ + spin_unlock(&(streamer_priv->lock)); return; } @@ -919,6 +925,7 @@ static void streamer_interrupt(int irq, void *dev_id, struct pt_regs *regs) dev->interrupt = 0; writew(SISR_MI, streamer_mmio + SISR_MASK_SUM); + spin_unlock(&(streamer_priv->lock)); } @@ -927,11 +934,14 @@ static int streamer_xmit(struct sk_buff *skb, struct device *dev) struct streamer_private *streamer_priv = (struct streamer_private *) dev->priv; __u8 *streamer_mmio = streamer_priv->streamer_mmio; + int flags; if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) { return 1; } + spin_lock_irqsave(&(streamer_priv->lock), flags); + if (streamer_priv->free_tx_ring_entries) { streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].status = 0; streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_free].bufcnt_framelen = 0x00010000 | skb->len; @@ -956,8 +966,10 @@ static int streamer_xmit(struct sk_buff *skb, struct device *dev) streamer_priv->tx_ring_free = (streamer_priv->tx_ring_free + 1) & (STREAMER_TX_RING_SIZE - 1); dev->tbusy = 0; + spin_unlock_irqrestore(&(streamer_priv->lock), flags); return 0; } else { + spin_unlock_irqrestore(&(streamer_priv->lock), flags); return 1; } } diff --git a/drivers/net/lanstreamer.h b/drivers/net/lanstreamer.h index f8803334889e..085006cf9961 100644 --- a/drivers/net/lanstreamer.h +++ b/drivers/net/lanstreamer.h @@ -283,6 +283,7 @@ struct streamer_private { __u16 streamer_addr_table_addr, streamer_parms_addr; __u16 mac_rx_buffer; __u8 streamer_laa[6]; + spinlock_t lock; }; struct streamer_adapter_addr_table { diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c index 1bfe98d89b8b..4ef5a218a549 100644 --- a/drivers/net/ne2k-pci.c +++ b/drivers/net/ne2k-pci.c @@ -12,19 +12,31 @@ 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 + 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. - People are making PCI ne2000 clones! Oh the horror, the horror... + 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. + + ChangeLog: + + 12/15/2000 Merged Scyld v1.02 into 2.2.18 + J.A. Magallon */ -/* 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"; #include #include @@ -49,7 +61,18 @@ static const char *version = #endif /* Set statically or when loading the driver module. */ -static int debug = 1; +static int debug = 1; /* 1 normal messages, 0 quiet .. 7 verbose. */ +/* More are supported, limit only on options */ +#define MAX_UNITS 6 +/* Used to pass the full-duplex flag, etc. */ +static int full_duplex[MAX_UNITS] = {0, }; +static int options[MAX_UNITS] = {0, }; + +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. */ @@ -62,12 +85,13 @@ static int debug = 1; /* 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, }; @@ -79,18 +103,17 @@ static struct { int flags; } pci_clone_list[] __initdata = { - {0x10ec, 0x8029, "RealTek RTL-8029", 0}, - {0x1050, 0x0940, "Winbond 89C940", 0}, - {0x11f6, 0x1401, "Compex RL2000", 0}, - {0x8e2e, 0x3000, "KTI ET32P2", 0}, - {0x4a14, 0x5000, "NetVin NV5000SC", 0}, - {0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO}, - {0x10bd, 0x0e34, "SureCom NE34", 0}, - {0x1050, 0x5a5a, "Winbond", 0}, - {0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO | HOLTEK_FDX}, - {0x12c3, 0x5598, "Holtek HT80229", - ONLY_32BIT_IO | HOLTEK_FDX | STOP_PG_0x60 }, - {0,} +{0x10ec, 0x8029, "RealTek RTL-8029", REALTEK_FDX}, +{0x1050, 0x0940, "Winbond 89C940", 0}, +{0x1050, 0x5a5a, "Winbond w89c940", 0}, +{0x8e2e, 0x3000, "KTI ET32P2", 0}, +{0x4a14, 0x5000, "NetVin NV5000SC", 0}, +{0x1106, 0x0926, "Via 86C926", ONLY_16BIT_IO}, +{0x10bd, 0x0e34, "SureCom NE34", 0}, +{0x12c3, 0x0058, "Holtek HT80232", ONLY_16BIT_IO|HOLTEK_FDX}, +{0x12c3, 0x5598, "Holtek HT80229", ONLY_32BIT_IO|HOLTEK_FDX|STOP_PG_0x60 }, +{0x11f6, 0x1401, "Compex RL2000", 0}, +{0,} }; /* ---- No user-serviceable parts below ---- */ @@ -119,7 +142,7 @@ static void ne2k_pci_block_input(struct device *dev, int count, static void ne2k_pci_block_output(struct device *dev, const int count, const unsigned char *buf, const int start_page); - + /* No room in the standard 8390 structure for extra info we need. */ struct ne2k_pci_card { @@ -137,7 +160,7 @@ init_module(void) { /* We must emit version information. */ if (debug) - printk(KERN_INFO "%s", version); + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); if (ne2k_pci_probe(0)) { printk(KERN_NOTICE "ne2k-pci.c: No useable cards found, driver NOT installed.\n"); @@ -263,8 +286,8 @@ __initfunc (int ne2k_pci_probe(struct device *dev)) return cards_found ? 0 : -ENODEV; } -__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioaddr, int irq, - int chip_idx)) +__initfunc (static struct device *ne2k_pci_probe1(struct device *dev, + long ioaddr, int irq, int chip_idx)) { int i; unsigned char SA_prom[32]; @@ -291,6 +314,8 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioadd dev = init_etherdev(dev, 0); + if (!dev) return 0; + /* Reset card. Who knows what dain-bramaged state it was left in. */ { unsigned long reset_start_time = jiffies; @@ -342,7 +367,7 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioadd /* 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) { - for (i = 0; i < 4 ; i++) + for (i = 0; i < 8 ; i++) ((u32 *)SA_prom)[i] = le32_to_cpu(inl(ioaddr + NE_DATAPORT)); } else for(i = 0; i < 32 /*sizeof(SA_prom)*/; i++) @@ -379,6 +404,10 @@ __initfunc (static struct device *ne2k_pci_probe1(struct device *dev, long ioadd ei_status.stop_page = stop_page; ei_status.word16 = 1; ei_status.ne2k_flags = pci_clone_list[chip_idx].flags; + if (chip_idx < MAX_UNITS) { + if (full_duplex[chip_idx] || (options[chip_idx] & FORCE_FDX)) + ei_status.ne2k_flags |= FORCE_FDX; + } ei_status.rx_start_page = start_page + TX_PAGES; #ifdef PACKETBUF_MEMSIZE @@ -401,8 +430,17 @@ ne2k_pci_open(struct device *dev) { if (request_irq(dev->irq, ei_interrupt, SA_SHIRQ, dev->name, dev)) return -EAGAIN; - ei_open(dev); MOD_INC_USE_COUNT; + /* 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; } diff --git a/drivers/net/tulip.c b/drivers/net/tulip.c index e2e67668878d..79baa359b4ea 100644 --- a/drivers/net/tulip.c +++ b/drivers/net/tulip.c @@ -15,10 +15,14 @@ Support and updates available at http://cesdis.gsfc.nasa.gov/linux/drivers/tulip.html - + This driver also contains updates by Wolfgang Walter and others. For this specific driver variant please use linux-kernel for bug reports. + + Updated 12/17/2000 by Jim McQuillan to + include support for the Linksys LNE100TX card based on the + Admtek 985 Centaur-P chipset. */ #define SMP_CHECK @@ -398,6 +402,8 @@ static struct tulip_chip_table { HAS_MII | HAS_NWAY143 | HAS_8023X, t21142_timer }, { "ADMtek Comet", 256, 0x0001abef, MC_HASH_ONLY, comet_timer }, + { "ADMtek Centaur-P", 256, 0x0001abef, + MC_HASH_ONLY, comet_timer }, { "Compex 9881 PMAC", 128, 0x0001ebef, HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, mxic_timer }, { "Intel DS21145 Tulip", 128, 0x0801fbff, @@ -411,8 +417,8 @@ static struct tulip_chip_table { /* This matches the table above. Note 21142 == 21143. */ enum chips { DC21040=0, DC21041=1, DC21140=2, DC21142=3, DC21143=3, - LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMPEX9881, - I21145, + LC82C168, MX98713, MX98715, MX98725, AX88140, PNIC2, COMET, COMET5, + COMPEX9881, I21145, XIRCOM, }; /* A full-duplex map for media types. */ @@ -423,7 +429,7 @@ static const char media_cap[] = {0,0,0,16, 3,19,16,24, 27,4,7,5, 0,20,23,20 }; static u8 t21040_csr13[] = {2,0x0C,8,4, 4,0,0,0, 0,0,0,0, 4,0,0,0}; /* 21041 transceiver register settings: 10-T, 10-2, AUI, 10-T, 10T-FD*/ -static u16 t21041_csr13[] = { 0xEF05, 0xEF0D, 0xEF0D, 0xEF05, 0xEF05, }; +static u16 t21041_csr13[] = { 0xEF01, 0xEF09, 0xEF09, 0xEF01, 0xEF09, }; static u16 t21041_csr14[] = { 0xFFFF, 0xF7FD, 0xF7FD, 0x7F3F, 0x7F3D, }; static u16 t21041_csr15[] = { 0x0008, 0x0006, 0x000E, 0x0008, 0x0008, }; @@ -584,7 +590,7 @@ int __init tulip_probe(struct device *dev) return -ENODEV; for (;pci_index < 0xff; pci_index++) { - u16 vendor, device, pci_command, new_command, subvendor; + u16 vendor, device, pci_command, new_command; int chip_idx; int irq; long ioaddr; @@ -602,13 +608,6 @@ int __init tulip_probe(struct device *dev) PCI_VENDOR_ID, &vendor); pcibios_read_config_word(pci_bus, pci_device_fn, PCI_DEVICE_ID, &device); - pcibios_read_config_word(pci_bus, pci_device_fn, - PCI_SUBSYSTEM_VENDOR_ID, &subvendor); - - if( subvendor == 0x1376 ){ - printk("tulip: skipping LMC card.\n"); - continue; - } for (chip_idx = 0; pci_tbl[chip_idx].vendor_id; chip_idx++) if (vendor == pci_tbl[chip_idx].vendor_id @@ -750,7 +749,13 @@ static struct device *tulip_probe1(int pci_bus, int pci_devfn, put_unaligned(le16_to_cpu(value), ((u16*)dev->dev_addr) + i); sum += value & 0xffff; } - } else if (chip_idx == COMET) { + } else if (chip_idx == COMET){ + /* No need to read the EEPROM. */ + put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr); + put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4)); + for (i = 0; i < 6; i ++) + sum += dev->dev_addr[i]; + } else if (chip_idx == COMET5){ /* No need to read the EEPROM. */ put_unaligned(inl(ioaddr + 0xA4), (u32 *)dev->dev_addr); put_unaligned(inl(ioaddr + 0xA8), (u16 *)(dev->dev_addr + 4)); @@ -995,6 +1000,9 @@ static struct device *tulip_probe1(int pci_bus, int pci_devfn, case COMET: /* No initialization necessary. */ break; + case COMET5: + /* No initialization necessary. */ + break; } if (tulip_tbl[chip_idx].flags & HAS_PWRDWN) @@ -1321,6 +1329,17 @@ static int mdio_read(struct device *dev, int phy_id, int location) } return 0xffff; } + if (tp->chip_id == COMET5) { + if (phy_id == 1) { + if (location < 7) + return inl(ioaddr + 0xB4 + (location<<2)); + else if (location == 17) + return inl(ioaddr + 0xD0); + else if (location >= 29 && location <= 31) + return inl(ioaddr + 0xD4 + ((location-29)<<2)); + } + return 0xffff; + } /* Establish sync by sending at least 32 logic ones. */ for (i = 32; i >= 0; i--) { @@ -1379,6 +1398,18 @@ static void mdio_write(struct device *dev, int phy_id, int location, int value) return; } + if (tp->chip_id == COMET5) { + if (phy_id != 1) + return; + if (location < 7) + outl(value, ioaddr + 0xB4 + (location<<2)); + else if (location == 17) + outl(value, ioaddr + 0xD0); + else if (location >= 29 && location <= 31) + outl(value, ioaddr + 0xD4 + ((location-29)<<2)); + return; + } + /* Establish sync by sending 32 logic ones. */ for (i = 32; i >= 0; i--) { outl(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr); @@ -1462,6 +1493,11 @@ tulip_open(struct device *dev) outl(addr_high, ioaddr + 0xA8); outl(0, ioaddr + 0xAC); outl(0, ioaddr + 0xB0); + } else if (tp->chip_id == COMET5) { + outl(addr_low, ioaddr + 0xA4); + outl(addr_high, ioaddr + 0xA8); + outl(0, ioaddr + 0xAC); + outl(0, ioaddr + 0xB0); } } else { /* This is set_rx_mode(), but without starting the transmitter. */ @@ -1575,6 +1611,9 @@ media_picked: } else if (tp->chip_id == COMET) { dev->if_port = 0; tp->csr6 = 0x00040000; + } else if (tp->chip_id == COMET5) { + dev->if_port = 0; + tp->csr6 = 0x00040000; } else if (tp->chip_id == AX88140) { tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100; } else @@ -3014,6 +3053,8 @@ static int private_ioctl(struct device *dev, struct ifreq *rq, int cmd) data[0] = 32; else if (tp->chip_id == COMET) data[0] = 1; + else if (tp->chip_id == COMET5) + data[0] = 1; else return -ENODEV; case SIOCDEVPRIVATE+1: /* Read the specified MII register. */ @@ -3142,6 +3183,9 @@ static void set_rx_mode(struct device *dev) } else if (tp->chip_id == COMET) { /* Has a simple hash filter. */ outl(mc_filter[0], ioaddr + 0xAC); outl(mc_filter[1], ioaddr + 0xB0); + } else if (tp->chip_id == COMET5) { /* Has a simple hash filter. */ + outl(mc_filter[0], ioaddr + 0xAC); + outl(mc_filter[1], ioaddr + 0xB0); } } } else { diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index 6ed796962939..7ad2863faddf 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -1,35 +1,44 @@ /* via-rhine.c: A Linux Ethernet device driver for VIA Rhine family chips. */ /* - Written 1998-1999 by Donald Becker. + Written 1998-2000 by Donald Becker. - This software may be used and distributed according to the terms - of the GNU Public License (GPL), incorporated herein by reference. - Drivers derived from this code also fall under the GPL and must retain - this authorship and copyright notice. + 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. This driver is designed for the VIA VT86c100A Rhine-II PCI Fast Ethernet controller. It also works with the older 3043 Rhine-I chip. - The author may be reached as becker@cesdis.edu, or - Donald Becker - 312 Severn Ave. #W302 + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation + 410 Severn Ave., Suite 210 Annapolis MD 21403 Support and updates available at - http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html + http://www.scyld.com/network/via-rhine.html + + + Linux kernel version history: + + LK1.0.0: + - Urban Widmark: merges from Beckers 1.08b version and 2.4.0 (VT6102) */ -static const char *versionA = -"via-rhine.c:v1.01 2/27/99 Written by Donald Becker\n"; -static const char *versionB = -" http://cesdis.gsfc.nasa.gov/linux/drivers/via-rhine.html\n"; +/* These identify the driver base version and may not be removed. */ +static const char version1[] = +"via-rhine.c:v1.08b-LK1.0.0 12/14/2000 Written by Donald Becker\n"; +static const char version2[] = +" http://www.scyld.com/network/via-rhine.html\n"; -/* A few user-configurable values. These may be modified when a driver - module is loaded.*/ +/* 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. */ static int max_interrupt_work = 20; -static int min_pci_latency = 64; +static int min_pci_latency = 32; /* Set the copy breakpoint for the copy-only-tiny-frames scheme. Setting to > 1518 effectively disables this feature. */ @@ -55,7 +64,8 @@ static const int multicast_filter_limit = 32; Making the Tx ring too large decreases the effectiveness of channel bonding and packet priority. There are no ill effects from too-large receive rings. */ -#define TX_RING_SIZE 8 +#define TX_RING_SIZE 16 +#define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ #define RX_RING_SIZE 16 /* Operational parameters that usually are not changed. */ @@ -64,9 +74,15 @@ static const int multicast_filter_limit = 32; #define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/ + +#if !defined(__OPTIMIZE__) +#warning You must compile this file with the correct options! +#warning See the last lines of the source file. +#error You must compile this driver with "-O". +#endif + #include #include -#include #include #include #include @@ -82,15 +98,17 @@ static const int multicast_filter_limit = 32; #include #include -/* This driver was written to use PCI memory space, however some x86 - motherboards only configure I/O space accesses correctly. */ -#if defined(__i386__) && !defined(VIA_USE_MEMORY) -#define VIA_USE_IO -#endif -#if defined(__alpha__) -#define VIA_USE_IO -#endif -#ifdef VIA_USE_IO +/* Condensed bus+endian portability operations. */ +#define virt_to_le32desc(addr) cpu_to_le32(virt_to_bus(addr)) +#define le32desc_to_virt(addr) bus_to_virt(le32_to_cpu(addr)) + +/* This driver was written to use PCI memory space, however most versions + of the Rhine only work correctly with I/O space accesses. */ +#if defined(VIA_USE_MEMORY) +#warning Many adapters using the VIA Rhine chip are not configured to work +#warning with PCI memory space accesses. +#else +#define USE_IO_OPS #undef readb #undef readw #undef readl @@ -105,21 +123,7 @@ static const int multicast_filter_limit = 32; #define writel outl #endif -/* Kernel compatibility defines, some common to David Hind's PCMCIA package. - This is only in the support-all-kernels source code. */ - -#define RUN_AT(x) (jiffies + (x)) - -#if (LINUX_VERSION_CODE >= 0x20100) -static char kernel_version[] = UTS_RELEASE; -#else -#ifndef __alpha__ -#define ioremap vremap -#define iounmap vfree -#endif -#endif -#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115 -MODULE_AUTHOR("Donald Becker "); +MODULE_AUTHOR("Donald Becker "); MODULE_DESCRIPTION("VIA Rhine PCI Fast Ethernet driver"); MODULE_PARM(max_interrupt_work, "i"); MODULE_PARM(min_pci_latency, "i"); @@ -127,28 +131,6 @@ MODULE_PARM(debug, "i"); MODULE_PARM(rx_copybreak, "i"); MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i"); MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i"); -#endif -#if LINUX_VERSION_CODE < 0x20123 -#define test_and_set_bit(val, addr) set_bit(val, addr) -#endif -#if LINUX_VERSION_CODE <= 0x20139 -#define net_device_stats enet_statistics -#else -#define NETSTATS_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20155 || defined(CARDBUS) -/* Grrrr, the PCI code changed, but did not consider CardBus... */ -#include -#define PCI_SUPPORT_VER1 -#else -#define PCI_SUPPORT_VER2 -#endif -#if LINUX_VERSION_CODE < 0x20159 -#define dev_free_skb(skb) dev_kfree_skb(skb, FREE_WRITE); -#else -#define dev_free_skb(skb) dev_kfree_skb(skb); -#endif - /* Theory of Operation @@ -226,13 +208,13 @@ IV. Notes IVb. References Preliminary VT86C100A manual from http://www.via.com.tw/ -http://cesdis.gsfc.nasa.gov/linux/misc/100mbps.html -http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html +http://www.scyld.com/expert/100mbps.html +http://www.scyld.com/expert/NWay.html IVc. Errata The VT86C100A manual is not reliable information. -The chip does not handle unaligned transmit or receive buffers, resulting +The 3043 chip does not handle unaligned transmit or receive buffers, resulting in significant performance degradation for bounce buffer copies on transmit and unaligned IP headers on receive. The chip does not pad to minimum transmit length. @@ -250,6 +232,15 @@ enum pci_flags_bit { PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4, PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3, }; + +#if defined(VIA_USE_MEMORY) +#define RHINE_IOTYPE (PCI_USES_MEM | PCI_USES_MASTER | PCI_ADDR0) +#define RHINEII_IOSIZE 4096 +#else +#define RHINE_IOTYPE (PCI_USES_IO | PCI_USES_MASTER | PCI_ADDR1) +#define RHINEII_IOSIZE 256 +#endif + struct pci_id_info { const char *name; u16 vendor_id, device_id, device_id_mask, flags; @@ -264,34 +255,41 @@ static struct device *via_probe1(int pci_bus, int pci_devfn, static struct pci_id_info pci_tbl[] __initdata = { { "VIA VT86C100A Rhine-II", 0x1106, 0x6100, 0xffff, - PCI_USES_MEM|PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1}, + RHINE_IOTYPE, 128, via_probe1}, + { "VIA VT6102 Rhine-II", 0x1106, 0x3065, 0xffff, + RHINE_IOTYPE, RHINEII_IOSIZE, via_probe1}, { "VIA VT3043 Rhine", 0x1106, 0x3043, 0xffff, - PCI_USES_IO|PCI_USES_MEM|PCI_USES_MASTER, 128, via_probe1}, + RHINE_IOTYPE, 128, via_probe1}, {0,}, /* 0 terminated list. */ }; /* A chip capabilities table, matching the entries in pci_tbl[] above. */ -enum chip_capability_flags {CanHaveMII=1, }; +enum chip_capability_flags { + CanHaveMII=1, HasESIPhy=2, HasDavicomPhy=4, + ReqTxAlign=0x10, HasWOL=0x20, +}; + struct chip_info { int io_size; int flags; } static cap_tbl[] __initdata = { - {128, CanHaveMII, }, - {128, CanHaveMII, }, + {128, CanHaveMII | ReqTxAlign, }, + {128, CanHaveMII | HasWOL, }, + {128, CanHaveMII | ReqTxAlign, }, }; -/* Offsets to the device registers. -*/ +/* Offsets to the device registers. */ enum register_offsets { StationAddr=0x00, RxConfig=0x06, TxConfig=0x07, ChipCmd=0x08, IntrStatus=0x0C, IntrEnable=0x0E, MulticastFilter0=0x10, MulticastFilter1=0x14, RxRingPtr=0x18, TxRingPtr=0x1C, - MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIConfig=0x6E, + MIIPhyAddr=0x6C, MIIStatus=0x6D, PCIBusConfig=0x6E, MIICmd=0x70, MIIRegAddr=0x71, MIIData=0x72, - Config=0x78, RxMissed=0x7C, RxCRCErrs=0x7E, + Config=0x78, ConfigA=0x7A, RxMissed=0x7C, RxCRCErrs=0x7E, + StickyHW=0x83, WOLcrClr=0xA4, WOLcgClr=0xA7, PwrcsrClr=0xAC, }; /* Bits in the interrupt status/mask registers. */ @@ -303,21 +301,18 @@ enum intr_status_bits { IntrRxOverflow=0x0400, IntrRxDropped=0x0800, IntrRxNoBuf=0x1000, IntrTxAborted=0x2000, IntrLinkChange=0x4000, IntrRxWakeUp=0x8000, - IntrNormalSummary=0x0003, IntrAbnormalSummary=0x8260, + IntrNormalSummary=0x0003, IntrAbnormalSummary=0xC260, }; - /* The Rx and Tx buffer descriptors. */ struct rx_desc { - u16 rx_status; - u16 rx_length; + s32 rx_status; u32 desc_length; u32 addr; u32 next_desc; }; struct tx_desc { - u16 tx_status; - u16 tx_own; + s32 tx_status; u32 desc_length; u32 addr; u32 next_desc; @@ -325,9 +320,10 @@ struct tx_desc { /* Bits in *_desc.status */ enum rx_status_bits { - RxDescOwn=0x80000000, RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F}; + RxOK=0x8000, RxWholePkt=0x0300, RxErr=0x008F +}; enum desc_status_bits { - DescOwn=0x8000, DescEndPacket=0x4000, DescIntr=0x1000, + DescOwn=0x80000000, DescEndPacket=0x4000, DescIntr=0x1000, }; /* Bits in ChipCmd. */ @@ -338,6 +334,7 @@ enum chip_cmd_bits { CmdNoTxPoll=0x0800, CmdReset=0x8000, }; +#define PRIV_ALIGN 15 /* Required alignment mask */ struct netdev_private { /* Descriptor rings first for alignment. */ struct rx_desc rx_ring[RX_RING_SIZE]; @@ -349,12 +346,12 @@ struct netdev_private { unsigned char *tx_buf[TX_RING_SIZE]; /* Tx bounce buffers */ unsigned char *tx_bufs; /* Tx bounce buffer region. */ struct device *next_module; /* Link for devices of this type. */ + void *priv_addr; /* Unaligned address for kfree */ struct net_device_stats stats; struct timer_list timer; /* Media monitoring timer. */ unsigned char pci_bus, pci_devfn; /* Frequently used values: keep some adjacent for cache effect. */ - int chip_id; - long in_interrupt; /* Word-long for SMP locks. */ + int chip_id, drv_flags; struct rx_desc *rx_head_desc; unsigned int cur_rx, dirty_rx; /* Producer/consumer ring indices */ unsigned int cur_tx, dirty_tx; @@ -388,6 +385,7 @@ static void set_rx_mode(struct device *dev); static struct net_device_stats *get_stats(struct device *dev); static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd); static int netdev_close(struct device *dev); +static inline void clear_tally_counters(long ioaddr); @@ -432,30 +430,13 @@ static int __init pci_etherdev_probe(struct device *dev, struct pci_id_info pci_ continue; { -#if defined(PCI_SUPPORT_VER2) struct pci_dev *pdev = pci_find_slot(pci_bus, pci_device_fn); -#ifdef VIA_USE_IO +#ifdef USE_IO_OPS pciaddr = pdev->base_address[0]; #else pciaddr = pdev->base_address[1]; #endif irq = pdev->irq; -#else - u32 pci_memaddr; - u8 pci_irq_line; - pcibios_read_config_byte(pci_bus, pci_device_fn, - PCI_INTERRUPT_LINE, &pci_irq_line); -#ifdef VIA_USE_IO - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_0, &pci_memaddr); - pciaddr = pci_memaddr; -#else - pcibios_read_config_dword(pci_bus, pci_device_fn, - PCI_BASE_ADDRESS_1, &pci_memaddr); - pciaddr = pci_memaddr; -#endif - irq = pci_irq_line; -#endif } if (debug > 2) @@ -511,7 +492,7 @@ int __init via_rhine_probe(struct device *dev) { static int did_version = 0; if (!did_version++) - printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); return pci_etherdev_probe(dev, pci_tbl); } #endif @@ -521,6 +502,7 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn, int chip_id, int card_idx) { struct netdev_private *np; + void *priv_mem; int i, option = card_idx < MAX_UNITS ? options[card_idx] : 0; dev = init_etherdev(dev, 0); @@ -528,14 +510,20 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn, printk(KERN_INFO "%s: %s at 0x%lx, ", dev->name, pci_tbl[chip_id].name, ioaddr); - /* Ideally we would be read the EEPROM but access may be locked. */ - for (i = 0; i <6; i++) + /* We would prefer to read the EEPROM but access may be locked. */ + for (i = 0; i < 6; i++) dev->dev_addr[i] = readb(ioaddr + StationAddr + i); for (i = 0; i < 5; i++) printk("%2.2x:", dev->dev_addr[i]); printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq); -#ifdef VIA_USE_IO + /* Allocate driver private memory for descriptor lists. + Check for the very unlikely case of no memory. */ + priv_mem = kmalloc(sizeof(*np) + PRIV_ALIGN, GFP_KERNEL); + if (priv_mem == NULL) + return NULL; + +#ifdef USE_IO_OPS request_region(ioaddr, pci_tbl[chip_id].io_size, dev->name); #endif @@ -546,9 +534,9 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn, dev->irq = irq; /* Make certain the descriptor lists are cache-aligned. */ - np = (void *)(((long)kmalloc(sizeof(*np), GFP_KERNEL) + 31) & ~31); + dev->priv = np = (void *)(((long)priv_mem + PRIV_ALIGN) & ~PRIV_ALIGN); memset(np, 0, sizeof(*np)); - dev->priv = np; + np->priv_addr = priv_mem; np->next_module = root_net_dev; root_net_dev = dev; @@ -556,6 +544,7 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn, np->pci_bus = pci_bus; np->pci_devfn = pci_devfn; np->chip_id = chip_id; + np->drv_flags = cap_tbl[chip_id].flags; if (dev->mem_start) option = dev->mem_start; @@ -582,7 +571,7 @@ static struct device * __init via_probe1(int pci_bus, int pci_devfn, dev->set_multicast_list = &set_rx_mode; dev->do_ioctl = &mii_ioctl; - if (cap_tbl[np->chip_id].flags & CanHaveMII) { + if (np->drv_flags & CanHaveMII) { int phy, phy_idx = 0; np->phys[0] = 1; /* Standard for this chip. */ for (phy = 1; phy < 32 && phy_idx < 4; phy++) { @@ -625,9 +614,23 @@ static int mdio_read(struct device *dev, int phy_id, int regnum) static void mdio_write(struct device *dev, int phy_id, int regnum, int value) { + struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; int boguscnt = 1024; + if (phy_id == np->phys[0]) { + switch (regnum) { + case 0: /* Is user forcing speed/duplex? */ + if (value & 0x9000) /* Autonegotiation. */ + np->duplex_lock = 0; + else + np->full_duplex = (value & 0x0100) ? 1 : 0; + break; + case 4: + np->advertising = value; + break; + } + } /* Wait for a previous command to complete. */ while ((readb(ioaddr + MIICmd) & 0x60) && --boguscnt > 0) ; @@ -649,15 +652,17 @@ static int netdev_open(struct device *dev) /* Reset the chip. */ writew(CmdReset, ioaddr + ChipCmd); - if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) + MOD_INC_USE_COUNT; + + if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev)) { + MOD_DEC_USE_COUNT; return -EAGAIN; + } if (debug > 1) printk(KERN_DEBUG "%s: netdev_open() irq %d.\n", dev->name, dev->irq); - MOD_INC_USE_COUNT; - init_ring(dev); writel(virt_to_bus(np->rx_ring), ioaddr + RxRingPtr); @@ -667,7 +672,7 @@ static int netdev_open(struct device *dev) writeb(dev->dev_addr[i], ioaddr + StationAddr + i); /* Initialize other registers. */ - writew(0x0006, ioaddr + PCIConfig); /* Tune configuration??? */ + writew(0x0006, ioaddr + PCIBusConfig); /* Tune configuration??? */ /* Configure the FIFO thresholds. */ writeb(0x20, ioaddr + TxConfig); /* Initial threshold 32 bytes */ np->tx_thresh = 0x20; @@ -678,7 +683,6 @@ static int netdev_open(struct device *dev) dev->tbusy = 0; dev->interrupt = 0; - np->in_interrupt = 0; set_rx_mode(dev); @@ -696,6 +700,11 @@ static int netdev_open(struct device *dev) writew(np->chip_cmd, ioaddr + ChipCmd); check_duplex(dev); + /* The LED outputs of various MII xcvrs should be configured. */ + /* For NS or Mison phys, turn on bit 1 in register 0x17 */ + /* For ESI phys, turn on bit 7 in register 0x17. */ + mdio_write(dev, np->phys[0], 0x17, mdio_read(dev, np->phys[0], 0x17) | + (np->drv_flags & HasESIPhy) ? 0x0080 : 0x0001); if (debug > 2) printk(KERN_DEBUG "%s: Done netdev_open(), status %4.4x " @@ -705,7 +714,7 @@ static int netdev_open(struct device *dev) /* Set the timer to check for link beat. */ init_timer(&np->timer); - np->timer.expires = RUN_AT(1); + np->timer.expires = jiffies + 2; np->timer.data = (unsigned long)dev; np->timer.function = &netdev_timer; /* timer handler */ add_timer(&np->timer); @@ -718,11 +727,12 @@ static void check_duplex(struct device *dev) struct netdev_private *np = (struct netdev_private *)dev->priv; long ioaddr = dev->base_addr; int mii_reg5 = mdio_read(dev, np->phys[0], 5); + int negotiated = mii_reg5 & np->advertising; int duplex; if (np->duplex_lock || mii_reg5 == 0xffff) return; - duplex = (mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040; + duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040; if (np->full_duplex != duplex) { np->full_duplex = duplex; if (debug) @@ -748,9 +758,14 @@ static void netdev_timer(unsigned long data) printk(KERN_DEBUG "%s: VIA Rhine monitor tick, status %4.4x.\n", dev->name, readw(ioaddr + IntrStatus)); } + if (test_bit(0, (void*)&dev->tbusy) != 0 + && np->cur_tx - np->dirty_tx > 1 + && jiffies - dev->trans_start > TX_TIMEOUT) + tx_timeout(dev); + check_duplex(dev); - np->timer.expires = RUN_AT(next_tick); + np->timer.expires = jiffies + next_tick; add_timer(&np->timer); } @@ -764,15 +779,15 @@ static void tx_timeout(struct device *dev) dev->name, readw(ioaddr + IntrStatus), mdio_read(dev, np->phys[0], 1)); - /* Perhaps we should reinitialize the hardware here. */ - dev->if_port = 0; - /* Stop and restart the chip's Tx processes . */ + /* Perhaps we should reinitialize the hardware here. */ + dev->if_port = 0; + /* Stop and restart the chip's Tx processes . */ - /* Trigger an immediate transmit demand. */ + /* Trigger an immediate transmit demand. */ - dev->trans_start = jiffies; - np->stats.tx_errors++; - return; + dev->trans_start = jiffies; + np->stats.tx_errors++; + return; } @@ -791,35 +806,33 @@ static void init_ring(struct device *dev) for (i = 0; i < RX_RING_SIZE; i++) { np->rx_ring[i].rx_status = 0; - np->rx_ring[i].rx_length = 0; - np->rx_ring[i].desc_length = np->rx_buf_sz; - np->rx_ring[i].next_desc = virt_to_bus(&np->rx_ring[i+1]); + np->rx_ring[i].desc_length = cpu_to_le32(np->rx_buf_sz); + np->rx_ring[i].next_desc = virt_to_le32desc(&np->rx_ring[i+1]); np->rx_skbuff[i] = 0; } /* Mark the last entry as wrapping the ring. */ - np->rx_ring[i-1].next_desc = virt_to_bus(&np->rx_ring[0]); + np->rx_ring[i-1].next_desc = virt_to_le32desc(&np->rx_ring[0]); - /* Fill in the Rx buffers. */ + /* Fill in the Rx buffers. Handle allocation failure gracefully. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz); np->rx_skbuff[i] = skb; if (skb == NULL) break; skb->dev = dev; /* Mark as being used by this device. */ - np->rx_ring[i].addr = virt_to_bus(skb->tail); - np->rx_ring[i].rx_status = 0; - np->rx_ring[i].rx_length = DescOwn; + np->rx_ring[i].addr = virt_to_le32desc(skb->tail); + np->rx_ring[i].rx_status = cpu_to_le32(DescOwn); } np->dirty_rx = (unsigned int)(i - RX_RING_SIZE); for (i = 0; i < TX_RING_SIZE; i++) { np->tx_skbuff[i] = 0; - np->tx_ring[i].tx_own = 0; - np->tx_ring[i].desc_length = 0x00e08000; - np->tx_ring[i].next_desc = virt_to_bus(&np->tx_ring[i+1]); + np->tx_ring[i].tx_status = 0; + np->tx_ring[i].desc_length = cpu_to_le32(0x00e08000); + np->tx_ring[i].next_desc = virt_to_le32desc(&np->tx_ring[i+1]); np->tx_buf[i] = kmalloc(PKT_BUF_SZ, GFP_KERNEL); } - np->tx_ring[i-1].next_desc = virt_to_bus(&np->tx_ring[0]); + np->tx_ring[i-1].next_desc = virt_to_le32desc(&np->tx_ring[0]); return; } @@ -832,41 +845,45 @@ static int start_tx(struct sk_buff *skb, struct device *dev) /* Block a timer-based transmit from overlapping. This could better be done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { - if (jiffies - dev->trans_start < TX_TIMEOUT) - return 1; - tx_timeout(dev); + /* This watchdog code is redundant with the media monitor timer. */ + if (jiffies - dev->trans_start > TX_TIMEOUT) + tx_timeout(dev); return 1; } - /* Caution: the write order is important here, set the field - with the "ownership" bits last. */ + /* Explicitly flush packet data cache lines here. */ + + /* Caution: the write order is important here, set the descriptor word + with the "ownership" bit last. No SMP locking is needed if the + cur_tx is incremented after the descriptor is consistent. */ /* Calculate the next Tx descriptor entry. */ entry = np->cur_tx % TX_RING_SIZE; np->tx_skbuff[entry] = skb; - if ((long)skb->data & 3) { /* Must use alignment buffer. */ + if ((np->drv_flags & ReqTxAlign) && ((long)skb->data & 3)) { + /* Must use alignment buffer. */ if (np->tx_buf[entry] == NULL && (np->tx_buf[entry] = kmalloc(PKT_BUF_SZ, GFP_KERNEL)) == NULL) return 1; memcpy(np->tx_buf[entry], skb->data, skb->len); - np->tx_ring[entry].addr = virt_to_bus(np->tx_buf[entry]); + np->tx_ring[entry].addr = virt_to_le32desc(np->tx_buf[entry]); } else - np->tx_ring[entry].addr = virt_to_bus(skb->data); + np->tx_ring[entry].addr = virt_to_le32desc(skb->data); - np->tx_ring[entry].desc_length = 0x00E08000 | - (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN); - np->tx_ring[entry].tx_own = DescOwn; + np->tx_ring[entry].desc_length = + cpu_to_le32(0x00E08000 | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); + np->tx_ring[entry].tx_status = cpu_to_le32(DescOwn); np->cur_tx++; - /* Non-x86 Todo: explicitly flush cache lines here. */ + /* Explicitly flush descriptor cache lines here. */ /* Wake the potentially-idle transmit channel. */ writew(CmdTxDemand | np->chip_cmd, dev->base_addr + ChipCmd); - if (np->cur_tx - np->dirty_tx < TX_RING_SIZE - 1) + if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 1) clear_bit(0, (void*)&dev->tbusy); /* Typical path */ else np->tx_full = 1; @@ -884,26 +901,9 @@ static int start_tx(struct sk_buff *skb, struct device *dev) static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) { struct device *dev = (struct device *)dev_instance; - struct netdev_private *np; - long ioaddr, boguscnt = max_interrupt_work; - - ioaddr = dev->base_addr; - np = (struct netdev_private *)dev->priv; -#if defined(__i386__) - /* A lock to prevent simultaneous entry bug on Intel SMP machines. */ - if (test_and_set_bit(0, (void*)&dev->interrupt)) { - printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n", - dev->name); - dev->interrupt = 0; /* Avoid halting machine. */ - return; - } -#else - if (dev->interrupt) { - printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name); - return; - } - dev->interrupt = 1; -#endif + struct netdev_private *np = (void *)dev->priv; + long ioaddr = dev->base_addr; + int boguscnt = max_interrupt_work; do { u32 intr_status = readw(ioaddr + IntrStatus); @@ -924,10 +924,9 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) { int entry = np->dirty_tx % TX_RING_SIZE; - int txstatus; - if (np->tx_ring[entry].tx_own) + int txstatus = le32_to_cpu(np->tx_ring[entry].tx_status); + if (txstatus & DescOwn) break; - txstatus = np->tx_ring[entry].tx_status; if (debug > 6) printk(KERN_DEBUG " Tx scavenge %d status %4.4x.\n", entry, txstatus); @@ -951,16 +950,16 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) #endif np->stats.collisions += (txstatus >> 3) & 15; #if defined(NETSTATS_VER2) - np->stats.tx_bytes += np->tx_ring[entry].desc_length & 0x7ff; + np->stats.tx_bytes += np->tx_skbuff[entry]->len; #endif np->stats.tx_packets++; } /* Free the original skb. */ - dev_free_skb(np->tx_skbuff[entry]); + dev_kfree_skb(np->tx_skbuff[entry]); np->tx_skbuff[entry] = 0; } if (np->tx_full && dev->tbusy - && np->cur_tx - np->dirty_tx < TX_RING_SIZE - 4) { + && np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) { /* The ring is no longer full, clear tbusy. */ np->tx_full = 0; clear_bit(0, (void*)&dev->tbusy); @@ -984,11 +983,6 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs) printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n", dev->name, readw(ioaddr + IntrStatus)); -#if defined(__i386__) - clear_bit(0, (void*)&dev->interrupt); -#else - dev->interrupt = 0; -#endif return; } @@ -1001,15 +995,15 @@ static int netdev_rx(struct device *dev) int boguscnt = np->dirty_rx + RX_RING_SIZE - np->cur_rx; if (debug > 4) { - printk(KERN_DEBUG " In netdev_rx(), entry %d status %4.4x.\n", - entry, np->rx_head_desc->rx_length); + printk(KERN_DEBUG " In netdev_rx(), entry %d status %8.8x.\n", + entry, np->rx_head_desc->rx_status); } /* If EOP is set on the next entry, it's a new packet. Send it up. */ - while ( ! (np->rx_head_desc->rx_length & DescOwn)) { + while ( ! (np->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) { struct rx_desc *desc = np->rx_head_desc; - int data_size = desc->rx_length; - u16 desc_status = desc->rx_status; + u32 desc_status = le32_to_cpu(desc->rx_status); + int data_size = desc_status >> 16; if (debug > 4) printk(KERN_DEBUG " netdev_rx() status is %4.4x.\n", @@ -1039,7 +1033,7 @@ static int netdev_rx(struct device *dev) } else { struct sk_buff *skb; /* Length should omit the CRC */ - u16 pkt_len = data_size - 4; + int pkt_len = data_size - 4; /* Check if the packet is long enough to accept without copying to a minimally-sized skbuff. */ @@ -1047,21 +1041,23 @@ static int netdev_rx(struct device *dev) && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) { skb->dev = dev; skb_reserve(skb, 2); /* 16 byte align the IP header */ -#if ! defined(__alpha__) || USE_IP_COPYSUM /* Avoid misaligned on Alpha */ - eth_copy_and_sum(skb, bus_to_virt(desc->addr), - pkt_len, 0); +#if HAS_IP_COPYSUM /* Call copy + cksum if available. */ + eth_copy_and_sum(skb, np->rx_skbuff[entry]->tail, pkt_len, 0); skb_put(skb, pkt_len); #else - memcpy(skb_put(skb,pkt_len), bus_to_virt(desc->addr), pkt_len); + memcpy(skb_put(skb, pkt_len), np->rx_skbuff[entry]->tail, + pkt_len); #endif } else { skb_put(skb = np->rx_skbuff[entry], pkt_len); np->rx_skbuff[entry] = NULL; } skb->protocol = eth_type_trans(skb, dev); - np->stats.rx_bytes+=skb->len; netif_rx(skb); dev->last_rx = jiffies; +#if defined(NETSTATS_VER2) + np->stats.rx_bytes += skb->len; +#endif np->stats.rx_packets++; } entry = (++np->cur_rx) % RX_RING_SIZE; @@ -1078,10 +1074,9 @@ static int netdev_rx(struct device *dev) if (skb == NULL) break; /* Better luck next round. */ skb->dev = dev; /* Mark as being used by this device. */ - np->rx_ring[entry].addr = virt_to_bus(skb->tail); + np->rx_ring[entry].addr = virt_to_le32desc(skb->tail); } - np->rx_ring[entry].rx_status = 0; - np->rx_ring[entry].rx_length = DescOwn; + np->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); } /* Pre-emptively restart Rx engine. */ @@ -1095,10 +1090,11 @@ static void netdev_error(struct device *dev, int intr_status) long ioaddr = dev->base_addr; if (intr_status & (IntrMIIChange | IntrLinkChange)) { - if (readb(ioaddr + MIIStatus) & 0x02) + if (readb(ioaddr + MIIStatus) & 0x02) { /* Link failed, restart autonegotiation. */ - mdio_write(dev, np->phys[0], 0, 0x3300); - else + if (np->drv_flags & HasDavicomPhy) + mdio_write(dev, np->phys[0], 0, 0x3300); + } else check_duplex(dev); if (debug) printk(KERN_ERR "%s: MII status changed: Autonegotiation " @@ -1109,7 +1105,7 @@ static void netdev_error(struct device *dev, int intr_status) if (intr_status & IntrStatsMax) { np->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); np->stats.rx_missed_errors += readw(ioaddr + RxMissed); - writel(0, RxMissed); + clear_tally_counters(ioaddr); } if (intr_status & IntrTxAbort) { /* Stats counted in Tx-done handler, just restart Tx. */ @@ -1122,7 +1118,8 @@ static void netdev_error(struct device *dev, int intr_status) printk(KERN_INFO "%s: Transmitter underrun, increasing Tx " "threshold setting to %2.2x.\n", dev->name, np->tx_thresh); } - if ((intr_status & ~(IntrLinkChange|IntrStatsMax|IntrTxAbort)) && debug) { + if ((intr_status & ~(IntrLinkChange | IntrStatsMax | + IntrTxAbort|IntrTxAborted)) && debug) { printk(KERN_ERR "%s: Something Wicked happened! %4.4x.\n", dev->name, intr_status); /* Recovery for other fault sources not known. */ @@ -1140,28 +1137,39 @@ static struct enet_statistics *get_stats(struct device *dev) non-critical. */ np->stats.rx_crc_errors += readw(ioaddr + RxCRCErrs); np->stats.rx_missed_errors += readw(ioaddr + RxMissed); - writel(0, RxMissed); + clear_tally_counters(ioaddr); return &np->stats; } +/* Clears the "tally counters" for CRC errors and missed frames(?). + It has been reported that some chips need a write of 0 to clear + these, for others the counters are set to 1 when written to and + instead cleared when read. So we clear them both ways ... */ +static inline void clear_tally_counters(const long ioaddr) +{ + writel(0, ioaddr + RxMissed); + readw(ioaddr + RxCRCErrs); + readw(ioaddr + RxMissed); +} + /* The big-endian AUTODIN II ethernet CRC calculation. N.B. Do not use for bulk data, use a table-based routine instead. This is common code and should be moved to net/core/crc.c */ static unsigned const ethernet_polynomial = 0x04c11db7U; static inline u32 ether_crc(int length, unsigned char *data) { - int crc = -1; + int crc = -1; - while(--length >= 0) { + while(--length >= 0) { unsigned char current_octet = *data++; int bit; for (bit = 0; bit < 8; bit++, current_octet >>= 1) { crc = (crc << 1) ^ ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0); } - } - return crc; + } + return crc; } static void set_rx_mode(struct device *dev) @@ -1178,6 +1186,8 @@ static void set_rx_mode(struct device *dev) } else if ((dev->mc_count > multicast_filter_limit) || (dev->flags & IFF_ALLMULTI)) { /* Too many to match, or accept all multicasts. */ + writel(0xffffffff, ioaddr + MulticastFilter0); + writel(0xffffffff, ioaddr + MulticastFilter1); rx_mode = 0x0C; } else { struct dev_mc_list *mclist; @@ -1190,7 +1200,7 @@ static void set_rx_mode(struct device *dev) } writel(mc_filter[0], ioaddr + MulticastFilter0); writel(mc_filter[1], ioaddr + MulticastFilter1); - rx_mode = 0x08; + rx_mode = 0x0C; } writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig); } @@ -1207,7 +1217,7 @@ static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd) data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f); return 0; case SIOCDEVPRIVATE+2: /* Write the specified MII register */ - if (!suser()) + if (!capable(CAP_NET_ADMIN)) return -EPERM; mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]); return 0; @@ -1229,32 +1239,39 @@ static int netdev_close(struct device *dev) printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n", dev->name, readw(ioaddr + ChipCmd)); + del_timer(&np->timer); + + /* Switch to loopback mode to avoid hardware races. */ + writeb(np->tx_thresh | 0x01, ioaddr + TxConfig); + /* Disable interrupts by clearing the interrupt mask. */ writew(0x0000, ioaddr + IntrEnable); /* Stop the chip's Tx and Rx processes. */ writew(CmdStop, ioaddr + ChipCmd); - del_timer(&np->timer); - free_irq(dev->irq, dev); /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { - np->rx_ring[i].rx_length = 0; + np->rx_ring[i].rx_status = 0; np->rx_ring[i].addr = 0xBADF00D0; /* An invalid address. */ if (np->rx_skbuff[i]) { #if LINUX_VERSION_CODE < 0x20100 np->rx_skbuff[i]->free = 1; #endif - dev_free_skb(np->rx_skbuff[i]); + dev_kfree_skb(np->rx_skbuff[i]); } np->rx_skbuff[i] = 0; } for (i = 0; i < TX_RING_SIZE; i++) { if (np->tx_skbuff[i]) - dev_free_skb(np->tx_skbuff[i]); + dev_kfree_skb(np->tx_skbuff[i]); np->tx_skbuff[i] = 0; + if (np->tx_buf[i]) { + kfree(np->tx_buf[i]); + np->tx_buf[i] = 0; + } } MOD_DEC_USE_COUNT; @@ -1267,37 +1284,28 @@ static int netdev_close(struct device *dev) int init_module(void) { if (debug) /* Emit version even if no cards detected. */ - printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB); -#ifdef CARDBUS - register_driver(ðerdev_ops); - return 0; -#else + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); return pci_etherdev_probe(NULL, pci_tbl); -#endif } void cleanup_module(void) { - -#ifdef CARDBUS - unregister_driver(ðerdev_ops); -#endif + struct device *next_dev; /* No need to check MOD_IN_USE, as sys_delete_module() checks. */ while (root_net_dev) { - struct netdev_private *np = - (struct netdev_private *)(root_net_dev->priv); + struct netdev_private *np = (void *)(root_net_dev->priv); unregister_netdev(root_net_dev); -#ifdef VIA_USE_IO +#ifdef USE_IO_OPS release_region(root_net_dev->base_addr, pci_tbl[np->chip_id].io_size); #else iounmap((char *)(root_net_dev->base_addr)); #endif + next_dev = np->next_module; + if (np->priv_addr) + kfree(np->priv_addr); kfree(root_net_dev); - root_net_dev = np->next_module; -#if 0 - kfree(np); /* Assumption: no struct realignment. */ -#endif + root_net_dev = next_dev; } } diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 951207e09853..6dc1b7070723 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2924,9 +2924,7 @@ cleanup_dasd (void) int init_module ( void ) { - int rc=0; return dasd_init(); - return rc; } void diff --git a/drivers/s390/block/dasd.h b/drivers/s390/block/dasd.h index bb063f304aff..3a0313007f88 100644 --- a/drivers/s390/block/dasd.h +++ b/drivers/s390/block/dasd.h @@ -7,3 +7,8 @@ void dasd_free_request(ccw_req_t *); int (*genhd_dasd_name)(char*,int,int,struct gendisk*); int dasd_oper_handler ( int irq, devreg_t *devreg ); +dasd_era_t dasd_3370_erp_examine (ccw_req_t * cqr, devstat_t * stat); +dasd_era_t dasd_3990_erp_examine (ccw_req_t * cqr, devstat_t * stat); +dasd_era_t dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat); +dasd_era_t dasd_9343_erp_examine (ccw_req_t * cqr, devstat_t * stat); + diff --git a/drivers/s390/block/dasd_3370_erp.c b/drivers/s390/block/dasd_3370_erp.c index 75af18b39c34..1069308746d9 100644 --- a/drivers/s390/block/dasd_3370_erp.c +++ b/drivers/s390/block/dasd_3370_erp.c @@ -5,6 +5,7 @@ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 */ +#include #include #include diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 963260f3f9c9..a116db771ba4 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c @@ -6,6 +6,7 @@ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 */ +#include #include #include diff --git a/drivers/s390/block/dasd_9336_erp.c b/drivers/s390/block/dasd_9336_erp.c index 2c04ca437681..6cf40a0d2798 100644 --- a/drivers/s390/block/dasd_9336_erp.c +++ b/drivers/s390/block/dasd_9336_erp.c @@ -5,6 +5,7 @@ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 */ +#include #include #include @@ -32,8 +33,6 @@ dasd_era_t dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat) { - char *sense = stat->ii.sense.data; - /* check for successful execution first */ if (stat->cstat == 0x00 && stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) diff --git a/drivers/s390/block/dasd_9343_erp.c b/drivers/s390/block/dasd_9343_erp.c index 5f7d6c5ede77..aa0d8f10e4e0 100644 --- a/drivers/s390/block/dasd_9343_erp.c +++ b/drivers/s390/block/dasd_9343_erp.c @@ -5,6 +5,7 @@ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 */ +#include #include #include diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index cc472471e950..1d6adbe01b63 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -74,6 +74,7 @@ dasd_eckd_private_t { eckd_count_t count_area; } dasd_eckd_private_t; +#ifdef CONFIG_DASD_DYNAMIC static devreg_t dasd_eckd_known_devices[] = { { @@ -92,6 +93,7 @@ devreg_t dasd_eckd_known_devices[] = { oper_func: dasd_oper_handler } }; +#endif static inline unsigned int round_up_multiple (unsigned int no, unsigned int mult) @@ -923,7 +925,9 @@ dasd_discipline_t dasd_eckd_discipline = { int dasd_eckd_init( void ) { int rc = 0; +#ifdef CONFIG_DASD_DYNAMIC int i; +#endif printk ( KERN_INFO PRINTK_HEADER "%s discipline initializing\n", dasd_eckd_discipline.name); ASCEBC(dasd_eckd_discipline.ebcname,4); @@ -944,8 +948,9 @@ dasd_eckd_init( void ) { void dasd_eckd_cleanup( void ) { - int rc = 0; +#ifdef CONFIG_DASD_DYNAMIC int i; +#endif printk ( KERN_INFO PRINTK_HEADER "%s discipline cleaning up\n", dasd_eckd_discipline.name); #ifdef CONFIG_DASD_DYNAMIC @@ -960,7 +965,7 @@ dasd_eckd_cleanup( void ) { } #endif /* CONFIG_DASD_DYNAMIC */ dasd_discipline_deq(&dasd_eckd_discipline); - return rc; + return; } /* diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index fd713ef87737..36c505a185ca 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -282,5 +282,6 @@ typedef struct dasd_eckd_confdata_t { } __attribute__ ((packed)) dasd_eckd_confdata_t; int dasd_eckd_init( void ); +void dasd_eckd_cleanup( void ); #endif /* DASD_ECKD_H */ diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index c91963c42dfe..eeec40c2e2fd 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c @@ -181,9 +181,7 @@ dasd_fba_fill_geometry(struct dasd_device_t *device, struct hd_geometry *geo) int rc = 0; unsigned long sectors = device->sizes.blocks << device->sizes.s2b_shift; unsigned long tracks = sectors >> 6; - unsigned long trk_rem = sectors & ((1<<6)-1); unsigned long cyls = tracks >> 4; - unsigned long cyls_rem = tracks & ((1<<4)-1); switch(device->sizes.bp_block) { case 512: @@ -371,7 +369,9 @@ dasd_discipline_t dasd_fba_discipline = { int dasd_fba_init( void ) { int rc = 0; +#ifdef CONFIG_DASD_DYNAMIC int i; +#endif printk ( KERN_INFO PRINTK_HEADER "%s discipline initializing\n", dasd_fba_discipline.name); ASCEBC(dasd_fba_discipline.ebcname,4); @@ -392,8 +392,9 @@ dasd_fba_init( void ) { void dasd_fba_cleanup( void ) { - int rc = 0; +#ifdef CONFIG_DASD_DYNAMIC int i; +#endif printk ( KERN_INFO PRINTK_HEADER "%s discipline cleaning up\n", dasd_fba_discipline.name); #ifdef CONFIG_DASD_DYNAMIC @@ -408,7 +409,7 @@ dasd_fba_cleanup( void ) { } #endif /* CONFIG_DASD_DYNAMIC */ dasd_discipline_deq(&dasd_fba_discipline); - return rc; + return; } /* * Overrides for Emacs so that we follow Linus's tabbing style. diff --git a/drivers/s390/block/dasd_fba.h b/drivers/s390/block/dasd_fba.h index 1891592b584b..0e151534a2fb 100644 --- a/drivers/s390/block/dasd_fba.h +++ b/drivers/s390/block/dasd_fba.h @@ -66,5 +66,6 @@ struct dasd_fba_characteristics_t { } __attribute__ ((packed)) dasd_fba_characteristics_t; int dasd_fba_init( void ); +void dasd_fba_cleanup( void ); #endif /* DASD_FBA_H */ diff --git a/drivers/s390/block/mdisk.c b/drivers/s390/block/mdisk.c index df05be8883c2..565934c1dff4 100644 --- a/drivers/s390/block/mdisk.c +++ b/drivers/s390/block/mdisk.c @@ -104,6 +104,122 @@ struct { long blksize[MDISK_DEVS]; } mdisk_setup_data; +/* + * The 'low level' IO function + */ + +static __inline__ int +dia250(void* iob,int cmd) +{ + int rc; + + iob = (void*) virt_to_phys(iob); + + asm volatile (" lr 2,%1\n" + " lr 3,%2\n" + " .long 0x83230250\n" + " lr %0,3" + : "=d" (rc) + : "d" (iob) , "d" (cmd) + : "2", "3" ); + return rc; +} + +/* + * The device characteristics function + */ + +static __inline__ int +dia210(void* devchar) +{ + int rc; + + devchar = (void*) virt_to_phys(devchar); + + asm volatile (" lr 2,%1\n" + " .long 0x83200210\n" + " ipm %0\n" + " srl %0,28" + : "=d" (rc) + : "d" (devchar) + : "2" ); + return rc; +} + + +/* + * release of minidisk device + */ + +static __inline__ int +mdisk_term_io(mdisk_Dev *dev) +{ + mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; + + memset(iob,0,sizeof(mdisk_init_io_t)); + + iob->dev_nr = dev->vdev; + + return dia250(iob,TERM_BIO); +} + + +/* + * Init of minidisk device + */ + +static __inline__ int +mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size) +{ + mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; + int rc; + + memset(iob,0,sizeof(mdisk_init_io_t)); + + iob->dev_nr = dev->vdev; + iob->block_size = blocksize; + iob->offset = offset; + iob->start_block= 0; + iob->end_block = size; + + rc = dia250(iob,INIT_BIO); + + /* + * clear for following io once + */ + + memset(iob,0,sizeof(mdisk_rw_io_t)); + + return rc; +} + + +/* + * setup and start of minidisk io request + */ + +static __inline__ int +mdisk_rw_io_clustered (mdisk_Dev *dev, + mdisk_bio_t* bio_array, + int length, + int req, + int sync) +{ + int rc; + mdisk_rw_io_t *iob = dev->iob; + + iob->dev_nr = dev->vdev; + iob->key = 0; + iob->flags = sync; + + iob->block_count = length; + iob->interrupt_params = req; + iob->bio_list = virt_to_phys(bio_array); + + rc = dia250(iob,RW_BIO); + return rc; +} + /* * Parameter parsing function, called from init/main.c * vdev : virtual device number @@ -117,7 +233,7 @@ __initfunc(void mdisk_setup(char *str,int *ints)) { char *cur = str; int vdev, size, offset=0,blksize; - static i = 0; +static int i = 0; if (!i) memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data)); @@ -280,48 +396,7 @@ static struct file_operations mdisk_fops = { NULL, /* mdisk_lock */ }; -/* - * The 'low level' IO function - */ - - -static __inline__ int -dia250(void* iob,int cmd) -{ - int rc; - - iob = (void*) virt_to_phys(iob); - - asm volatile (" lr 2,%1\n" - " lr 3,%2\n" - " .long 0x83230250\n" - " lr %0,3" - : "=d" (rc) - : "d" (iob) , "d" (cmd) - : "2", "3" ); - return rc; -} - -/* - * The device characteristics function - */ - -static __inline__ int -dia210(void* devchar) -{ - int rc; - - devchar = (void*) virt_to_phys(devchar); - asm volatile (" lr 2,%1\n" - " .long 0x83200210\n" - " ipm %0\n" - " srl %0,28" - : "=d" (rc) - : "d" (devchar) - : "2" ); - return rc; -} /* * read the label of a minidisk and extract its characteristics */ @@ -396,80 +471,6 @@ mdisk_read_label (mdisk_Dev *dev, int i) } - -/* - * Init of minidisk device - */ - -static __inline__ int -mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size) -{ - mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; - int rc; - - memset(iob,0,sizeof(mdisk_init_io_t)); - - iob->dev_nr = dev->vdev; - iob->block_size = blocksize; - iob->offset = offset; - iob->start_block= 0; - iob->end_block = size; - - rc = dia250(iob,INIT_BIO); - - /* - * clear for following io once - */ - - memset(iob,0,sizeof(mdisk_rw_io_t)); - - return rc; -} - -/* - * release of minidisk device - */ - -static __inline__ int -mdisk_term_io(mdisk_Dev *dev) -{ - mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; - - memset(iob,0,sizeof(mdisk_init_io_t)); - - iob->dev_nr = dev->vdev; - - return dia250(iob,TERM_BIO); -} - -/* - * setup and start of minidisk io request - */ - -static __inline__ int -mdisk_rw_io_clustered (mdisk_Dev *dev, - mdisk_bio_t* bio_array, - int length, - int req, - int sync) -{ - int rc; - mdisk_rw_io_t *iob = dev->iob; - - iob->dev_nr = dev->vdev; - iob->key = 0; - iob->flags = sync; - - iob->block_count = length; - iob->interrupt_params = req; - iob->bio_list = virt_to_phys(bio_array); - - rc = dia250(iob,RW_BIO); - return rc; -} - - - /* * this handles a clustered request in success case * all buffers are detach and marked uptodate to the kernel @@ -640,11 +641,8 @@ void mdisk_request(void) */ void do_mdisk_interrupt(struct pt_regs *regs, __u16 code) { - u16 code; mdisk_Dev *dev; - code = S390_lowcore.cpu_addr; - if ((code >> 8) != 0x03) { printk("mnd: wrong sub-interruption code %d",code>>8); return; diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index db67ff042284..b17785525333 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -20,9 +20,19 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Tested with Linux 1.2.13, ..., 2.2.16, ..., 2.4.0-test4 * + * Tested with Linux 1.2.13, ..., 2.2.16, ..., 2.4.0-test10 * * * * $Log: gdth.c,v $ + * Revision 1.45 2000/11/16 12:02:24 achim + * Changes for kernel 2.4 + * + * Revision 1.44 2000/10/11 08:44:10 achim + * Clustering changes: New flag media_changed added + * + * Revision 1.43 2000/09/20 12:59:01 achim + * DPMEM remap functions for all PCI controller types implemented + * Small changes for ia64 platform + * * Revision 1.42 2000/07/20 09:04:50 achim * Small changes for kernel 2.4 * @@ -180,7 +190,7 @@ * Initial revision * ************************************************************************/ -#ident "$Id: gdth.c,v 1.42 2000/07/20 09:04:50 achim Exp $" +#ident "$Id: gdth.c,v 1.45 2000/11/16 12:02:24 achim Exp $" /* All GDT Disk Array Controllers are fully supported by this driver. * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the @@ -1111,8 +1121,51 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } + /* check and reset interface area */ dp6_ptr = (gdt6_dpram_str *)ha->brd; - /* reset interface area */ + gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); + if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) { + printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", + pcistr->dpmem); + found = FALSE; + for (i = 0xC8000; i < 0xE8000; i += 0x4000) { + gdth_munmap(ha->brd); + ha->brd = gdth_mmap(i, sizeof(ushort)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + if (gdth_readw(ha->brd) != 0xffff) { + TRACE2(("init_pci_old() address 0x%x busy\n", i)); + continue; + } + gdth_munmap(ha->brd); +#if LINUX_VERSION_CODE >= 0x2015C + pci_write_config_dword(pcistr->pdev, + PCI_BASE_ADDRESS_0, i); +#else + pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, + PCI_BASE_ADDRESS_0, i); +#endif + ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + dp6_ptr = (gdt6_dpram_str *)ha->brd; + gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); + if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) { + printk("GDT-PCI: Use free address at 0x%x\n", i); + found = TRUE; + break; + } + } + if (!found) { + printk("GDT-PCI: No free address found!\n"); + gdth_munmap(ha->brd); + return 0; + } + } memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u)); if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); @@ -1181,8 +1234,51 @@ GDTH_INITFUNC(static int, gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha)) gdth_munmap(ha->brd); return 0; } + /* check and reset interface area */ dp6c_ptr = (gdt6c_dpram_str *)ha->brd; - /* reset interface area */ + gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); + if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) { + printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", + pcistr->dpmem); + found = FALSE; + for (i = 0xC8000; i < 0xE8000; i += 0x4000) { + gdth_munmap(ha->brd); + ha->brd = gdth_mmap(i, sizeof(ushort)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + if (gdth_readw(ha->brd) != 0xffff) { + TRACE2(("init_pci_plx() address 0x%x busy\n", i)); + continue; + } + gdth_munmap(ha->brd); +#if LINUX_VERSION_CODE >= 0x2015C + pci_write_config_dword(pcistr->pdev, + PCI_BASE_ADDRESS_2, i); +#else + pcibios_write_config_dword(pcistr->bus, pcistr->device_fn, + PCI_BASE_ADDRESS_2, i); +#endif + ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); + if (ha->brd == NULL) { + printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); + return 0; + } + dp6c_ptr = (gdt6c_dpram_str *)ha->brd; + gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); + if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) { + printk("GDT-PCI: Use free address at 0x%x\n", i); + found = TRUE; + break; + } + } + if (!found) { + printk("GDT-PCI: No free address found!\n"); + gdth_munmap(ha->brd); + return 0; + } + } memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u)); if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); @@ -1966,7 +2062,6 @@ GDTH_INITFUNC(static int, gdth_search_drives(int hanum)) TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); /* set/get features raw service (scatter/gather) */ - ha->raw_feat = 0; if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER, 0,0)) { TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n")); @@ -2061,18 +2156,14 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n", hdrive,ha->info)); ha->hdr[hdrive].cluster_type = (unchar)ha->info; - } else { - ha->hdr[hdrive].cluster_type = 0; - } + } /* R/W attributes */ if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) { TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n", hdrive,ha->info)); ha->hdr[hdrive].rw_attribs = (unchar)ha->info; - } else { - ha->hdr[hdrive].rw_attribs = 0; - } + } return 1; } @@ -2264,10 +2355,14 @@ static void gdth_next(int hanum) TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n", nscp->cmnd[0], b, t, nscp->lun)); nscp->result = DID_BAD_TARGET << 16; - GDTH_UNLOCK_HA(ha,flags); - /* io_request_lock already active ! */ - nscp->scsi_done(nscp); - GDTH_LOCK_HA(ha,flags); + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; + else { + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ + nscp->scsi_done(nscp); + GDTH_LOCK_HA(ha,flags); + } } else { switch (nscp->cmnd[0]) { case TEST_UNIT_READY: @@ -2280,7 +2375,24 @@ static void gdth_next(int hanum) TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0], nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); - if (gdth_internal_cache_cmd(hanum,nscp)) { + if (ha->hdr[t].media_changed && nscp->cmnd[0] != INQUIRY) { + /* return UNIT_ATTENTION */ + TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n", + nscp->cmnd[0], t)); + ha->hdr[t].media_changed = FALSE; + memset((char*)nscp->sense_buffer,0,16); + nscp->sense_buffer[0] = 0x70; + nscp->sense_buffer[2] = UNIT_ATTENTION; + nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; + else { + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ + nscp->scsi_done(nscp); + GDTH_LOCK_HA(ha,flags); + } + } else if (gdth_internal_cache_cmd(hanum,nscp)) { GDTH_UNLOCK_HA(ha,flags); /* io_request_lock already active ! */ nscp->scsi_done(nscp); @@ -2325,7 +2437,24 @@ static void gdth_next(int hanum) case WRITE_6: case READ_10: case WRITE_10: - if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + if (ha->hdr[t].media_changed) { + /* return UNIT_ATTENTION */ + TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n", + nscp->cmnd[0], t)); + ha->hdr[t].media_changed = FALSE; + memset((char*)nscp->sense_buffer,0,16); + nscp->sense_buffer[0] = 0x70; + nscp->sense_buffer[2] = UNIT_ATTENTION; + nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; + else { + GDTH_UNLOCK_HA(ha,flags); + /* io_request_lock already active ! */ + nscp->scsi_done(nscp); + GDTH_LOCK_HA(ha,flags); + } + } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; break; @@ -2471,6 +2600,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0])); break; } + scp->result = DID_OK << 16; scp->sense_buffer[0] = 0; @@ -2487,7 +2617,8 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) register gdth_ha_str *ha; register gdth_cmd_str *cmdp; struct scatterlist *sl; - ushort i; + ushort i, cnt; + ulong32 no; int cmd_index, read_write; ha = HADATA(gdth_ctr_tab[hanum]); @@ -2543,11 +2674,13 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) if (read_write) { if (scp->cmd_len != 6) { - cmdp->u.cache.BlockNo = ntohl(*(ulong32*)&scp->cmnd[2]); - cmdp->u.cache.BlockCnt= (ulong32)ntohs(*(ushort*)&scp->cmnd[7]); + memcpy(&no, &scp->cmnd[2], sizeof(ulong32)); + cmdp->u.cache.BlockNo = ntohl(no); + memcpy(&cnt, &scp->cmnd[7], sizeof(ushort)); + cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt); } else { - cmdp->u.cache.BlockNo = - ntohl(*(ulong32*)&scp->cmnd[0]) & 0x001fffffUL; + memcpy(&no, &scp->cmnd[0], sizeof(ulong32)); + cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL; cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4]; } @@ -2660,7 +2793,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw.lun = l; cmdp->u.raw.bus = b; cmdp->u.raw.priority = 0; - cmdp->u.raw.link_p = NULL; + cmdp->u.raw.link_p = 0; cmdp->u.raw.sdlen = scp->request_bufflen; cmdp->u.raw.sense_len = 16; cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer); @@ -2825,6 +2958,7 @@ static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, e->first_stamp = e->last_stamp = tv.tv_sec; e->same_count = 1; e->event_data = *evt; + e->application = 0; } return e; } @@ -3195,36 +3329,28 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) if (!(ha->hdr[scp->target].cluster_type & CLUSTER_MOUNTED)) { /* NOT MOUNTED -> MOUNT */ - if (!(ha->hdr[scp->target].cluster_type & - CLUSTER_RESERVED)) { - /* cluster drive NOT RESERVED */ - scp->SCp.Status = GDT_MOUNT; - } else { + scp->SCp.Status = GDT_MOUNT; + if (ha->hdr[scp->target].cluster_type & + CLUSTER_RESERVED) { /* cluster drive RESERVED (on the other node) */ - scp->SCp.Status = GDT_MOUNT; scp->SCp.phase = -2; /* reservation conflict */ } } else { scp->SCp.Status = -1; } - /* retry */ - scp->SCp.this_residual = HIGH_PRI; - return 2; - } else if (scp->SCp.Status == GDT_MOUNT) { - ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED; + } else { + if (scp->SCp.Status == GDT_MOUNT) { + ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED; + ha->hdr[scp->target].media_changed = TRUE; + } else if (scp->SCp.Status == GDT_UNMOUNT) { + ha->hdr[scp->target].cluster_type &= ~CLUSTER_MOUNTED; + ha->hdr[scp->target].media_changed = TRUE; + } scp->SCp.Status = -1; - /* return UNIT_ATTENTION */ - memset((char*)scp->sense_buffer,0,16); - scp->sense_buffer[0] = 0x70; - scp->sense_buffer[2] = UNIT_ATTENTION; - scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - scp->SCp.Message = (int)(ha->info<<16|S_BSY); - } else { - scp->SCp.Status = -1; - /* retry */ - scp->SCp.this_residual = HIGH_PRI; - return 2; } + /* retry */ + scp->SCp.this_residual = HIGH_PRI; + return 2; } else { /* RESERVE/RELEASE ? */ if (scp->cmnd[0] == RESERVE) { @@ -3259,12 +3385,6 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) scp->sense_buffer[0] = 0x70; scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - } else if (scp->cmnd[0] == RESERVE || - scp->cmnd[0] == RELEASE) { - memset((char*)scp->sense_buffer,0,16); - scp->sense_buffer[0] = 0x70; - scp->sense_buffer[2] = NOT_READY; - scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } else if (service == CACHESERVICE) { if (ha->status == S_CACHE_UNKNOWN && (ha->hdr[scp->target].cluster_type & @@ -3293,7 +3413,7 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) } } else { /* sense buffer filled from controller firmware (DMA) */ - if (ha->status!=S_RAW_SCSI || ha->info>=0x100) { + if (ha->status != S_RAW_SCSI || ha->info >= 0x100) { scp->result = DID_BAD_TARGET << 16; } else { scp->result = (DID_OK << 16) | ha->info; @@ -4467,8 +4587,12 @@ GDTH_INITFUNC(void, gdth_setup(char *str,int *ints)) } } - +#if LINUX_VERSION_CODE < 0x020400 #ifdef MODULE Scsi_Host_Template driver_template = GDTH; #include "scsi_module.c" #endif +#else +Scsi_Host_Template driver_template = GDTH; +#include "scsi_module.c" +#endif diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index df26a9be8476..b8dc32909c58 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -10,7 +10,7 @@ * * * - * $Id: gdth.h,v 1.33 2000/07/24 09:29:25 achim Exp $ + * $Id: gdth.h,v 1.35 2000/10/11 08:42:38 achim Exp $ */ #include @@ -29,9 +29,9 @@ /* defines, macros */ /* driver version */ -#define GDTH_VERSION_STR "1.23" +#define GDTH_VERSION_STR "1.25" #define GDTH_VERSION 1 -#define GDTH_SUBVERSION 23 +#define GDTH_SUBVERSION 25 /* protocol version */ #define PROTOCOL_VERSION 1 @@ -625,7 +625,7 @@ typedef struct { unchar priority; /* only 0 used */ ulong32 sense_len; /* sense data length */ ulong32 sense_data; /* sense data addr. */ - struct raw *link_p; /* linked cmds (not supp.) */ + ulong32 link_p; /* linked cmds (not supp.) */ ulong32 sg_ranz; /* s/g element count */ gdth_sg_str sg_lst[GDTH_MAXSG]; /* s/g list */ } PACKED raw; /* raw service cmd. struct. */ @@ -877,7 +877,7 @@ typedef struct { Scsi_Cmnd *req_first; /* top of request queue */ struct { unchar present; /* Flag: host drive present? */ - unchar is_logdrv; /* Flag: logical drive (master)? */ + unchar is_logdrv; /* Flag: log. drive (master)? */ unchar is_arraydrv; /* Flag: array drive? */ unchar is_master; /* Flag: array drive master? */ unchar is_parity; /* Flag: parity drive? */ @@ -891,7 +891,7 @@ typedef struct { unchar ldr_no; /* log. drive no. */ unchar rw_attribs; /* r/w attributes */ unchar cluster_type; /* cluster properties */ - unchar reserved; + unchar media_changed; /* Flag:MOUNT/UNMOUNT occured */ ulong32 start_sec; /* start sector */ } hdr[MAX_LDRIVES]; /* host drives */ struct { diff --git a/drivers/scsi/gdth_ioctl.h b/drivers/scsi/gdth_ioctl.h index 34715246fbb1..de435c409a16 100644 --- a/drivers/scsi/gdth_ioctl.h +++ b/drivers/scsi/gdth_ioctl.h @@ -2,7 +2,7 @@ #define _GDTH_IOCTL_H /* gdth_ioctl.h - * $Id: gdth_ioctl.h,v 1.6 2000/07/24 09:29:43 achim Exp $ + * $Id: gdth_ioctl.h,v 1.7 2000/10/11 08:43:35 achim Exp $ */ /* IOCTLs */ @@ -19,6 +19,7 @@ #define GDTIOCTL_SCSI (GDTIOCTL_MASK | 9) /* SCSI command */ #define GDTIOCTL_RESET_BUS (GDTIOCTL_MASK |10) /* reset SCSI bus */ #define GDTIOCTL_RESCAN (GDTIOCTL_MASK |11) /* rescan host drives */ +#define GDTIOCTL_RESET_DRV (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */ #define GDTIOCTL_MAGIC 0xaffe0003UL #define EVENT_SIZE 294 diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index dbbb43513050..4d561228188a 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -1,5 +1,5 @@ /* gdth_proc.c - * $Id: gdth_proc.c,v 1.22 2000/07/24 09:30:28 achim Exp $ + * $Id: gdth_proc.c,v 1.23 2000/10/11 08:43:11 achim Exp $ */ #include "gdth_ioctl.h" @@ -526,6 +526,30 @@ static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp) GDTH_UNLOCK_HA(ha, flags); break; + case GDTIOCTL_RESET_DRV: + if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str) )) + return(-EBUSY); + piord = (gdth_iord_str *)ha->pscratch; + piord->size = sizeof(gdth_iord_str); + piord->status = S_OK; + i = piowr->iu.scsi.target; + if (ha->hdr[i].present) { + gdtcmd.BoardNode = LOCALBOARD; + gdtcmd.Service = CACHESERVICE; + gdtcmd.OpCode = GDT_CLUST_RESET; + gdtcmd.u.cache.DeviceNo = i; + gdtcmd.u.cache.BlockNo = 0; + gdtcmd.u.cache.sg_canz = 0; +#if LINUX_VERSION_CODE >= 0x020322 + gdth_do_cmd(scp, &gdtcmd, cmnd, 30); + piord->status = (ulong32)scp->SCp.Message; +#else + gdth_do_cmd(&scp, &gdtcmd, cmnd, 30); + piord->status = (ulong32)scp.SCp.Message; +#endif + } + break; + default: return(-EINVAL); } diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 793875190f78..72407ccad6a7 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -882,9 +882,8 @@ int ultrastor_abort(Scsi_Cmnd *SCpnt) (inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1)) { int flags; - save_flags(flags); printk("Ux4F: abort while completed command pending\n"); - restore_flags(flags); + save_flags(flags); cli(); ultrastor_interrupt(0, NULL, NULL); restore_flags(flags); diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in index f4b5be5b5bdb..bb857a41b22d 100644 --- a/drivers/sound/Config.in +++ b/drivers/sound/Config.in @@ -311,10 +311,7 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then fi dep_tristate 'NM256AV/NM256ZX audio support' CONFIG_SOUND_NM256 $CONFIG_SOUND_OSS - dep_tristate 'Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS - if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then - dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS - fi + dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS # Additional low level drivers. diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index c23c1d44259c..e8d1819a61e1 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -97,7 +97,7 @@ obj-$(CONFIG_SOUND_MAESTRO) += maestro.o obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o -obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o +obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o uart401.o ifeq ($(CONFIG_SOUND_EMU10K1),y) obj-y += emu10k1/emu10k1.o @@ -126,7 +126,6 @@ vidc_mod-objs := vidc.o vidc_fill.o vidc_synth.o wavefront-objs := wavfront.o wf_midi.o yss225.o nm256-objs := nm256_audio.o ac97.o via82cxxx-objs := via82cxxx_audio.o ac97.o -ymfsb-objs := ymf_sb.o ac97.o # Extract lists of the multi-part drivers. @@ -218,9 +217,6 @@ nm256.o: $(nm256-objs) via82cxxx.o: $(via82cxxx-objs) $(LD) -r -o $@ $(via82cxxx-objs) -ymfsb.o: $(ymfsb-objs) - $(LD) -r -o $@ $(ymfsb-objs) - # Firmware files that need translation # # The translated files are protected by a file that keeps track diff --git a/drivers/sound/emu10k1/main.c b/drivers/sound/emu10k1/main.c index 9385e53c0f6c..5548786a2868 100644 --- a/drivers/sound/emu10k1/main.c +++ b/drivers/sound/emu10k1/main.c @@ -784,10 +784,3 @@ static void __exit emu10k1_cleanup_module(void) module_init(emu10k1_init_module); module_exit(emu10k1_cleanup_module); - -#ifndef MODULE -int __init init_emu10k1(void) -{ - return emu10k1_init_module(); -} -#endif diff --git a/drivers/sound/es1370.c b/drivers/sound/es1370.c index 43bea56d3ee3..394989b777fe 100644 --- a/drivers/sound/es1370.c +++ b/drivers/sound/es1370.c @@ -114,6 +114,11 @@ * 03.09.1999 0.30 change read semantics for MIDI to match * OSS more closely; remove possible wakeup race * 28.10.1999 0.31 More waitqueue races fixed + * 08.01.2000 0.32 Prevent some ioctl's from returning bad count values on underrun/overrun; + * Tim Janik's BSE (Bedevilled Sound Engine) found this + * 21.11.2000 0.34 Initialize dma buffers in poll, otherwise poll may return a bogus mask + * 12.12.2000 0.35 More dma buffer initializations, patch from + * Tjeerd Mulder * * some important things missing in Ensoniq documentation: * @@ -858,7 +863,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a VALIDATE_STATE(s); if (cmd == SOUND_MIXER_PRIVATE1) { /* enable/disable/query mixer preamp */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { s->mix.micpreamp = !!val; wrcodec(s, 0x19, s->mix.micpreamp); @@ -867,7 +873,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a } if (cmd == SOUND_MIXER_PRIVATE2) { /* enable/disable/query use of linein as second lineout */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { spin_lock_irqsave(&s->lock, flags); if (val) @@ -881,7 +888,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a } if (cmd == SOUND_MIXER_PRIVATE3) { /* enable/disable/query microphone impedance setting */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != -1) { spin_lock_irqsave(&s->lock, flags); if (val) @@ -957,12 +965,14 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a switch (_IOC_NR(cmd)) { case SOUND_MIXER_IMIX: - get_user_ret(s->mix.imix, (int *)arg, -EFAULT); + if (get_user(s->mix.imix, (int *)arg)) + return -EFAULT; set_recsrc(s, s->mix.recsrc); return 0; case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; set_recsrc(s, val); return 0; @@ -970,7 +980,8 @@ static int mixer_ioctl(struct es1370_state *s, unsigned int cmd, unsigned long a i = _IOC_NR(cmd); if (i >= SOUND_MIXER_NRDEVICES || !mixtable[i].avail) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; l = val & 0xff; if (l > 100) l = 100; @@ -1354,6 +1365,7 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; int val, mapped, ret; VALIDATE_STATE(s); @@ -1388,7 +1400,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (s->open_mode & (~file->f_mode) & (FMODE_READ|FMODE_WRITE)) return -EINVAL; @@ -1407,7 +1420,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(DAC2_DIVTOSR((s->ctrl & CTRL_PCLKDIV) >> CTRL_SH_PCLKDIV), (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; @@ -1433,7 +1447,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1464,7 +1479,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1504,7 +1520,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + 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))) @@ -1526,12 +1543,15 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0) + if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); abinfo.fragsize = s->dma_dac2.fragsize; - abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count; + count = s->dma_dac2.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac2.dmasize - count; abinfo.fragstotal = s->dma_dac2.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -1540,12 +1560,15 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0) + if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; + count = s->dma_adc.count; + if (count < 0) + count = 0; + abinfo.bytes = count; abinfo.fragstotal = s->dma_adc.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -1558,19 +1581,28 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); - val = s->dma_dac2.count; + count = s->dma_dac2.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; + if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; + count = s->dma_adc.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_adc.fragshift; cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; @@ -1580,10 +1612,15 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); cinfo.bytes = s->dma_dac2.total_bytes; - cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift; + count = s->dma_dac2.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac2.fragshift; cinfo.ptr = s->dma_dac2.hwptr; if (s->dma_dac2.mapped) s->dma_dac2.count &= s->dma_dac2.fragsize-1; @@ -1601,7 +1638,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1628,7 +1666,8 @@ static int es1370_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) @@ -1878,6 +1917,7 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; unsigned ctrl; int val, ret; @@ -1902,7 +1942,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -1917,7 +1958,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(dac1_samplerate[(s->ctrl & CTRL_WTSRSEL) >> CTRL_SH_WTSRSEL], (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); @@ -1930,7 +1972,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (s->dma_dac1.mapped) return -EINVAL; @@ -1950,7 +1993,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -1971,7 +2015,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) return ret; @@ -1981,12 +2026,15 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_GETOSPACE: - if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0) + if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); abinfo.fragsize = s->dma_dac1.fragsize; - abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count; + count = s->dma_dac1.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac1.dmasize - count; abinfo.fragstotal = s->dma_dac1.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -1997,19 +2045,26 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_GETODELAY: + if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); - val = s->dma_dac1.count; + count = s->dma_dac1.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; + if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1370_update_ptr(s); cinfo.bytes = s->dma_dac1.total_bytes; - cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift; + count = s->dma_dac1.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac1.fragshift; cinfo.ptr = s->dma_dac1.hwptr; if (s->dma_dac1.mapped) s->dma_dac1.count &= s->dma_dac1.fragsize-1; @@ -2022,7 +2077,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dma_dac1.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; s->dma_dac1.ossfragshift = val & 0xffff; s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_dac1.ossfragshift < 4) @@ -2036,7 +2092,8 @@ static int es1370_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_SUBDIVIDE: if (s->dma_dac1.subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; s->dma_dac1.subdivision = val; @@ -2463,7 +2520,7 @@ __initfunc(int init_es1370(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1370: version v0.31 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1370: version v0.35 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) { if (pcidev->base_address[0] == 0 || diff --git a/drivers/sound/es1371.c b/drivers/sound/es1371.c index edc376a0df72..72276e623a5d 100644 --- a/drivers/sound/es1371.c +++ b/drivers/sound/es1371.c @@ -96,6 +96,12 @@ * detect ES137x chip and derivatives. * 05.01.2000 0.22 Should now work with rev7 boards; patch by * Eric Lemar, elemar@cs.washington.edu + * 08.01.2000 0.23 Prevent some ioctl's from returning bad count values on underrun/overrun; + * Tim Janik's BSE (Bedevilled Sound Engine) found this + * 01.03.2000 0.26 SPDIF patch by Mikael Bouillot + * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask + * 12.12.2000 0.28 More dma buffer initializations, patch from + * Tjeerd Mulder */ /*****************************************************************************/ @@ -1937,6 +1943,7 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; int val, mapped, ret; VALIDATE_STATE(s); @@ -1971,7 +1978,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1987,7 +1995,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user((file->f_mode & FMODE_READ) ? s->adcrate : s->dac2rate, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { stop_adc(s); s->dma_adc.ready = 0; @@ -2013,7 +2022,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -2044,7 +2054,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -2084,7 +2095,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + 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))) @@ -2106,12 +2118,15 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!(s->ctrl & CTRL_DAC2_EN) && (val = prog_dmabuf_dac2(s)) != 0) + if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_dac2.fragsize; - abinfo.bytes = s->dma_dac2.dmasize - s->dma_dac2.count; + count = s->dma_dac2.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac2.dmasize - count; abinfo.fragstotal = s->dma_dac2.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac2.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -2120,12 +2135,15 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(s->ctrl & CTRL_ADC_EN) && (val = prog_dmabuf_adc(s)) != 0) + if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; + count = s->dma_adc.count; + if (count < 0) + count = 0; + abinfo.bytes = count; abinfo.fragstotal = s->dma_adc.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -2138,19 +2156,28 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); - val = s->dma_dac2.count; + count = s->dma_dac2.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; + if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; + count = s->dma_adc.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_adc.fragshift; cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; @@ -2160,10 +2187,15 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac2.ready && (val = prog_dmabuf_dac2(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_dac2.total_bytes; - cinfo.blocks = s->dma_dac2.count >> s->dma_dac2.fragshift; + count = s->dma_dac2.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac2.fragshift; cinfo.ptr = s->dma_dac2.hwptr; if (s->dma_dac2.mapped) s->dma_dac2.count &= s->dma_dac2.fragsize-1; @@ -2181,7 +2213,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -2208,7 +2241,8 @@ static int es1371_ioctl(struct inode *inode, struct file *file, unsigned int cmd if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac2.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) @@ -2458,6 +2492,7 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; int val, ret; VALIDATE_STATE(s); @@ -2481,7 +2516,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -2490,7 +2526,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dac1rate, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; stop_dac1(s); s->dma_dac1.ready = 0; spin_lock_irqsave(&s->lock, flags); @@ -2503,7 +2540,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -2521,7 +2559,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { stop_dac1(s); s->dma_dac1.ready = 0; @@ -2542,7 +2581,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user((s->ctrl & CTRL_DAC1_EN) ? PCM_ENABLE_OUTPUT : 0, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val & PCM_ENABLE_OUTPUT) { if (!s->dma_dac1.ready && (ret = prog_dmabuf_dac1(s))) return ret; @@ -2552,12 +2592,15 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_GETOSPACE: - if (!(s->ctrl & CTRL_DAC1_EN) && (val = prog_dmabuf_dac1(s)) != 0) + if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); abinfo.fragsize = s->dma_dac1.fragsize; - abinfo.bytes = s->dma_dac1.dmasize - s->dma_dac1.count; + count = s->dma_dac1.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac1.dmasize - count; abinfo.fragstotal = s->dma_dac1.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac1.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -2568,19 +2611,26 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return 0; case SNDCTL_DSP_GETODELAY: + if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); - val = s->dma_dac1.count; + count = s->dma_dac1.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETOPTR: - if (!(file->f_mode & FMODE_WRITE)) - return -EINVAL; + if (!s->dma_dac1.ready && (val = prog_dmabuf_dac1(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); es1371_update_ptr(s); cinfo.bytes = s->dma_dac1.total_bytes; - cinfo.blocks = s->dma_dac1.count >> s->dma_dac1.fragshift; + count = s->dma_dac1.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_dac1.fragshift; cinfo.ptr = s->dma_dac1.hwptr; if (s->dma_dac1.mapped) s->dma_dac1.count &= s->dma_dac1.fragsize-1; @@ -2593,7 +2643,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int return put_user(s->dma_dac1.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; s->dma_dac1.ossfragshift = val & 0xffff; s->dma_dac1.ossmaxfrags = (val >> 16) & 0xffff; if (s->dma_dac1.ossfragshift < 4) @@ -2607,7 +2658,8 @@ static int es1371_ioctl_dac(struct inode *inode, struct file *file, unsigned int case SNDCTL_DSP_SUBDIVIDE: if (s->dma_dac1.subdivision) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; s->dma_dac1.subdivision = val; @@ -3261,7 +3313,7 @@ __initfunc(int init_es1371(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "es1371: version v0.22 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "es1371: version v0.28 time " __TIME__ " " __DATE__ "\n"); for (pcidev = pci_devices; pcidev && index < NR_DEVICE; pcidev = pcidev->next) { if (pcidev->vendor == PCI_VENDOR_ID_ENSONIQ) { if (pcidev->device != PCI_DEVICE_ID_ENSONIQ_ES1371 && diff --git a/drivers/sound/esssolo1.c b/drivers/sound/esssolo1.c index 1493738cad80..ef470141a2d4 100644 --- a/drivers/sound/esssolo1.c +++ b/drivers/sound/esssolo1.c @@ -63,7 +63,12 @@ * 28.10.1999 0.10 More waitqueue races fixed * 09.12.1999 0.11 Work around stupid Alpha port issue (virt_to_bus(kmalloc(GFP_DMA)) > 16M) * Disabling recording on Alpha - * + * 12.01.2000 0.12 Prevent some ioctl's from returning bad count values on underrun/overrun; + * Tim Janik's BSE (Bedevilled Sound Engine) found this + * Integrated (aka redid 8-)) APM support patch by Zach Brown + * 21.11.2000 0.16 Initialize dma buffers in poll, otherwise poll may return a bogus mask + * 12.12.2000 0.17 More dma buffer initializations, patch from + * Tjeerd Mulder */ /*****************************************************************************/ @@ -1276,7 +1281,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { stop_adc(s); stop_dac(s); @@ -1303,7 +1309,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(s->rate, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; stop_adc(s); stop_dac(s); s->dma_adc.ready = s->dma_dac.ready = 0; @@ -1313,7 +1320,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { stop_adc(s); stop_dac(s); @@ -1328,7 +1336,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { stop_adc(s); stop_dac(s); @@ -1354,7 +1363,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + 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))) @@ -1378,7 +1388,7 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 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->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); solo1_update_ptr(s); @@ -1395,7 +1405,7 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(s->ena & FMODE_READ) && (val = prog_dmabuf_adc(s)) != 0) + if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) return val; spin_lock_irqsave(&s->lock, flags); solo1_update_ptr(s); @@ -1413,6 +1423,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); solo1_update_ptr(s); count = s->dma_dac.count; @@ -1424,13 +1436,12 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; + if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); solo1_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - count = s->dma_dac.count; - if (count < 0) - count = 0; - cinfo.blocks = count >> s->dma_dac.fragshift; + cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; @@ -1440,10 +1451,15 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); solo1_update_ptr(s); cinfo.bytes = s->dma_dac.total_bytes; - cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; + count = s->dma_dac.count; + if (count < 0) + count = 0; + cinfo.blocks = 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; @@ -1467,7 +1483,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1494,7 +1511,8 @@ static int solo1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) @@ -2170,7 +2188,7 @@ static struct initvol { if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "solo1: version v0.11 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "solo1: version v0.17 time " __TIME__ " " __DATE__ "\n"); while (index < NR_DEVICE && (pcidev = pci_find_device(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, pcidev))) { if (pcidev->base_address[0] == 0 || diff --git a/drivers/sound/sonicvibes.c b/drivers/sound/sonicvibes.c index 03ad29b94885..88ffcf29c1ea 100644 --- a/drivers/sound/sonicvibes.c +++ b/drivers/sound/sonicvibes.c @@ -77,11 +77,15 @@ * 24.08.1999 0.19 get rid of the dmaio kludge, replace with allocate_resource * 31.08.1999 0.20 add spin_lock_init * __initlocaldata to fix gcc 2.7.x problems - * use new resource allocation to allocate DDMA IO space * replaced current->state = x with set_current_state(x) * 03.09.1999 0.21 change read semantics for MIDI to match * OSS more closely; remove possible wakeup race * 28.10.1999 0.22 More waitqueue races fixed + * 08.01.2000 0.25 Prevent some ioctl's from returning bad count values on underrun/overrun; + * Tim Janik's BSE (Bedevilled Sound Engine) found this + * 21.11.2000 0.27 Initialize dma buffers in poll, otherwise poll may return a bogus mask + * 12.12.2000 0.28 More dma buffer initializations, patch from + * Tjeerd Mulder * */ @@ -1543,6 +1547,7 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un unsigned long flags; audio_buf_info abinfo; count_info cinfo; + int count; int val, mapped, ret; unsigned char fmtm, fmtd; @@ -1578,7 +1583,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_SPEED: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val >= 0) { if (file->f_mode & FMODE_READ) { stop_adc(s); @@ -1594,7 +1600,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg); case SNDCTL_DSP_STEREO: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; fmtd = 0; fmtm = ~0; if (file->f_mode & FMODE_READ) { @@ -1617,7 +1624,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return 0; case SNDCTL_DSP_CHANNELS: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 0) { fmtd = 0; fmtm = ~0; @@ -1646,7 +1654,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg); case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/ - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != AFMT_QUERY) { fmtd = 0; fmtm = ~0; @@ -1683,7 +1692,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(val, (int *)arg); case SNDCTL_DSP_SETTRIGGER: - get_user_ret(val, (int *)arg, -EFAULT); + 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(s, 1))) @@ -1705,12 +1715,15 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un case SNDCTL_DSP_GETOSPACE: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; - if (!(s->enable & SV_CENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0) + if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0) return val; spin_lock_irqsave(&s->lock, flags); sv_update_ptr(s); abinfo.fragsize = s->dma_dac.fragsize; - abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count; + count = s->dma_dac.count; + if (count < 0) + count = 0; + abinfo.bytes = s->dma_dac.dmasize - count; abinfo.fragstotal = s->dma_dac.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -1719,12 +1732,15 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un case SNDCTL_DSP_GETISPACE: if (!(file->f_mode & FMODE_READ)) return -EINVAL; - if (!(s->enable & SV_CENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0) + if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0) return val; spin_lock_irqsave(&s->lock, flags); sv_update_ptr(s); abinfo.fragsize = s->dma_adc.fragsize; - abinfo.bytes = s->dma_adc.count; + count = s->dma_adc.count; + if (count < 0) + count = 0; + abinfo.bytes = count; abinfo.fragstotal = s->dma_adc.numfrag; abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift; spin_unlock_irqrestore(&s->lock, flags); @@ -1737,19 +1753,28 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un case SNDCTL_DSP_GETODELAY: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); sv_update_ptr(s); - val = s->dma_dac.count; + count = s->dma_dac.count; spin_unlock_irqrestore(&s->lock, flags); - return put_user(val, (int *)arg); + if (count < 0) + count = 0; + return put_user(count, (int *)arg); case SNDCTL_DSP_GETIPTR: if (!(file->f_mode & FMODE_READ)) return -EINVAL; + if (!s->dma_adc.ready && (val = prog_dmabuf(s, 1)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); sv_update_ptr(s); cinfo.bytes = s->dma_adc.total_bytes; - cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift; + count = s->dma_adc.count; + if (count < 0) + count = 0; + cinfo.blocks = count >> s->dma_adc.fragshift; cinfo.ptr = s->dma_adc.hwptr; if (s->dma_adc.mapped) s->dma_adc.count &= s->dma_adc.fragsize-1; @@ -1759,10 +1784,15 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un case SNDCTL_DSP_GETOPTR: if (!(file->f_mode & FMODE_WRITE)) return -EINVAL; + if (!s->dma_dac.ready && (val = prog_dmabuf(s, 0)) != 0) + return val; spin_lock_irqsave(&s->lock, flags); sv_update_ptr(s); cinfo.bytes = s->dma_dac.total_bytes; - cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift; + count = s->dma_dac.count; + if (count < 0) + count = 0; + cinfo.blocks = 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; @@ -1780,7 +1810,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un return put_user(s->dma_adc.fragsize, (int *)arg); case SNDCTL_DSP_SETFRAGMENT: - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (file->f_mode & FMODE_READ) { s->dma_adc.ossfragshift = val & 0xffff; s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff; @@ -1807,7 +1838,8 @@ static int sv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, un if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) || (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision)) return -EINVAL; - get_user_ret(val, (int *)arg, -EFAULT); + if (get_user(val, (int *)arg)) + return -EFAULT; if (val != 1 && val != 2 && val != 4) return -EINVAL; if (file->f_mode & FMODE_READ) @@ -2432,7 +2464,7 @@ __initfunc(int init_sonicvibes(void)) if (!pci_present()) /* No PCI bus in this machine! */ return -ENODEV; - printk(KERN_INFO "sv: version v0.22 time " __TIME__ " " __DATE__ "\n"); + printk(KERN_INFO "sv: version v0.28 time " __TIME__ " " __DATE__ "\n"); #if 0 if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT))) printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n"); diff --git a/drivers/sound/sound_core.c b/drivers/sound/sound_core.c index 3b5c85680585..daed78412ce4 100644 --- a/drivers/sound/sound_core.c +++ b/drivers/sound/sound_core.c @@ -63,7 +63,6 @@ extern int msnd_pinnacle_init(void); extern int init_solo1(void); extern int init_ymf7xxsb_module(void); extern int cs_probe(void); -extern int init_emu10k1(void); extern int cs4281_probe(void); extern void init_vwsnd(void); extern int ymf_probe(void); @@ -435,9 +434,6 @@ int soundcore_init(void) #ifdef CONFIG_SOUND_CS4281 cs4281_probe(); #endif -#ifdef CONFIG_SOUND_EMU10K1 - init_emu10k1(); -#endif #ifdef CONFIG_SOUND_YMFPCI ymf_probe(); #endif diff --git a/drivers/sound/ymf_sb.c b/drivers/sound/ymf_sb.c deleted file mode 100644 index 2af381963287..000000000000 --- a/drivers/sound/ymf_sb.c +++ /dev/null @@ -1,995 +0,0 @@ -/* - Legacy audio driver for YMF724, 740, 744, 754 series. - Copyright 2000 Daisuke Nagano - - Based on the VIA 82Cxxx driver by Jeff Garzik - - Distribued under the GNU PUBLIC LICENSE (GPL) Version 2. - See the "COPYING" file distributed with kernel source tree for more info. - - ------------------------------------------------------------------------- - - It only supports SBPro compatible function of YMF7xx series s.t. - * 22.05kHz, 8-bit and stereo sample - * OPL3-compatible FM synthesizer - * MPU-401 compatible "external" MIDI interface - - and AC'97 mixer of these cards. - - ------------------------------------------------------------------------- - - Revision history - - Tue May 14 19:00:00 2000 0.0.1 - * initial release - - Tue May 16 19:29:29 2000 0.0.2 - - * add a little delays for reset devices. - * fixed addressing bug. - - Sun May 21 15:14:37 2000 0.0.3 - - * Add 'master_vol' module parameter to change 'PCM out Vol' of AC'97. - * remove native UART401 support. External MIDI port should be supported - by sb_midi driver. - * add support for SPDIF OUT. Module parameter 'spdif_out' is now available. - - Wed May 31 00:13:57 2000 0.0.4 - - * remove entries in Hwmcode.h. Now YMF744 / YMF754 sets instructions - in 724hwmcode.h. - * fixed wrong legacy_io setting on YMF744/YMF754 . - - Sat Jun 3 23:44:08 2000 0.0.5 - - * correct all return value -1 to appropriate -E* value. - * add pci_enable_device() for linux-2.3.x. - - Sat Jun 7 00:17:32 2000 0.1.0 - - * Remove SBPro mixer support. - * Added AC'97 mixer support and remove option 'master_volume'. - * Correct all separated valuables into struct ymf_cards. - - Mon Jun 12 21:36:50 2000 0.1.1 - - * Invalid dma setting fixed. - -- John A. Boyd Jr. - - * ymfsb only compiled as module: fixed - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "sound_config.h" -#include "soundmodule.h" -#include "sb.h" -#include "724hwmcode.h" - -#include "ac97.h" - -#undef YMF_DEBUG - -/* ---------------------------------------------------------------------- */ - -#ifndef SOUND_LOCK -# define SOUND_LOCK do {} while (0) -# define SOUND_LOCK_END do {} while (0) -#endif - -#ifndef PCI_VENDOR_ID_YAMAHA -# define PCI_VENDOR_ID_YAMAHA 0x1073 -#endif -#ifndef PCI_DEVICE_ID_YMF724 -# define PCI_DEVICE_ID_YMF724 0x0004 -#endif -#ifndef PCI_DEVICE_ID_YMF740 -# define PCI_DEVICE_ID_YMF740 0x000A -#endif -#ifndef PCI_DEVICE_ID_YMF740C -# define PCI_DEVICE_ID_YMF740C 0x000C -#endif -#ifndef PCI_DEVICE_ID_YMF724F -# define PCI_DEVICE_ID_YMF724F 0x000D -#endif -#ifndef PCI_DEVICE_ID_YMF744 -# define PCI_DEVICE_ID_YMF744 0x0010 -#endif -#ifndef PCI_DEVICE_ID_YMF754 -# define PCI_DEVICE_ID_YMF754 0x0012 -#endif - -/* ---------------------------------------------------------------------- */ - -#define YMFSB_RESET_DELAY 5 - -#define YMFSB_REGSIZE 0x8000 - -#define YMFSB_AC97TIMEOUT 2000 - -#define YMFSB_WORKBITTIMEOUT 250000 - -#define YMFSB_DSPLENGTH 0x0080 -#define YMFSB_CTRLLENGTH 0x3000 - -#define YMFSB_PCIR_VENDORID 0x00 -#define YMFSB_PCIR_DEVICEID 0x02 -#define YMFSB_PCIR_CMD 0x04 -#define YMFSB_PCIR_REVISIONID 0x08 -#define YMFSB_PCIR_BASEADDR 0x10 -#define YMFSB_PCIR_IRQ 0x3c - -#define YMFSB_PCIR_LEGCTRL 0x40 -#define YMFSB_PCIR_ELEGCTRL 0x42 -#define YMFSB_PCIR_DSXGCTRL 0x48 -#define YMFSB_PCIR_OPLADR 0x60 -#define YMFSB_PCIR_SBADR 0x62 -#define YMFSB_PCIR_MPUADR 0x64 - -#define YMFSB_INTFLAG 0x0004 -#define YMFSB_ACTIVITY 0x0006 -#define YMFSB_GLOBALCTRL 0x0008 -#define YMFSB_ZVCTRL 0x000A -#define YMFSB_TIMERCTRL 0x0010 -#define YMFSB_TIMERCOUNT 0x0012 -#define YMFSB_SPDIFOUTCTRL 0x0018 -#define YMFSB_SPDIFOUTSTATUS 0x001C -#define YMFSB_EEPROMCTRL 0x0020 -#define YMFSB_SPDIFINCTRL 0x0034 -#define YMFSB_SPDIFINSTATUS 0x0038 -#define YMFSB_DSPPROGRAMDL 0x0048 -#define YMFSB_DLCNTRL 0x004C -#define YMFSB_GPIOININTFLAG 0x0050 -#define YMFSB_GPIOININTENABLE 0x0052 -#define YMFSB_GPIOINSTATUS 0x0054 -#define YMFSB_GPIOOUTCTRL 0x0056 -#define YMFSB_GPIOFUNCENABLE 0x0058 -#define YMFSB_GPIOTYPECONFIG 0x005A -#define YMFSB_AC97CMDDATA 0x0060 -#define YMFSB_AC97CMDADR 0x0062 -#define YMFSB_PRISTATUSDATA 0x0064 -#define YMFSB_PRISTATUSADR 0x0066 -#define YMFSB_SECSTATUSDATA 0x0068 -#define YMFSB_SECSTATUSADR 0x006A -#define YMFSB_SECCONFIG 0x0070 -#define YMFSB_LEGACYOUTVOL 0x0080 -#define YMFSB_LEGACYOUTVOLL 0x0080 -#define YMFSB_LEGACYOUTVOLR 0x0082 -#define YMFSB_NATIVEDACOUTVOL 0x0084 -#define YMFSB_NATIVEDACOUTVOLL 0x0084 -#define YMFSB_NATIVEDACOUTVOLR 0x0086 -#define YMFSB_SPDIFOUTVOL 0x0088 -#define YMFSB_SPDIFOUTVOLL 0x0088 -#define YMFSB_SPDIFOUTVOLR 0x008A -#define YMFSB_AC3OUTVOL 0x008C -#define YMFSB_AC3OUTVOLL 0x008C -#define YMFSB_AC3OUTVOLR 0x008E -#define YMFSB_PRIADCOUTVOL 0x0090 -#define YMFSB_PRIADCOUTVOLL 0x0090 -#define YMFSB_PRIADCOUTVOLR 0x0092 -#define YMFSB_LEGACYLOOPVOL 0x0094 -#define YMFSB_LEGACYLOOPVOLL 0x0094 -#define YMFSB_LEGACYLOOPVOLR 0x0096 -#define YMFSB_NATIVEDACLOOPVOL 0x0098 -#define YMFSB_NATIVEDACLOOPVOLL 0x0098 -#define YMFSB_NATIVEDACLOOPVOLR 0x009A -#define YMFSB_SPDIFLOOPVOL 0x009C -#define YMFSB_SPDIFLOOPVOLL 0x009E -#define YMFSB_SPDIFLOOPVOLR 0x009E -#define YMFSB_AC3LOOPVOL 0x00A0 -#define YMFSB_AC3LOOPVOLL 0x00A0 -#define YMFSB_AC3LOOPVOLR 0x00A2 -#define YMFSB_PRIADCLOOPVOL 0x00A4 -#define YMFSB_PRIADCLOOPVOLL 0x00A4 -#define YMFSB_PRIADCLOOPVOLR 0x00A6 -#define YMFSB_NATIVEADCINVOL 0x00A8 -#define YMFSB_NATIVEADCINVOLL 0x00A8 -#define YMFSB_NATIVEADCINVOLR 0x00AA -#define YMFSB_NATIVEDACINVOL 0x00AC -#define YMFSB_NATIVEDACINVOLL 0x00AC -#define YMFSB_NATIVEDACINVOLR 0x00AE -#define YMFSB_BUF441OUTVOL 0x00B0 -#define YMFSB_BUF441OUTVOLL 0x00B0 -#define YMFSB_BUF441OUTVOLR 0x00B2 -#define YMFSB_BUF441LOOPVOL 0x00B4 -#define YMFSB_BUF441LOOPVOLL 0x00B4 -#define YMFSB_BUF441LOOPVOLR 0x00B6 -#define YMFSB_SPDIFOUTVOL2 0x00B8 -#define YMFSB_SPDIFOUTVOL2L 0x00B8 -#define YMFSB_SPDIFOUTVOL2R 0x00BA -#define YMFSB_SPDIFLOOPVOL2 0x00BC -#define YMFSB_SPDIFLOOPVOL2L 0x00BC -#define YMFSB_SPDIFLOOPVOL2R 0x00BE -#define YMFSB_ADCSLOTSR 0x00C0 -#define YMFSB_RECSLOTSR 0x00C4 -#define YMFSB_ADCFORMAT 0x00C8 -#define YMFSB_RECFORMAT 0x00CC -#define YMFSB_P44SLOTSR 0x00D0 -#define YMFSB_STATUS 0x0100 -#define YMFSB_CTRLSELECT 0x0104 -#define YMFSB_MODE 0x0108 -#define YMFSB_SAMPLECOUNT 0x010C -#define YMFSB_NUMOFSAMPLES 0x0110 -#define YMFSB_CONFIG 0x0114 -#define YMFSB_PLAYCTRLSIZE 0x0140 -#define YMFSB_RECCTRLSIZE 0x0144 -#define YMFSB_EFFCTRLSIZE 0x0148 -#define YMFSB_WORKSIZE 0x014C -#define YMFSB_MAPOFREC 0x0150 -#define YMFSB_MAPOFEFFECT 0x0154 -#define YMFSB_PLAYCTRLBASE 0x0158 -#define YMFSB_RECCTRLBASE 0x015C -#define YMFSB_EFFCTRLBASE 0x0160 -#define YMFSB_WORKBASE 0x0164 -#define YMFSB_DSPINSTRAM 0x1000 -#define YMFSB_CTRLINSTRAM 0x4000 - - -/* ---------------------------------------------------------------------- */ - -#define MAX_CARDS 4 - -#define PFX "ymf_sb: " - -#define YMFSB_VERSION "0.1.1" -#define YMFSB_CARD_NAME "YMF7xx Legacy Audio driver " YMFSB_VERSION - -#define ymf7xxsb_probe_midi probe_sbmpu -#define ymf7xxsb_attach_midi attach_sbmpu -#define ymf7xxsb_unload_midi unload_sbmpu - -/* ---------------------------------------------------------------------- */ - -static struct ymf_card { - int card; - unsigned short *ymfbase; - - struct address_info sb_data, opl3_data, mpu_data; - - struct ac97_hwint ac97_dev; - int mixer_oss_dev; -} ymf_cards[MAX_CARDS]; - -static unsigned int cards = 0; - -/* ---------------------------------------------------------------------- */ - -#ifdef MODULE -static int mpu_io = 0; -static int synth_io = 0; -static int io = 0; -static int dma = 0; -static int spdif_out = 1; -MODULE_PARM(mpu_io, "i"); -MODULE_PARM(synth_io, "i"); -MODULE_PARM(io,"i"); -MODULE_PARM(dma,"i"); -MODULE_PARM(spdif_out,"i"); -#else -static int mpu_io = 0x330; -static int synth_io = 0x388; -static int io = 0x220; -static int dma = 1; -static int spdif_out = 1; -#endif - -/* ---------------------------------------------------------------------- */ - -static int readRegWord( struct ymf_card *card, int adr ) { - - if (card->ymfbase==NULL) return 0; - - return readw(card->ymfbase+adr/2); -} - -static void writeRegWord( struct ymf_card *card, int adr, int val ) { - - if (card->ymfbase==NULL) return; - - writew((unsigned short)(val&0xffff), card->ymfbase + adr/2); - - return; -} - -static int readRegDWord( struct ymf_card *card, int adr ) { - - if (card->ymfbase==NULL) return 0; - - return (readl(card->ymfbase+adr/2)); -} - -static void writeRegDWord( struct ymf_card *card, int adr, int val ) { - - if (card->ymfbase==NULL) return; - - writel((unsigned int)(val&0xffffffff), card->ymfbase+adr/2); - - return; -} - -/* ---------------------------------------------------------------------- */ - -static int checkPrimaryBusy( struct ymf_card *card ) -{ - int timeout=0; - - while ( timeout++ < YMFSB_AC97TIMEOUT ) - { - if ( (readRegWord(card, YMFSB_PRISTATUSADR) & 0x8000) == 0x0000 ) - return 0; - } - return -EBUSY; -} - -static int checkCodec( struct ymf_card *card, struct pci_dev *pcidev ) -{ - u8 tmp8; - - pci_read_config_byte( pcidev, YMFSB_PCIR_DSXGCTRL, &tmp8 ); - if ( tmp8 & 0x03 ) { - pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc); - mdelay(YMFSB_RESET_DELAY); - pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8|0x03); - mdelay(YMFSB_RESET_DELAY); - pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc); - mdelay(YMFSB_RESET_DELAY); - } - - if ( checkPrimaryBusy( card ) ) return -EBUSY; - - return 0; -} - -static int setupLegacyIO( struct ymf_card *card, struct pci_dev *pcidev ) -{ - int v; - int sbio=0, mpuio=0, oplio=0,dma=0; - - switch(card->sb_data.io_base) { - case 0x220: - sbio = 0; - break; - case 0x240: - sbio = 1; - break; - case 0x260: - sbio = 2; - break; - case 0x280: - sbio = 3; - break; - default: - return -EINVAL; - break; - } -#ifdef YMF_DEBUG - printk(PFX "set SBPro I/O at 0x%x\n",card->sb_data.io_base); -#endif - - switch(card->mpu_data.io_base) { - case 0x330: - mpuio = 0; - break; - case 0x300: - mpuio = 1; - break; - case 0x332: - mpuio = 2; - break; - case 0x334: - mpuio = 3; - break; - default: - mpuio = 0; - break; - } -#ifdef YMF_DEBUG - printk(PFX "set MPU401 I/O at 0x%x\n",card->mpu_data.io_base); -#endif - - switch(card->opl3_data.io_base) { - case 0x388: - oplio = 0; - break; - case 0x398: - oplio = 1; - break; - case 0x3a0: - oplio = 2; - break; - case 0x3a8: - oplio = 3; - break; - default: - return -EINVAL; - break; - } -#ifdef YMF_DEBUG - printk(PFX "set OPL3 I/O at 0x%x\n",card->opl3_data.io_base); -#endif - - dma = card->sb_data.dma; -#ifdef YMF_DEBUG - printk(PFX "set DMA address at 0x%x\n",card->sb_data.dma); -#endif - - v = 0x0000 | ((dma&0x03)<<6) | 0x003f; - pci_write_config_word(pcidev, YMFSB_PCIR_LEGCTRL, v); -#ifdef YMF_DEBUG - printk(PFX "LEGCTRL: 0x%x\n",v); -#endif - switch( pcidev->device ) { - case PCI_DEVICE_ID_YMF724: - case PCI_DEVICE_ID_YMF740: - case PCI_DEVICE_ID_YMF724F: - case PCI_DEVICE_ID_YMF740C: - v = 0x8800 | ((mpuio<<4)&0x03) | ((sbio<<2)&0x03) | (oplio&0x03); - pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v); -#ifdef YMF_DEBUG - printk(PFX "ELEGCTRL: 0x%x\n",v); -#endif - break; - - case PCI_DEVICE_ID_YMF744: - case PCI_DEVICE_ID_YMF754: - v = 0x8800; - pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v); - pci_write_config_word(pcidev, YMFSB_PCIR_OPLADR, card->opl3_data.io_base); - pci_write_config_word(pcidev, YMFSB_PCIR_SBADR, card->sb_data.io_base); - pci_write_config_word(pcidev, YMFSB_PCIR_MPUADR, card->mpu_data.io_base); - break; - - default: - printk(KERN_ERR PFX "Invalid device ID: %d\n",pcidev->device); - return -EINVAL; - break; - } - - return 0; -} - -/* ---------------------------------------------------------------------- */ -/* AC'97 stuff */ -static int ymfsb_readAC97Reg( struct ac97_hwint *dev, u8 reg ) -{ - struct ymf_card *card = (struct ymf_card *)dev->driver_private; - unsigned long flags; - int ret; - - if ( reg > 0x7f ) return -EINVAL; - - save_flags(flags); - cli(); - writeRegWord( card, YMFSB_AC97CMDADR, 0x8000 | reg ); - if ( checkPrimaryBusy( card ) ) { - restore_flags(flags); - return -EBUSY; - } - ret = readRegWord( card, YMFSB_AC97CMDDATA ); - restore_flags(flags); - - return ret; -} - -static int ymfsb_writeAC97Reg( struct ac97_hwint *dev, u8 reg, u16 value ) -{ - struct ymf_card *card = (struct ymf_card *)dev->driver_private; - unsigned long flags; - - if ( reg > 0x7f ) return -EINVAL; - - save_flags(flags); - cli(); - if ( checkPrimaryBusy( card ) ) { - restore_flags(flags); - return -EBUSY; - } - - writeRegWord( card, YMFSB_AC97CMDADR, 0x0000 | reg ); - writeRegWord( card, YMFSB_AC97CMDDATA, value ); - - restore_flags(flags); - return 0; -} - -struct initialValues -{ - unsigned short port; - unsigned short value; -}; - -static struct initialValues ymfsb_ac97_initial_values[] = -{ - { AC97_RESET, 0x0000 }, - { AC97_MASTER_VOL_STEREO, 0x0000 }, - { AC97_HEADPHONE_VOL, 0x8000 }, - { AC97_PCMOUT_VOL, 0x0606 }, - { AC97_MASTER_VOL_MONO, 0x0000 }, - { AC97_PCBEEP_VOL, 0x0000 }, - { AC97_PHONE_VOL, 0x0008 }, - { AC97_MIC_VOL, 0x8000 }, - { AC97_LINEIN_VOL, 0x8808 }, - { AC97_CD_VOL, 0x8808 }, - { AC97_VIDEO_VOL, 0x8808 }, - { AC97_AUX_VOL, 0x8808 }, - { AC97_RECORD_SELECT, 0x0000 }, - { AC97_RECORD_GAIN, 0x0B0B }, - { AC97_GENERAL_PURPOSE, 0x0000 }, - { 0xffff, 0xffff } -}; - -static int ymfsb_resetAC97( struct ac97_hwint *dev ) -{ - int i; - - for ( i=0 ; ymfsb_ac97_initial_values[i].port != 0xffff ; i++ ) - { - ac97_put_register ( dev, - ymfsb_ac97_initial_values[i].port, - ymfsb_ac97_initial_values[i].value ); - } - - return 0; -} - -static int ymfsb_ac97_mixer_ioctl( int dev, unsigned int cmd, caddr_t arg ) -{ - int i; - - for ( i=0 ; i < MAX_CARDS ; i++ ) - { - if ( ymf_cards[i].mixer_oss_dev == dev ) break; - } - - if ( i < MAX_CARDS ) - return ac97_mixer_ioctl(&(ymf_cards[i].ac97_dev), cmd, arg); - else - return -ENODEV; -} - -static struct mixer_operations ymfsb_ac97_mixer_operations = { - "YAMAHA", - "YAMAHA PCI", - ymfsb_ac97_mixer_ioctl -}; - -static struct ac97_mixer_value_list ymfsb_ac97_mixer_defaults[] = { - { SOUND_MIXER_VOLUME, { { 85, 85 } } }, - { SOUND_MIXER_SPEAKER, { { 100 } } }, - { SOUND_MIXER_PCM, { { 65, 65 } } }, - { SOUND_MIXER_CD, { { 65, 65 } } }, - { -1, { { 0, 0 } } } -}; - -/* ---------------------------------------------------------------------- */ - -static void enableDSP( struct ymf_card *card ) -{ - writeRegDWord( card, YMFSB_CONFIG, 0x00000001 ); - return; -} - -static void disableDSP( struct ymf_card *card ) -{ - int val; - int i; - - val = readRegDWord( card, YMFSB_CONFIG ); - if ( val ) { - writeRegDWord( card, YMFSB_CONFIG, 0 ); - } - - i=0; - while( ++i < YMFSB_WORKBITTIMEOUT ) { - val = readRegDWord( card, YMFSB_STATUS ); - if ( (val & 0x00000002) == 0x00000000 ) break; - } - - return; -} - -static int setupInstruction( struct ymf_card *card, struct pci_dev *pcidev ) -{ - int i; - int val; - - writeRegDWord( card, YMFSB_NATIVEDACOUTVOL, 0 ); /* mute dac */ - disableDSP( card ); - - writeRegDWord( card, YMFSB_MODE, 0x00010000 ); - - /* DS-XG Software Reset */ - writeRegDWord( card, YMFSB_MODE, 0x00000000 ); - writeRegDWord( card, YMFSB_MAPOFREC, 0x00000000 ); - writeRegDWord( card, YMFSB_MAPOFEFFECT, 0x00000000 ); - writeRegDWord( card, YMFSB_PLAYCTRLBASE, 0x00000000 ); - writeRegDWord( card, YMFSB_RECCTRLBASE, 0x00000000 ); - writeRegDWord( card, YMFSB_EFFCTRLBASE, 0x00000000 ); - - val = readRegWord( card, YMFSB_GLOBALCTRL ); - writeRegWord( card, YMFSB_GLOBALCTRL, (val&~0x0007) ); - - /* setup DSP instruction code */ - for ( i=0 ; i>2] ); - } - - switch( pcidev->device ) { - case PCI_DEVICE_ID_YMF724: - case PCI_DEVICE_ID_YMF740: - /* setup Control instruction code */ - for ( i=0 ; i>2] ); - } - break; - - case PCI_DEVICE_ID_YMF724F: - case PCI_DEVICE_ID_YMF740C: - case PCI_DEVICE_ID_YMF744: - case PCI_DEVICE_ID_YMF754: - /* setup Control instruction code */ - - for ( i=0 ; i>2] ); - } - break; - - default: - return -ENXIO; - } - - enableDSP( card ); - - return 0; -} - -/* ---------------------------------------------------------------------- */ - -static int __init ymf7xx_init( struct ymf_card *card, struct pci_dev *pcidev ) -{ - unsigned short v; - int mixer; - - /* Read hardware information */ -#ifdef YMF_DEBUG - unsigned int dv; - pci_read_config_word(pcidev, YMFSB_PCIR_VENDORID, &v); - printk(KERN_INFO PFX "Vendor ID = 0x%x\n",v); - pci_read_config_word(pcidev, YMFSB_PCIR_DEVICEID, &v); - printk(KERN_INFO PFX "Device ID = 0x%x\n",v); - pci_read_config_word(pcidev, YMFSB_PCIR_REVISIONID, &v); - printk(KERN_INFO PFX "Revision ID = 0x%x\n",v&0xff); - pci_read_config_dword(pcidev, YMFSB_PCIR_BASEADDR, &dv); - printk(KERN_INFO PFX "Base address = 0x%x\n",dv); - pci_read_config_word(pcidev, YMFSB_PCIR_IRQ, &v); - printk(KERN_INFO PFX "IRQ line = 0x%x\n",v&0xff); -#endif - - /* enables memory space access / bus mastering */ - pci_read_config_word(pcidev, YMFSB_PCIR_CMD, &v); - pci_write_config_word(pcidev, YMFSB_PCIR_CMD, v|0x06); - - /* check codec */ -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "check codec...\n"); -#endif - if (checkCodec(card, pcidev)) return -EBUSY; - - /* setup legacy I/O */ -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "setup legacy I/O...\n"); -#endif - if (setupLegacyIO(card, pcidev)) return -EBUSY; - - /* setup instruction code */ -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "setup instructions...\n"); -#endif - if (setupInstruction(card, pcidev)) return -EBUSY; - - /* AC'97 setup */ -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "setup AC'97...\n"); -#endif - if ( ac97_init( &card->ac97_dev ) ) return -EBUSY; - - mixer = sound_alloc_mixerdev(); - if ( num_mixers >= MAX_MIXER_DEV ) return -EBUSY; - - mixer_devs[mixer] = &ymfsb_ac97_mixer_operations; - card->mixer_oss_dev = mixer; - ac97_set_values( &card->ac97_dev, ymfsb_ac97_mixer_defaults ); - -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "setup Legacy Volume...\n"); -#endif - /* Legacy Audio Output Volume L & R ch */ - writeRegDWord( card, YMFSB_LEGACYOUTVOL, 0x3fff3fff ); - -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "setup SPDIF output control...\n"); -#endif - /* SPDIF Output control */ - v = spdif_out != 0 ? 0x0001 : 0x0000; - writeRegWord( card, YMFSB_SPDIFOUTCTRL, v ); - /* no copyright protection, - sample-rate converted, - re-recorded software comercially available (the 1st generation), - original */ - writeRegWord( card, YMFSB_SPDIFOUTSTATUS, 0x9a04 ); - - return 0; -} - -/* ---------------------------------------------------------------------- */ - -static void __init ymf7xxsb_attach_sb(struct address_info *hw_config) -{ - hw_config->driver_use_1 |= SB_NO_MIXER; - if(!sb_dsp_init(hw_config)) - hw_config->slots[0] = -1; -} - -static int __init ymf7xxsb_probe_sb(struct address_info *hw_config) -{ - if (check_region(hw_config->io_base, 16)) - { - printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n", - hw_config->io_base); - return 0; - } - return sb_dsp_detect(hw_config, SB_PCI_YAMAHA, 0); -} - - -static void ymf7xxsb_unload_sb(struct address_info *hw_config, int unload_mpu) -{ - if(hw_config->slots[0]!=-1) - sb_dsp_unload(hw_config, unload_mpu); -} - -/* ---------------------------------------------------------------------- */ - -static int __init ymf7xxsb_install (struct pci_dev *pcidev) -{ - struct { - unsigned short deviceid; - char *devicename; - } devicetable[] = - { - { PCI_DEVICE_ID_YMF724, "YMF724A-E" }, - { PCI_DEVICE_ID_YMF724F, "YMF724F" }, - { PCI_DEVICE_ID_YMF740, "YMF740A-B" }, - { PCI_DEVICE_ID_YMF740C, "YMF740C" }, - { PCI_DEVICE_ID_YMF744, "YMF744" }, - { PCI_DEVICE_ID_YMF754, "YMF754" }, - }; - - char *devicename = "unknown"; - int i; - unsigned long iobase; - struct ymf_card *card; - - if ( pcidev->irq == 0 ) return -ENODEV; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0) - if ( pci_enable_device(pcidev) ) { - printk (KERN_ERR PFX "cannot enable PCI device\n"); - return -EIO; - } -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) - iobase = pcidev->base_address[0]&PCI_BASE_ADDRESS_MEM_MASK; -#else - iobase = pcidev->resource[0].start&PCI_BASE_ADDRESS_MEM_MASK; -#endif - if ( iobase == 0x00000000 ) return -ENODEV; - - for ( i=0 ; idevice) - { - devicename = devicetable[i].devicename; - break; - } - } - - card = &ymf_cards[cards]; - - /* remap memory mapped I/O onto kernel virtual memory */ - if ( (card->ymfbase = ioremap_nocache(iobase, YMFSB_REGSIZE)) == 0 ) - { - printk(KERN_ERR PFX "ioremap (0x%lx) returns zero\n", iobase); - return -ENODEV; - } - printk(KERN_INFO PFX "found %s at 0x%lx\n", devicename, iobase); -#ifdef YMF_DEBUG - printk(KERN_INFO PFX "remappling to 0x%p\n", card->ymfbase); -#endif - - memset (&card->sb_data, 0, sizeof (struct address_info)); - memset (&card->opl3_data, 0, sizeof (struct address_info)); - memset (&card->mpu_data, 0, sizeof (struct address_info)); - memset (&card->ac97_dev, 0, sizeof (struct ac97_hwint)); - - card->card = cards; - - card->sb_data.name = YMFSB_CARD_NAME; - card->opl3_data.name = YMFSB_CARD_NAME; - card->mpu_data.name = YMFSB_CARD_NAME; - - card->sb_data.card_subtype = MDL_YMPCI; - - if ( io == 0 ) io = 0x220; - card->sb_data.io_base = io; - card->sb_data.irq = pcidev->irq; - card->sb_data.dma = dma; - - if ( synth_io == 0 ) synth_io = 0x388; - card->opl3_data.io_base = synth_io; - card->opl3_data.irq = -1; - - if ( mpu_io == 0 ) mpu_io = 0x330; - card->mpu_data.io_base = mpu_io; - card->mpu_data.irq = -1; - - card->ac97_dev.reset_device = ymfsb_resetAC97; - card->ac97_dev.read_reg = ymfsb_readAC97Reg; - card->ac97_dev.write_reg = ymfsb_writeAC97Reg; - card->ac97_dev.driver_private = (void *)card; - - if ( ymf7xx_init(card, pcidev) ) { - printk (KERN_ERR PFX - "Cannot initialize %s, aborting\n", - devicename); - return -ENODEV; - } - - /* regist legacy SoundBlaster Pro */ - if (!ymf7xxsb_probe_sb(&card->sb_data)) { - printk (KERN_ERR PFX - "SB probe at 0x%X failed, aborting\n", - io); - return -ENODEV; - } - ymf7xxsb_attach_sb (&card->sb_data); - - /* regist legacy MIDI */ - if ( mpu_io > 0 && 0) - { - if (!ymf7xxsb_probe_midi (&card->mpu_data)) { - printk (KERN_ERR PFX - "MIDI probe @ 0x%X failed, aborting\n", - mpu_io); - ymf7xxsb_unload_sb (&card->sb_data, 0); - return -ENODEV; - } - ymf7xxsb_attach_midi (&card->mpu_data); - } - - /* regist legacy OPL3 */ - - cards++; - return 0; -} - -static int __init probe_ymf7xxsb (void) -{ - struct pci_dev *pcidev = NULL; - int i; - - for (i=0 ; i= 0 ) - sound_unload_mixerdev( ymf_cards[i].mixer_oss_dev ); - } - - free_iomaps(); - - /* - * Final clean up with the sound layer - */ - SOUND_LOCK_END; -} - -#ifdef MODULE - -MODULE_AUTHOR("Daisuke Nagano, breeze.nagano@nifty.ne.jp"); -MODULE_DESCRIPTION("YMF7xx Legacy Audio Driver"); - -int init_module(void) -{ - return init_ymf7xxsb_module(); -} - -void cleanup_module(void) -{ - cleanup_ymf7xxsb_module(); -} - -#endif diff --git a/drivers/sound/ymfpci.c b/drivers/sound/ymfpci.c index d18b96d3df14..b4a625a8c5b1 100644 --- a/drivers/sound/ymfpci.c +++ b/drivers/sound/ymfpci.c @@ -34,6 +34,8 @@ * ? underused structure members */ +#define YMFPCI_HAVE_MIDI_SUPPORT + #include #include #include @@ -46,6 +48,10 @@ #include #include +#ifdef YMFPCI_HAVE_MIDI_SUPPORT +# include "sound_config.h" +#endif + #include "ymfpci.h" #define snd_magic_cast(t, p, err) ((t *)(p)) @@ -1870,6 +1876,90 @@ static int ymf_ioctl(struct inode *inode, struct file *file, return -ENOTTY; } +#ifdef YMFPCI_HAVE_MIDI_SUPPORT +/* MIDI stuff */ + +/* */ + +static int ymfpci_setup_legacy( ymfpci_t *codec, struct pci_dev *pcidev ) +{ + int v; + int mpuio=-1, oplio=-1; + + switch(codec->iomidi) { + case 0x330: + mpuio = 0; + break; + case 0x300: + mpuio = 1; + break; + case 0x332: + mpuio = 2; + break; + case 0x334: + mpuio = 3; + break; + default: + break; + } + + switch(codec->iosynth) { + case 0x388: + oplio = 0; + break; + case 0x398: + oplio = 1; + break; + case 0x3a0: + oplio = 2; + break; + case 0x3a8: + oplio = 3; + break; + default: + break; + } + + if ( mpuio >= 0 || oplio >= 0 ) { + v = 0x003e; + pci_write_config_word(pcidev, PCIR_LEGCTRL, v); + + switch( pcidev->device ) { + case PCI_DEVICE_ID_YAMAHA_724: + case PCI_DEVICE_ID_YAMAHA_740: + case PCI_DEVICE_ID_YAMAHA_724F: + case PCI_DEVICE_ID_YAMAHA_740C: + v = 0x8800; + if ( mpuio >= 0 ) { v|= (mpuio<<4)&0x03; } + if ( oplio >= 0 ) { v|= (oplio&0x03); } + pci_write_config_word(pcidev, PCIR_ELEGCTRL, v); + break; + + case PCI_DEVICE_ID_YAMAHA_744: + case PCI_DEVICE_ID_YAMAHA_754: + v = 0x8800; + pci_write_config_word(pcidev, PCIR_ELEGCTRL, v); + if ( mpuio >= 0 ) { + pci_write_config_word(pcidev, PCIR_OPLADR, codec->iosynth); + } + if ( oplio >= 0 ) { + pci_write_config_word(pcidev, PCIR_MPUADR, codec->iomidi); + } + break; + + default: + printk(KERN_ERR "ymfpci: Invalid device ID: %d\n",pcidev->device); + return -EINVAL; + break; + } + } + + return 0; +} +#endif /* YMFPCI_HAVE_MIDI_SUPPORT */ + +/* */ + static int ymf_open(struct inode *inode, struct file *file) { ymfpci_t *unit; @@ -1895,7 +1985,11 @@ static int ymf_open(struct inode *inode, struct file *file) /* XXX Semaphore here! */ for (unit = ymf_devs; unit != NULL; unit = unit->next) { +#if 0 if (unit->inst == instance) break; +#else + if (!((unit->dev_audio ^ minor) & ~0x0f)) break; +#endif } if (unit == NULL) return -ENODEV; @@ -2234,6 +2328,20 @@ static int ymf_ac97_init(ymfpci_t *card, int num_ac97) return 0; } +/* */ +#ifdef YMFPCI_HAVE_MIDI_SUPPORT +# ifdef MODULE +static int mpu_io = 0; +static int synth_io = 0; +MODULE_PARM(mpu_io, "i"); +MODULE_PARM(synth_io, "i"); +# else +static int mpu_io = 0x330; +static int synth_io = 0x388; +# endif +#endif /* YMFPCI_HAVE_MIDI_SUPPORT */ +/* */ + static int /* __init */ ymf_install(struct pci_dev *pcidev, int instance, int devx) { @@ -2268,6 +2376,15 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx) return -ENODEV; } +#ifdef YMFPCI_HAVE_MIDI_SUPPORT + codec->iomidi = mpu_io; + codec->iosynth = synth_io; + if (ymfpci_setup_legacy(codec, pcidev) < 0) { + ymfpci_free(codec); + return -ENODEV; + } +#endif + ymfpci_download_image(codec); udelay(100); /* seems we need some delay after downloading image.. */ @@ -2304,6 +2421,28 @@ ymf_install(struct pci_dev *pcidev, int instance, int devx) return err; } +#ifdef YMFPCI_HAVE_MIDI_SUPPORT + memset (&codec->opl3_data, 0, sizeof (struct address_info)); + memset (&codec->mpu_data, 0, sizeof (struct address_info)); + + codec->opl3_data.name = "ymfpci"; + codec->mpu_data.name = "ymfpci"; + + codec->opl3_data.io_base = codec->iosynth; + codec->opl3_data.irq = -1; + + codec->mpu_data.io_base = codec->iomidi; + codec->mpu_data.irq = -1; + + if ( mpu_io > 0 ) + { + if ( probe_uart401(&codec->mpu_data) ) { + attach_uart401(&codec->mpu_data); + } + } + +#endif /* YMFPCI_HAVE_MIDI_SUPPORT */ + codec->next = ymf_devs; ymf_devs = codec; @@ -2339,6 +2478,11 @@ ymfpci_free(ymfpci_t *codec) unregister_sound_mixer(codec->ac97_codec[0]->dev_mixer); kfree(codec->ac97_codec[0]); } +#ifdef YMFPCI_HAVE_MIDI_SUPPORT + if (codec->iomidi) { + unload_uart401(&(codec->mpu_data)); + } +#endif /* YMFPCI_HAVE_MIDI_SUPPORT */ kfree(codec); } diff --git a/drivers/sound/ymfpci.h b/drivers/sound/ymfpci.h index 29b611f1fc06..0f0b674eebe8 100644 --- a/drivers/sound/ymfpci.h +++ b/drivers/sound/ymfpci.h @@ -131,7 +131,19 @@ #define YDSXG_AC97READCMD 0x8000 #define YDSXG_AC97WRITECMD 0x0000 +#define PCIR_VENDORID 0x00 +#define PCIR_DEVICEID 0x02 +#define PCIR_CMD 0x04 +#define PCIR_REVISIONID 0x08 +#define PCIR_BASEADDR 0x10 +#define PCIR_IRQ 0x3c + +#define PCIR_LEGCTRL 0x40 +#define PCIR_ELEGCTRL 0x42 #define PCIR_DSXGCTRL 0x48 +#define PCIR_OPLADR 0x60 +#define PCIR_SBADR 0x62 +#define PCIR_MPUADR 0x64 #define YDSXG_DSPLENGTH 0x0080 #define YDSXG_CTRLLENGTH 0x3000 @@ -281,6 +293,10 @@ struct ymf_unit { int irq; int inst; /* Unit number (instance) */ + /* legacy hardware resources */ + unsigned int iosynth, iomidi; + struct address_info opl3_data, mpu_data; + spinlock_t reg_lock; spinlock_t voice_lock; diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in index 66ae3b852dd3..20d52b2b7a34 100644 --- a/drivers/usb/Config.in +++ b/drivers/usb/Config.in @@ -50,6 +50,7 @@ comment 'USB Devices' fi dep_tristate ' USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_OMNINET $CONFIG_USB_SERIAL dep_tristate ' USB Belkin and Peracom Single Port Serial Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_BELKIN $CONFIG_USB_SERIAL + dep_tristate ' USB Empeg empeg-car Mark I/II Driver (EXPERIMENTAL)' CONFIG_USB_SERIAL_EMPEG $CONFIG_USB_SERIAL fi bool ' USB Serial Converter verbose debug' CONFIG_USB_SERIAL_DEBUG $CONFIG_USB_SERIAL fi diff --git a/drivers/usb/dabusb.c b/drivers/usb/dabusb.c index 65c01e9977fc..76e6c214b9d6 100644 --- a/drivers/usb/dabusb.c +++ b/drivers/usb/dabusb.c @@ -173,8 +173,8 @@ static void dabusb_iso_complete (purb_t purb) // process if URB was not killed if (purb->status != -ENOENT) { - unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); - int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); + unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); + int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); for (i = 0; i < purb->number_of_packets; i++) if (!purb->iso_frame_desc[i].status) { len = purb->iso_frame_desc[i].actual_length; @@ -456,6 +456,8 @@ static int dabusb_startrek (pdabusb_t s) end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); + end->purb->dev=s->usbdev; + ret = usb_submit_urb (end->purb); if (ret) { err("usb_submit_urb returned:%d", ret); diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index c262023a7b7f..97481d2ae726 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -23,6 +23,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 +obj-$(CONFIG_USB_SERIAL_EMPEG) += empeg.o # Objects that export symbols. export-objs := usbserial.o diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c new file mode 100644 index 000000000000..cb5608b198da --- /dev/null +++ b/drivers/usb/serial/empeg.c @@ -0,0 +1,609 @@ +/* + * USB Empeg empeg-car player driver + * + * Copyright (C) 2000 + * Gary Brubaker (xavyer@ix.netcom.com) + * + * Copyright (C) 1999, 2000 + * Greg Kroah-Hartman (greg@kroah.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, as published by + * the Free Software Foundation, version 2. + * + * See Documentation/usb/usb-serial.txt for more information on using this driver + * + * (11/13/2000) gb + * Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open() + * (It only needs to be set once - Doh!) + * + * (11/11/2000) gb + * Updated to work with id_table structure. + * + * (11/04/2000) gb + * Forked this from visor.c, and hacked it up to work with an + * Empeg ltd. empeg-car player. Constructive criticism welcomed. + * I would like to say, 'Thank You' to Greg Kroah-Hartman for the + * use of his code, and for his guidance, advice and patience. :) + * A 'Thank You' is in order for John Ripley of Empeg ltd for his + * advice, and patience too. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_USB_SERIAL_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif +#include + +#include "usb-serial.h" + +#define EMPEG_VENDOR_ID 0x084f +#define EMPEG_PRODUCT_ID 0x0001 + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +/* function prototypes for an empeg-car player */ +static int empeg_open (struct usb_serial_port *port, struct file *filp); +static void empeg_close (struct usb_serial_port *port, struct file *filp); +static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count); +static void empeg_throttle (struct usb_serial_port *port); +static void empeg_unthrottle (struct usb_serial_port *port); +static int empeg_startup (struct usb_serial *serial); +static void empeg_shutdown (struct usb_serial *serial); +static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg); +static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios); +static void empeg_write_bulk_callback (struct urb *urb); +static void empeg_read_bulk_callback (struct urb *urb); + +static __u16 empeg_vendor_id = EMPEG_VENDOR_ID; +static __u16 empeg_product_id = EMPEG_PRODUCT_ID; +struct usb_serial_device_type empeg_device = { + name: "Empeg", + idVendor: &empeg_vendor_id, + idProduct: &empeg_product_id, + needs_interrupt_in: MUST_HAVE_NOT, /* must not have an interrupt in endpoint */ + needs_bulk_in: MUST_HAVE, /* must have a bulk in endpoint */ + needs_bulk_out: MUST_HAVE, /* must have a bulk out endpoint */ + num_interrupt_in: 0, + num_bulk_in: 1, + num_bulk_out: 1, + num_ports: 1, + open: empeg_open, + close: empeg_close, + throttle: empeg_throttle, + unthrottle: empeg_unthrottle, + startup: empeg_startup, + shutdown: empeg_shutdown, + ioctl: empeg_ioctl, + set_termios: empeg_set_termios, + write: empeg_write, + write_bulk_callback: empeg_write_bulk_callback, + read_bulk_callback: empeg_read_bulk_callback, +}; + +#define NUM_URBS 16 +#define URB_TRANSFER_BUFFER_SIZE 4096 + +static struct urb *write_urb_pool[NUM_URBS]; +static spinlock_t write_urb_pool_lock; +static int bytes_in; +static int bytes_out; + +/****************************************************************************** + * Empeg specific driver functions + ******************************************************************************/ +static int empeg_open (struct usb_serial_port *port, struct file *filp) +{ + unsigned long flags; + int result; + + if (port_paranoia_check (port, __FUNCTION__)) + return -ENODEV; + + dbg(__FUNCTION__ " - port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + ++port->open_count; + MOD_INC_USE_COUNT; + + /* gb - 2000/11/05 + * + * personally, I think these termios should be set in + * empeg_startup(), but it appears doing so leads to one + * of those chicken/egg problems. :) + * + */ + port->tty->termios->c_iflag + &= ~(IGNBRK + | BRKINT + | PARMRK + | ISTRIP + | INLCR + | IGNCR + | ICRNL + | IXON); + + port->tty->termios->c_oflag + &= ~OPOST; + + port->tty->termios->c_lflag + &= ~(ECHO + | ECHONL + | ICANON + | ISIG + | IEXTEN); + + port->tty->termios->c_cflag + &= ~(CSIZE + | PARENB); + + port->tty->termios->c_cflag + |= CS8; + + /* gb - 2000/11/05 + * + * force low_latency on + * + * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually + * force the data through if low_latency is set. Otherwise the pushes are + * scheduled; this is bad as it opens up the possibility of dropping bytes + * on the floor. We are trying to sustain high data transfer rates; and + * don't want to drop bytes on the floor. + * Moral: use low_latency - drop no bytes - life is good. :) + * + */ + port->tty->low_latency = 1; + + if (!port->active) { + port->active = 1; + bytes_in = 0; + bytes_out = 0; + + /* Start reading from the device */ + port->read_urb->transfer_flags |= USB_QUEUE_BULK; + + result = usb_submit_urb(port->read_urb); + + if (result) + err(__FUNCTION__ " - failed submitting read urb, error %d", result); + + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + return 0; +} + + +static void empeg_close (struct usb_serial_port *port, struct file * filp) +{ + struct usb_serial *serial; + unsigned char *transfer_buffer; + unsigned long flags; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + serial = get_usb_serial (port, __FUNCTION__); + if (!serial) + return; + + spin_lock_irqsave (&port->port_lock, flags); + + --port->open_count; + MOD_DEC_USE_COUNT; + + if (port->open_count <= 0) { + transfer_buffer = kmalloc (0x12, GFP_KERNEL); + + if (!transfer_buffer) { + err(__FUNCTION__ " - kmalloc(%d) failed.", 0x12); + } else { + kfree (transfer_buffer); + } + + /* shutdown our bulk read */ + usb_unlink_urb (port->read_urb); + port->active = 0; + port->open_count = 0; + } + + spin_unlock_irqrestore (&port->port_lock, flags); + + /* Uncomment the following line if you want to see some statistics in your syslog */ + /* info ("Bytes In = %d Bytes Out = %d", bytes_in, bytes_out); */ + +} + + +static int empeg_write (struct usb_serial_port *port, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial *serial = port->serial; + struct urb *urb; + const unsigned char *current_position = buf; + unsigned long flags; + int status; + int i; + int bytes_sent = 0; + int transfer_size; + + dbg(__FUNCTION__ " - port %d", port->number); + + usb_serial_debug_data (__FILE__, __FUNCTION__, count, buf); + + while (count > 0) { + + /* try to find a free urb in our list of them */ + urb = NULL; + + spin_lock_irqsave (&write_urb_pool_lock, flags); + + for (i = 0; i < NUM_URBS; ++i) { + if (write_urb_pool[i]->status != -EINPROGRESS) { + urb = write_urb_pool[i]; + break; + } + } + + spin_unlock_irqrestore (&write_urb_pool_lock, flags); + + if (urb == NULL) { + dbg (__FUNCTION__ " - no more free urbs"); + goto exit; + } + + if (urb->transfer_buffer == NULL) { + urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (urb->transfer_buffer == NULL) { + err(__FUNCTION__" no more kernel memory..."); + goto exit; + } + } + + transfer_size = MIN (count, URB_TRANSFER_BUFFER_SIZE); + + if (from_user) { + copy_from_user (urb->transfer_buffer, current_position, transfer_size); + } else { + memcpy (urb->transfer_buffer, current_position, transfer_size); + } + + count = (count > port->bulk_out_size) ? port->bulk_out_size : count; + + /* build up our urb */ + FILL_BULK_URB ( + urb, + serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + urb->transfer_buffer, + transfer_size, + empeg_write_bulk_callback, + port); + + urb->transfer_flags |= USB_QUEUE_BULK; + + /* send it down the pipe */ + status = usb_submit_urb(urb); + if (status) + dbg(__FUNCTION__ " - usb_submit_urb(write bulk) failed with status = %d", status); + + current_position += transfer_size; + bytes_sent += transfer_size; + count -= transfer_size; + bytes_out += transfer_size; + + } + +exit: + return bytes_sent; + +} + + +static void empeg_write_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero write bulk status received: %d", urb->status); + return; + } + + queue_task(&port->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); + + return; + +} + + +static void empeg_read_bulk_callback (struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial *serial = get_usb_serial (port, __FUNCTION__); + struct tty_struct *tty; + unsigned char *data = urb->transfer_buffer; + int i; + int result; + + if (port_paranoia_check (port, __FUNCTION__)) + return; + + dbg(__FUNCTION__ " - port %d", port->number); + + if (!serial) { + dbg(__FUNCTION__ " - bad serial pointer, exiting"); + return; + } + + if (urb->status) { + dbg(__FUNCTION__ " - nonzero read bulk status received: %d", urb->status); + return; + } + + usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data); + + tty = port->tty; + + if (urb->actual_length) { + for (i = 0; i < urb->actual_length ; ++i) { + /* gb - 2000/11/13 + * If we insert too many characters we'll overflow the buffer. + * This means we'll lose bytes - Decidedly bad. + */ + if(tty->flip.count >= TTY_FLIPBUF_SIZE) { + tty_flip_buffer_push(tty); + } + /* gb - 2000/11/13 + * This doesn't push the data through unless tty->low_latency is set. + */ + tty_insert_flip_char(tty, data[i], 0); + } + /* gb - 2000/11/13 + * Goes straight through instead of scheduling - if tty->low_latency is set. + */ + tty_flip_buffer_push(tty); + bytes_in += urb->actual_length; + } + + /* Continue trying to always read */ + port->read_urb->transfer_flags |= USB_QUEUE_BULK; + result = usb_submit_urb(port->read_urb); + + if (result) + err(__FUNCTION__ " - failed resubmitting read urb, error %d", result); + + return; + +} + + +static void empeg_throttle (struct usb_serial_port *port) +{ + unsigned long flags; + + dbg(__FUNCTION__ " - port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + usb_unlink_urb (port->read_urb); + + spin_unlock_irqrestore (&port->port_lock, flags); + + return; + +} + + +static void empeg_unthrottle (struct usb_serial_port *port) +{ + unsigned long flags; + int result; + + dbg(__FUNCTION__ " - port %d", port->number); + + spin_lock_irqsave (&port->port_lock, flags); + + port->read_urb->dev = port->serial->dev; + + result = usb_submit_urb(port->read_urb); + + if (result) + err(__FUNCTION__ " - failed submitting read urb, error %d", result); + + spin_unlock_irqrestore (&port->port_lock, flags); + + return; + +} + + +static int empeg_startup (struct usb_serial *serial) +{ + + dbg(__FUNCTION__); + + dbg(__FUNCTION__ " - Set config to 1"); + usb_set_configuration (serial->dev, 1); + + /* continue on with initialization */ + return 0; + +} + + +static void empeg_shutdown (struct usb_serial *serial) +{ + int i; + + dbg (__FUNCTION__); + + /* stop reads and writes on all ports */ + for (i=0; i < serial->num_ports; ++i) { + while (serial->port[i].open_count > 0) { + empeg_close (&serial->port[i], NULL); + } + } + +} + + +static int empeg_ioctl (struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg) +{ + dbg(__FUNCTION__ " - port %d, cmd 0x%.4x", port->number, cmd); + + return -ENOIOCTLCMD; +} + + +/* This function is all nice and good, but we don't change anything based on it :) */ +static void empeg_set_termios (struct usb_serial_port *port, struct termios *old_termios) +{ + unsigned int cflag = port->tty->termios->c_cflag; + + dbg(__FUNCTION__ " - port %d", port->number); + + /* check that they really want us to change something */ + if (old_termios) { + if ((cflag == old_termios->c_cflag) && + (RELEVANT_IFLAG(port->tty->termios->c_iflag) == RELEVANT_IFLAG(old_termios->c_iflag))) { + dbg(__FUNCTION__ " - nothing to change..."); + return; + } + } + + if ((!port->tty) || (!port->tty->termios)) { + dbg(__FUNCTION__" - no tty structures"); + return; + } + + /* get the byte size */ + switch (cflag & CSIZE) { + case CS5: dbg(__FUNCTION__ " - data bits = 5"); break; + case CS6: dbg(__FUNCTION__ " - data bits = 6"); break; + case CS7: dbg(__FUNCTION__ " - data bits = 7"); break; + default: + case CS8: dbg(__FUNCTION__ " - data bits = 8"); break; + } + + /* determine the parity */ + if (cflag & PARENB) + if (cflag & PARODD) + dbg(__FUNCTION__ " - parity = odd"); + else + dbg(__FUNCTION__ " - parity = even"); + else + dbg(__FUNCTION__ " - parity = none"); + + /* figure out the stop bits requested */ + if (cflag & CSTOPB) + dbg(__FUNCTION__ " - stop bits = 2"); + else + dbg(__FUNCTION__ " - stop bits = 1"); + + /* figure out the flow control settings */ + if (cflag & CRTSCTS) + dbg(__FUNCTION__ " - RTS/CTS is enabled"); + else + dbg(__FUNCTION__ " - RTS/CTS is disabled"); + + /* determine software flow control */ + if (I_IXOFF(port->tty)) + dbg(__FUNCTION__ " - XON/XOFF is enabled, XON = %2x, XOFF = %2x", START_CHAR(port->tty), STOP_CHAR(port->tty)); + else + dbg(__FUNCTION__ " - XON/XOFF is disabled"); + + /* get the baud rate wanted */ + dbg(__FUNCTION__ " - baud rate = %d", tty_get_baud_rate(port->tty)); + + return; + +} + + +static int __init empeg_init (void) +{ + struct urb *urb; + int i; + + usb_serial_register (&empeg_device); + + /* create our write urb pool and transfer buffers */ + spin_lock_init (&write_urb_pool_lock); + for (i = 0; i < NUM_URBS; ++i) { + urb = usb_alloc_urb(0); + write_urb_pool[i] = urb; + if (urb == NULL) { + err("No more urbs???"); + continue; + } + + urb->transfer_buffer = NULL; + urb->transfer_buffer = kmalloc (URB_TRANSFER_BUFFER_SIZE, GFP_KERNEL); + if (!urb->transfer_buffer) { + err (__FUNCTION__ " - out of memory for urb buffers."); + continue; + } + } + + return 0; + +} + + +static void __exit empeg_exit (void) +{ + int i; + unsigned long flags; + + usb_serial_deregister (&empeg_device); + + spin_lock_irqsave (&write_urb_pool_lock, flags); + + for (i = 0; i < NUM_URBS; ++i) { + if (write_urb_pool[i]) { + /* FIXME - uncomment the following usb_unlink_urb call when + * the host controllers get fixed to set urb->dev = NULL after + * the urb is finished. Otherwise this call oopses. */ + /* usb_unlink_urb(write_urb_pool[i]); */ + if (write_urb_pool[i]->transfer_buffer) + kfree(write_urb_pool[i]->transfer_buffer); + usb_free_urb (write_urb_pool[i]); + } + } + + spin_unlock_irqrestore (&write_urb_pool_lock, flags); + +} + + +module_init(empeg_init); +module_exit(empeg_exit); + +MODULE_AUTHOR("Gary Brubaker "); +MODULE_DESCRIPTION("USB Empeg Mark I/II Driver"); diff --git a/drivers/video/mdacon.c b/drivers/video/mdacon.c index e8ac09004f20..51aa6a9feb5c 100644 --- a/drivers/video/mdacon.c +++ b/drivers/video/mdacon.c @@ -75,14 +75,10 @@ static int mda_last_vc = 16; static struct vc_data *mda_display_fg = NULL; -#ifdef MODULE_PARM MODULE_PARM(mda_first_vc, "1-255i"); MODULE_PARM(mda_last_vc, "1-255i"); -#endif - -/* MDA register values - */ +/* MDA register values */ #define MDA_CURSOR_BLINKING 0x00 #define MDA_CURSOR_OFF 0x20 @@ -200,11 +196,7 @@ __initfunc(void mdacon_setup(char *str, int *ints)) } #endif -#ifdef MODULE -static int mda_detect(void) -#else __initfunc(static int mda_detect(void)) -#endif { int count=0; u16 *p, p_save; @@ -287,11 +279,7 @@ __initfunc(static int mda_detect(void)) return 1; } -#ifdef MODULE -static void mda_initialize(void) -#else __initfunc(static void mda_initialize(void)) -#endif { write_mda_b(97, 0x00); /* horizontal total */ write_mda_b(80, 0x01); /* horizontal displayed */ @@ -316,11 +304,7 @@ __initfunc(static void mda_initialize(void)) outb_p(0x00, mda_gfx_port); } -#ifdef MODULE -static const char *mdacon_startup(void) -#else __initfunc(static const char *mdacon_startup(void)) -#endif { mda_num_columns = 80; mda_num_lines = 25; @@ -606,11 +590,7 @@ struct consw mda_con = { mdacon_invert_region, /* con_invert_region */ }; -#ifdef MODULE -void mda_console_init(void) -#else __initfunc(void mda_console_init(void)) -#endif { if (mda_first_vc > mda_last_vc) return; diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 84e9ac54c9f9..3a25b167a1db 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1056,7 +1056,7 @@ static int writenote(struct memelfnote *men, struct file *file) #undef DUMP_SEEK #define DUMP_WRITE(addr, nr) \ - if (!dump_write(file, (addr), (nr))) \ + if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ goto close_coredump; #define DUMP_SEEK(off) \ if (!dump_seek(file, (off))) \ @@ -1078,7 +1078,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs) char corefile[6+sizeof(current->comm)]; int segs; int i; - size_t size; + size_t size = 0; struct vm_area_struct *vma; struct elfhdr elf; off_t offset = 0, dataoff; @@ -1099,24 +1099,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs) MOD_INC_USE_COUNT; #endif - /* Count what's needed to dump, up to the limit of coredump size */ - segs = 0; - size = 0; - for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { - if (maydump(vma)) - { - unsigned long sz = vma->vm_end-vma->vm_start; - - if (size+sz >= limit) - break; - else - size += sz; - } + segs = current->mm->map_count; - segs++; - } #ifdef DEBUG - printk("elf_core_dump: %d segs taking %d bytes\n", segs, size); + printk("elf_core_dump: %d segs %lu limit\n", segs, limit); #endif /* Set up header */ @@ -1294,13 +1280,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs) dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE); /* Write program headers for segments dump */ - for(vma = current->mm->mmap, i = 0; - i < segs && vma != NULL; vma = vma->vm_next) { + for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { struct elf_phdr phdr; size_t sz; - i++; - sz = vma->vm_end - vma->vm_start; phdr.p_type = PT_LOAD; @@ -1326,19 +1309,36 @@ static int elf_core_dump(long signr, struct pt_regs * regs) DUMP_SEEK(dataoff); - for(i = 0, vma = current->mm->mmap; - i < segs && vma != NULL; - vma = vma->vm_next) { - unsigned long addr = vma->vm_start; - unsigned long len = vma->vm_end - vma->vm_start; + for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) { + unsigned long addr; - i++; if (!maydump(vma)) continue; #ifdef DEBUG printk("elf_core_dump: writing %08lx %lx\n", addr, len); #endif - DUMP_WRITE((void *)addr, len); + for (addr = vma->vm_start; + addr < vma->vm_end; + addr += PAGE_SIZE) { + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + + pgd = pgd_offset(vma->vm_mm, addr); + pmd = pmd_alloc(pgd, addr); + + if (!pmd) + goto end_coredump; + pte = pte_alloc(pmd, addr); + if (!pte) + goto end_coredump; + if (!pte_present(*pte) && + pte_none(*pte)) { + DUMP_SEEK (file->f_pos + PAGE_SIZE); + } else { + DUMP_WRITE((void*)addr, PAGE_SIZE); + } + } } if ((off_t) file->f_pos != offset) { diff --git a/fs/fat/misc.c b/fs/fat/misc.c index a99d13577d60..a79c34cef74c 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -2,6 +2,8 @@ * linux/fs/fat/misc.c * * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) */ #include @@ -288,7 +290,9 @@ int date_dos2unix(unsigned short time,unsigned short date) { int month,year,secs; - month = ((date >> 5) & 15)-1; + /* first subtract and mask after that... Otherwise, if + date == 0, bad things happen */ + month = ((date >> 5) - 1) & 15; year = date >> 9; secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && @@ -310,6 +314,10 @@ void fat_date_unix2dos(int unix_date,unsigned short *time, unix_date -= sys_tz.tz_minuteswest*60; if (sys_tz.tz_dsttime) unix_date += 3600; + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (unix_date < 315532800) + unix_date = 315532800; + *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ (((unix_date/3600) % 24) << 11); day = unix_date/86400-3652; diff --git a/fs/smbfs/ChangeLog b/fs/smbfs/ChangeLog index da221ab2e977..ae9c1c4cc270 100644 --- a/fs/smbfs/ChangeLog +++ b/fs/smbfs/ChangeLog @@ -1,5 +1,10 @@ ChangeLog for smbfs. +2000-11-22 Igor Zhbanov + + * proc.c: fixed date_unix2dos for dates earlier than 01/01/1980 + and date_dos2unix for date==0 + 2000-11-04 Urban Widmark * proc.c, sock.c: adjust max parameters & max data to follow max_xmit @@ -41,7 +46,7 @@ ChangeLog for smbfs. * proc.c: removed support for old protocol levels. It didn't work anyway and was cluttering things up a lot. -2000-01-?? cpg@aladdin.de +2000-01-03 Christian Groessler * proc.c: added posix semantics for unlink diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index 2b3afb65bfd8..ba511314494a 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c @@ -280,7 +280,9 @@ date_dos2unix(struct smb_sb_info *server, __u16 date, __u16 time) int month, year; time_t secs; - month = ((date >> 5) & 15) - 1; + /* first subtract and mask after that... Otherwise, if + date == 0, bad things happen */ + month = ((date >> 5) - 1) & 15; year = date >> 9; secs = (time & 31) * 2 + 60 * ((time >> 5) & 63) + (time >> 11) * 3600 + 86400 * ((date & 31) - 1 + day_n[month] + (year / 4) + year * 365 - ((year & 3) == 0 && @@ -299,6 +301,11 @@ date_unix2dos(struct smb_sb_info *server, int day, year, nl_day, month; unix_date = utc2local(server, unix_date); + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (unix_date < 315532800) + unix_date = 315532800; + *time = (unix_date % 60) / 2 + (((unix_date / 60) % 60) << 5) + (((unix_date / 3600) % 24) << 11); diff --git a/include/asm-i386/bugs.h b/include/asm-i386/bugs.h index 8ed3a93423c8..14c0b22f2679 100644 --- a/include/asm-i386/bugs.h +++ b/include/asm-i386/bugs.h @@ -188,6 +188,7 @@ __asm__(".align 4\nvide: ret"); __initfunc(static void check_amd_k6(void)) { if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && + boot_cpu_data.x86 == 5 && boot_cpu_data.x86_model == 6 && boot_cpu_data.x86_mask == 1) { diff --git a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h index 5c4bef97a3a4..8a6adceca4f2 100644 --- a/include/asm-i386/uaccess.h +++ b/include/asm-i386/uaccess.h @@ -510,20 +510,20 @@ do { \ " popl %0\n" \ " shl $2,%0\n" \ " addl $3,%0\n" \ - " jmp 2b\n" \ + " jmp 3b\n" \ "5: pushl %%eax\n" \ " xorl %%eax,%%eax\n" \ " stosw\n" \ " stosb\n" \ " popl %%eax\n" \ " addl $3,%0\n" \ - " jmp 2b\n" \ + " jmp 3b\n" \ "6: pushl %%eax\n" \ " xorl %%eax,%%eax\n" \ " stosb\n" \ " popl %%eax\n" \ " incl %0\n" \ - " jmp 2b\n" \ + " jmp 3b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ " .align 4\n" \ diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index 3e3edd8b13b6..8b0180c063fe 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h @@ -5,6 +5,7 @@ #include #include #include +#include struct irqaction { void (*handler)(int, void *, struct pt_regs *); diff --git a/include/linux/pci.h b/include/linux/pci.h index 79339f33b481..ff7655468b77 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -307,6 +307,15 @@ * (and according to card ID within vendor). Send all updates to * . */ +#define PCI_VENDOR_ID_DYNALINK 0x0675 +#define PCI_DEVICE_ID_DYNALINK_IS64PH 0x1702 + +#define PCI_VENDOR_ID_BERKOM 0x0871 +#define PCI_DEVICE_ID_BERKOM_A1T 0xFFA1 +#define PCI_DEVICE_ID_BERKOM_T_CONCEPT 0xFFA2 +#define PCI_DEVICE_ID_BERKOM_A4T 0xFFA4 +#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO 0xFFA8 + #define PCI_VENDOR_ID_COMPAQ 0x0e11 #define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508 #define PCI_DEVICE_ID_COMPAQ_1280 0x3033 @@ -477,6 +486,10 @@ #define PCI_DEVICE_ID_CT_65554 0x00e4 #define PCI_DEVICE_ID_CT_65555 0x00e5 +#define PCI_DEVICE_ID_PLX_R685 0x1030 +#define PCI_DEVICE_ID_PLX_DJINN_ITOO 0x1151 +#define PCI_DEVICE_ID_PLX_R753 0x1152 + #define PCI_VENDOR_ID_MIRO 0x1031 #define PCI_DEVICE_ID_MIRO_36050 0x5601 @@ -530,6 +543,10 @@ #define PCI_DEVICE_ID_OPTI_82C861 0xc861 #define PCI_DEVICE_ID_OPTI_82C825 0xd568 +#define PCI_VENDOR_ID_ELSA 0x1048 +#define PCI_DEVICE_ID_ELSA_MICROLINK 0x1000 +#define PCI_DEVICE_ID_ELSA_QS3000 0x3000 + #define PCI_VENDOR_ID_SGS 0x104a #define PCI_DEVICE_ID_SGS_2000 0x0008 #define PCI_DEVICE_ID_SGS_1764 0x0009 @@ -554,6 +571,10 @@ /* Winbond have two vendor IDs! See 0x10ad as well */ #define PCI_VENDOR_ID_WINBOND2 0x1050 #define PCI_DEVICE_ID_WINBOND2_89C940 0x0940 +#define PCI_DEVICE_ID_WINBOND2_6692 0x6692 + +#define PCI_VENDOR_ID_ANIGMA 0x1051 +#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100 #define PCI_VENDOR_ID_MOTOROLA 0x1057 #define PCI_VENDOR_ID_MOTOROLA_OOPS 0x1507 @@ -873,6 +894,17 @@ #define PCI_DEVICE_ID_PHILIPS_SAA7145 0x7145 #define PCI_DEVICE_ID_PHILIPS_SAA7146 0x7146 +#define PCI_VENDOR_ID_EICON 0x1133 +#define PCI_DEVICE_ID_EICON_DIVA20PRO 0xe001 +#define PCI_DEVICE_ID_EICON_DIVA20 0xe002 +#define PCI_DEVICE_ID_EICON_DIVA20PRO_U 0xe003 +#define PCI_DEVICE_ID_EICON_DIVA20_U 0xe004 +#define PCI_DEVICE_ID_EICON_DIVA201 0xe005 +#define PCI_DEVICE_ID_EICON_MAESTRA 0xe010 +#define PCI_DEVICE_ID_EICON_MAESTRAQ 0xe012 +#define PCI_DEVICE_ID_EICON_MAESTRAQ_U 0xe013 +#define PCI_DEVICE_ID_EICON_MAESTRAP 0xe014 + #define PCI_VENDOR_ID_CYCLONE 0x113c #define PCI_DEVICE_ID_CYCLONE_SDK 0x0001 @@ -899,6 +931,10 @@ #define PCI_DEVICE_ID_DIGI_XRJ 0x0009 #define PCI_DEVICE_ID_DIGI_EPCJ 0x000a #define PCI_DEVICE_ID_DIGI_XR_920 0x0027 +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E 0x0070 +#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071 +#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072 +#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073 #define PCI_VENDOR_ID_MUTECH 0x1159 #define PCI_DEVICE_ID_MUTECH_MV1000 0x0001 @@ -1023,6 +1059,9 @@ #define PCI_VENDOR_ID_AVM 0x1244 #define PCI_DEVICE_ID_AVM_A1 0x0a00 +#define PCI_DEVICE_ID_AVM_B1 0x0700 +#define PCI_DEVICE_ID_AVM_C4 0x0800 +#define PCI_DEVICE_ID_AVM_T1 0x1200 #define PCI_VENDOR_ID_DIPIX 0x1246 @@ -1039,6 +1078,7 @@ #define PCI_DEVICE_ID_OPTIBASE_VQUEST 0x2130 #define PCI_VENDOR_ID_SATSAGEM 0x1267 +#define PCI_DEVICE_ID_SATSAGEM_NICCY 0x1016 #define PCI_DEVICE_ID_SATSAGEM_PCR2101 0x5352 #define PCI_DEVICE_ID_SATSAGEM_TELSATTURBO 0x5a4b @@ -1082,9 +1122,32 @@ #define PCI_DEVICE_ID_SIIG_2S1P_20x_650 0x2061 #define PCI_DEVICE_ID_SIIG_2S1P_20x_850 0x2062 +#define PCI_VENDOR_ID_HYPERCOPE 0x1365 +#define PCI_DEVICE_ID_HYPERCOPE_PLX 0x9050 +#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO 0x0104 +#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO 0x0106 +#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO 0x0107 +#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2 0x0108 +#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS 0x0109 + #define PCI_VENDOR_ID_NETGEAR 0x1385 #define PCI_DEVICE_ID_NETGEAR_GA620 0x620a +#define PCI_VENDOR_ID_CCD 0x1397 +#define PCI_DEVICE_ID_CCD_2BD0 0x2BD0 +#define PCI_DEVICE_ID_CCD_B000 0xB000 +#define PCI_DEVICE_ID_CCD_B006 0xB006 +#define PCI_DEVICE_ID_CCD_B007 0xB007 +#define PCI_DEVICE_ID_CCD_B008 0xB008 +#define PCI_DEVICE_ID_CCD_B009 0xB009 +#define PCI_DEVICE_ID_CCD_B00A 0xB00A +#define PCI_DEVICE_ID_CCD_B00B 0xB00B +#define PCI_DEVICE_ID_CCD_B00C 0xB00C +#define PCI_DEVICE_ID_CCD_B100 0xB100 + +#define PCI_VENDOR_ID_ABOCOM 0x13D1 +#define PCI_DEVICE_ID_ABOCOM_2BD1 0x2BD1 + #define PCI_VENDOR_ID_LAVA 0x1407 #define PCI_DEVICE_ID_LAVA_PARALLEL 0x8000 #define PCI_DEVICE_ID_LAVA_DUAL_PAR_A 0x8002 /* The Lava Dual Parallel is */ @@ -1102,6 +1165,9 @@ #define PCI_VENDOR_ID_AFAVLAB 0x14db #define PCI_DEVICE_ID_AFAVLAB_TK9902 0x2120 +#define PCI_VENDOR_ID_ZOLTRIX 0x15b0 +#define PCI_DEVICE_ID_ZOLTRIX_2BD0 0x2BD0 + #define PCI_VENDOR_ID_SYMPHONY 0x1c1c #define PCI_DEVICE_ID_SYMPHONY_101 0x0001 @@ -1258,6 +1324,7 @@ #define PCI_VENDOR_ID_TIGERJET 0xe159 #define PCI_DEVICE_ID_TIGERJET_300 0x0001 +#define PCI_DEVICE_ID_TIGERJET_100 0x0002 #define PCI_VENDOR_ID_ARK 0xedd8 #define PCI_DEVICE_ID_ARK_STING 0xa091 diff --git a/include/linux/synclink.h b/include/linux/synclink.h index 450341b74628..21e8a6f6473f 100644 --- a/include/linux/synclink.h +++ b/include/linux/synclink.h @@ -1,9 +1,9 @@ /* * SyncLink Multiprotocol Serial Adapter Driver * - * ==FILEDATE 19990810== + * $Id: synclink.h,v 2.2 2000/11/08 17:08:30 paul Exp $ * - * Copyright (C) 1998 by Microgate Corporation + * Copyright (C) 1998-2000 by Microgate Corporation * * Redistribution of this file is permitted under * the terms of the GNU Public License (GPL) @@ -11,6 +11,7 @@ #ifndef _SYNCLINK_H_ #define _SYNCLINK_H_ +#define SYNCLINK_H_VERSION 2.2 #define BOOLEAN int #define TRUE 1 diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 868f812acbfb..c552ff21b124 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -63,7 +63,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 9 +#define WIRELESS_EXT 10 /* * Changes : @@ -104,26 +104,33 @@ * - Change encoding to support larger tokens (>64 bits) * - Updated iw_params (disable, flags) and use it for NWID * - Extracted iw_point from iwreq for clarity + * + * V9 to V10 + * --------- + * - Add PM capability to range structure + * - Add PM modifier : MAX/MIN/RELATIVE + * - Add encoding option : IW_ENCODE_NOKEY + * - Add TxPower ioctls (work like TxRate) */ /* -------------------------- IOCTL LIST -------------------------- */ /* Basic operations */ -#define SIOCSIWNAME 0x8B00 /* Unused ??? */ -#define SIOCGIWNAME 0x8B01 /* get name */ +#define SIOCSIWNAME 0x8B00 /* Unused */ +#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */ #define SIOCGIWNWID 0x8B03 /* get network id */ -#define SIOCSIWFREQ 0x8B04 /* set channel/frequency */ -#define SIOCGIWFREQ 0x8B05 /* get channel/frequency */ +#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ +#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ #define SIOCSIWMODE 0x8B06 /* set operation mode */ #define SIOCGIWMODE 0x8B07 /* get operation mode */ -#define SIOCSIWSENS 0x8B08 /* set sensitivity */ -#define SIOCGIWSENS 0x8B09 /* get sensitivity */ +#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ +#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ /* Informative stuff */ -#define SIOCSIWRANGE 0x8B0A /* Unused ??? */ +#define SIOCSIWRANGE 0x8B0A /* Unused */ #define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ -#define SIOCSIWPRIV 0x8B0C /* Unused ??? */ +#define SIOCSIWPRIV 0x8B0C /* Unused */ #define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ /* Mobile IP support */ @@ -153,6 +160,8 @@ #define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ #define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ +#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ +#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ @@ -205,6 +214,9 @@ /* Maximum bit rates in the range struct */ #define IW_MAX_BITRATES 8 +/* Maximum tx powers in the range struct */ +#define IW_MAX_TXPOWER 8 + /* Maximum of address that you may set with SPY */ #define IW_MAX_SPY 8 @@ -232,11 +244,13 @@ /* Flags for encoding (along with the token) */ #define IW_ENCODE_INDEX 0x00FF /* Token index (if needed) */ -#define IW_ENCODE_FLAGS 0xF000 /* Flags defined below */ +#define IW_ENCODE_FLAGS 0xFF00 /* Flags defined below */ +#define IW_ENCODE_MODE 0xF000 /* Modes defined below */ #define IW_ENCODE_DISABLED 0x8000 /* Encoding disabled */ #define IW_ENCODE_ENABLED 0x0000 /* Encoding enabled */ #define IW_ENCODE_RESTRICTED 0x4000 /* Refuse non-encoded packets */ #define IW_ENCODE_OPEN 0x2000 /* Accept non-encoded packets */ +#define IW_ENCODE_NOKEY 0x0800 /* Key is write only, so not present */ /* Power management flags available (along with the value, if any) */ #define IW_POWER_ON 0x0000 /* No details... */ @@ -249,6 +263,14 @@ #define IW_POWER_ALL_R 0x0300 /* Receive all messages though PM */ #define IW_POWER_FORCE_S 0x0400 /* Force PM procedure for sending unicast */ #define IW_POWER_REPEATER 0x0800 /* Repeat broadcast messages in PM period */ +#define IW_POWER_MODIFIER 0x000F /* Modify a parameter */ +#define IW_POWER_MIN 0x0001 /* Value is a minimum */ +#define IW_POWER_MAX 0x0002 /* Value is a maximum */ +#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ + +/* Transmit Power flags available */ +#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ +#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ /****************************** TYPES ******************************/ @@ -359,6 +381,7 @@ struct iwreq struct iw_param sens; /* signal level threshold */ struct iw_param bitrate; /* default bit rate */ + struct iw_param txpower; /* default transmit power */ struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ @@ -422,15 +445,23 @@ struct iw_range __s32 max_frag; /* Maximal frag threshold */ /* Power Management duration & timeout */ - __s32 min_pmd; /* Minimal PM duration */ - __s32 max_pmd; /* Maximal PM duration */ + __s32 min_pmp; /* Minimal PM period */ + __s32 max_pmp; /* Maximal PM period */ __s32 min_pmt; /* Minimal PM timeout */ __s32 max_pmt; /* Maximal PM timeout */ + __u16 pmp_flags; /* How to decode max/min PM period */ + __u16 pmt_flags; /* How to decode max/min PM timeout */ + __u16 pm_capa; /* What PM options are supported */ /* Encoder stuff */ __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ __u8 num_encoding_sizes; /* Number of entry in the list */ __u8 max_encoding_tokens; /* Max number of tokens */ + + /* Transmit power */ + __u16 txpower_capa; /* What options are supported */ + __u8 num_txpower; /* Number of entries in the list */ + __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ }; /* diff --git a/ipc/shm.c b/ipc/shm.c index 4a33fa8fe850..b978f2a207f1 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -340,6 +340,8 @@ asmlinkage int sys_shmctl (int shmid, int cmd, struct shmid_ds *buf) shp->u.shm_perm.mode |= SHM_DEST; if (shp->u.shm_nattch <= 0) killseg (id); + /* Do not find it any more */ + shp->u.shm_perm.key = IPC_PRIVATE; break; } err = -EPERM; diff --git a/scripts/Configure b/scripts/Configure index eec81bbbee05..1212d7526f61 100644 --- a/scripts/Configure +++ b/scripts/Configure @@ -422,7 +422,18 @@ function define_string () { function string () { old=$(eval echo "\${$2}") def=${old:-$3} - readln "$1 ($2) [$def] " "$def" "$old" + while :; do + if [ "$old" = "?" ]; then + readln "$1 ($2) [$def] " "$def" "" + else + readln "$1 ($2) [$def] " "$def" "$old" + fi + if [ "$ans" = "?" ]; then + help "$2" + else + break + fi + done define_string "$2" "$ans" } #