D: Selection mechanism
N: Andre Hedrick
+E: andre@linux-ide.org
E: andre@suse.com
D: Random SMP kernel hacker...
D: Uniform Multi-Platform E-IDE driver
-D: AEC6210UF Ultra33
-D: Aladdin 1533/1543(C) chipset
-D: Active-Chipset maddness..........
-D: HighPoint HPT343/5 Ultra/33 & HPT366 Ultra/66 chipsets
-D: Intel PIIX chipset
-D: Promise PDC20246/20247 & PDC20262 chipsets
-D: SiS5513 Ultra/66/33 chipsets
-D: VIA 82C586/596/686 chipsets
+D: Active-ATA-Chipset maddness..........
+D: Ultra DMA 66/33
+D: ATA-Smart Kernel Daemon
S: 580 Second Street, Suite 2
S: Oakland, CA
S: USA
W: http://linux.powertweak.com
D: Moved PCI bridge tuning to userspace (Powertweak).
D: Centaur/IDT Winchip/Winchip 2 tweaks.
+D: AFFS fixes for 2.3.x
D: Misc clean ups and other random hacking.
S: 28, Laura Street,
S: Treforest, Pontypridd,
- Bash 1.14.7 ; bash -version
- Ncpfs 2.2.0 ; ncpmount -v
- Pcmcia-cs 3.1.2 ; cardmgr -V
-- PPP 2.3.11 ; pppd --version
+- PPP 2.4.0b1 ; pppd --version
- Util-linux 2.9i ; chsh -v
- isdn4k-utils v3.1beta7 ; isdnctrl 2>&1|grep version
PPP
===
- Due to changes in the PPP driver and routing code, those of you
+ The PPP driver has been restructured to support multilink and
+to enable it to operate over diverse kinds of media. Those of you
using PPP networking will need to upgrade your pppd to at least
-version 2.3.11. See ftp://cs.anu.edu.au/pub/software/ppp/ for newest
-versions.
+version 2.4.0b1. See ftp://linuxcare.com.au/pub/ppp/ for the latest
+version.
- You must make sure that the special device file /dev/ppp exists.
-It can be made by executing this command as root:
+ If you are not using devfs, you must make sure that the special
+device file /dev/ppp exists. It can be made by executing this command
+as root:
mknod /dev/ppp c 108 0
If you have built ppp support as modules, you should put the lines
-below in your /etc/modules.conf file. I assume you want asynchronous
-ppp; replace ppp_async by ppp_synctty if you want synchronous ppp.
+below in your /etc/modules.conf file.
- alias char-major-108 ppp_generic
- alias tty-ldisc-3 ppp_async
+ alias char-major-108 ppp_generic
+ alias /dev/ppp ppp_generic
+ alias tty-ldisc-3 ppp_async
+ alias tty-ldisc-14 ppp_synctty
+ alias ppp-compress-21 bsd_comp
+ alias ppp-compress-24 ppp_deflate
+ alias ppp-compress-26 ppp_deflate
+
+If you are using devfsd and you have ppp_generic as a module, put the
+following line in your /etc/devfsd.conf:
+
+ LOOKUP ppp MODLOAD
iBCS
====
PPP
===
-The 2.3.11 release:
-ftp://cs.anu.edu.au/pub/software/ppp/ppp-2.3.11.tar.gz
+The 2.4.0b1 release:
+ftp://linuxcare.com.au/pub/ppp/ppp-2.4.0b1.tar.gz
IP Chains
=========
Please read the comments at the top of drivers/scsi/3w-xxxx.c
-AEC6210 chipset support
-CONFIG_BLK_DEV_AEC6210
+AEC62XX chipset support
+CONFIG_BLK_DEV_AEC62XX
This driver adds up to 4 more EIDE devices sharing a single
interrupt. This add-on card is a bootable PCI UDMA controller. In
order to get this card to initialize correctly in some cases, you
should say Y here, and preferably also to "Use DMA by default when
available".
- Please read the comments at the top of drivers/ide/aec6210.c If
- you say Y here, then say Y to "Use DMA by default when available" as
+ The ATP850U/UF is an UltraDMA 33 chipset base.
+ The ATP860 is an UltraDMA 66 chipset base.
+ The ATP860M(acintosh) version is an UltraDMA 66 chipset base.
+
+ Please read the comments at the top of drivers/ide/aec62xx.c
+ If you say Y here, then say Y to "Use DMA by default when available" as
well.
-AEC6210 Tuning support (WIP)
-CONFIG_AEC6210_TUNING
- Please read the comments at the top of drivers/ide/aec6210.c
+AEC62XX Tuning support (WIP)
+CONFIG_AEC62XX_TUNING
+ Please read the comments at the top of drivers/ide/aec62xx.c
If unsure, say N.
ALI M15x3 chipset support
If unsure, say N.
+VIA82CXXX Tuning support (WIP)
+CONFIG_VIA82CXXX_TUNING
+ Please read the comments at the top of drivers/ide/via82cxxx.c
+
+ If unsure, say N.
+
Other IDE chipset support
CONFIG_IDE_CHIPSETS
Say Y here if you want to include enhanced support for various IDE
say N here.
FORE Systems 200E-series
-CONFIG_ATM_FORE200E
+CONFIG_ATM_FORE200E_MAYBE
This is a driver for the FORE Systems 200E-series ATM adapter
cards. It simultaneously supports PCA-200E and SBA-200E models
on PCI and SBUS hosts. Say Y (or M to compile as a module
named fore_200e.o) here if you have one of these ATM adapters.
+ Note that the driver will actually be compiled only if you
+ additionally enable the support for PCA-200E and/or SBA-200E
+ cards.
+
See the file Documentation/networking/fore200e.txt for further
details.
-Fore PCA-200E/SBA-200E ATM NIC Firmware Copyright Notice
---------------------------------------------------------
+FORE Systems PCA-200E/SBA-200E ATM NIC driver
+---------------------------------------------
+
+This driver adds support for the FORE Systems 200E-series ATM adapters
+to the Linux operating system. It is based on the earlier PCA-200E driver
+written by Uwe Dannowski.
+
+The driver simultaneously supports PCA-200E and SBA-200E adapters on
+i386, alpha (untested), powerpc, sparc and sparc64 archs.
+
+The intent is to enable the use of different models of FORE adapters at the
+same time, by hosts that have several bus interfaces (such as PCI+SBUS,
+PCI+MCA or PCI+EISA).
+
+Only PCI and SBUS devices are currently supported by the driver, but support
+for other bus interfaces such as EISA should not be too hard to add (this may
+be more tricky for the MCA bus, though, as FORE made some MCA-specific
+modifications to the adapter's AALI interface).
+
+
+Firmware Copyright Notice
+-------------------------
Please read the fore200e_firmware_copyright file present
in the linux/drivers/atm directory for details and restrictions.
uploaded to the ATM adapters at system boot time or at module loading time.
The supplied firmware images should work with all adapters.
-However, if you encounter problems (firmware doesn't start or the driver
-is unable to read PROM data), you may consider trying another firmware
+However, if you encounter problems (the firmware doesn't start or the driver
+is unable to read the PROM data), you may consider trying another firmware
version. Alternative binary firmware images can be found somewhere on the
-ForeThough CD-ROM supplied with your adapter by FORE Systems.
+ForeThought CD-ROM supplied with your adapter by FORE Systems.
You can also get the latest firmware images from FORE Systems at
http://www.fore.com. Register TACTics Online and go to
the 'software updates' pages. The firmware binaries are part of
-the various ForeThough software distributions.
+the various ForeThought software distributions.
Notice that different versions of the PCA-200E firmware exist, depending
on the endianess of the host architecture. The driver is shipped with
both little and big endian PCA firmware images.
Name and location of the new firmware images can be set at kernel
-configuration time.
-
-
-Driver Rebuilding
------------------
+configuration time:
1. Copy the new firmware binary files (with .bin, .bin1 or .bin2 suffix)
to some directory, such as linux/drivers/atm.
2. Reconfigure your kernel to set the new firmware name and location.
Expected pathnames are absolute or relative to the drivers/atm directory.
-3. Delete the files drivers/atm/fore200e_pca_fw.[co] and/or fore200e_sba_fw.[co]
- to ensure that the new firmware will be used when rebuilding the kernel or
- the module.
-
-4. Rebuild and re-install your kernel or your module.
+3. Rebuild and re-install your kernel or your module.
Feedback
Feedback is welcome. Please send success stories/bug reports/
patches/improvement/comments/flames to <lizzi@cnam.fr>.
-
Version history
===============
+0.9.4.3 (April 14, 2000):
+* mod_timer fix (Hal Murray)
+* PNIC2 resusitation (Chris Smith)
+
0.9.4.2 (March 21, 2000):
* Fix 21041 CSR7, CSR13/14/15 handling
* Merge some PCI ids from tulip 0.91x
IDE DRIVER [GENERAL]
P: Andre Hedrick
+M: andre@linux-ide.org
M: andre@suse.com
L: linux-kernel@vger.rutgers.edu
-W: http://linux.kernel.org/pub/linux/kernel/people/hedrick/
+W: http://www.kernel.org/pub/linux/kernel/people/hedrick/
+W: http://www.linux-ide.org/
S: Supported
IDE/ATAPI CDROM DRIVER
MAESTRO PCI SOUND DRIVER
P: Zach Brown
-M: zab@redhat.com
-W: http://people.redhat.com/zab/maestro/
-S: Supported
+M: zab@zabbo.net
+S: Odd Fixes
M68K
P: Jes Sorensen
rm -f drivers/char/conmakehash
rm -f drivers/pci/devlist.h drivers/pci/classlist.h drivers/pci/gen-devlist
rm -f drivers/sound/bin2hex drivers/sound/hex2hex
+ rm -f drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2}
rm -f net/khttpd/make_times_h
rm -f net/khttpd/times.h
rm -f submenu*
rm -f drivers/sound/msndperm.c
rm -f drivers/sound/pndsperm.c
rm -f drivers/sound/pndspini.c
+ rm -f drivers/atm/fore200e_*_fw.c drivers/atm/.fore200e_*.fw
rm -f .version .config* config.in config.old
rm -f scripts/tkparse scripts/kconfig.tk scripts/kconfig.tmp
rm -f scripts/lxdialog/*.o scripts/lxdialog/lxdialog
#ifdef CONFIG_SMP
/* create /proc/irq/1234/smp_affinity */
- entry = create_proc_entry("smp_affinity", 0700, irq_dir[irq]);
+ entry = create_proc_entry("smp_affinity", 0600, irq_dir[irq]);
entry->nlink = 1;
entry->data = (void *)(long)irq;
#ifdef CONFIG_SMP
/* create /proc/irq/prof_cpu_mask */
- entry = create_proc_entry("prof_cpu_mask", 0700, root_irq_dir);
+ entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir);
entry->nlink = 1;
entry->data = (void *)&prof_cpu_mask;
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD7409 is not set
#
# Define implied options from the CPU selection here
#
-if [ "$CONFIG_M386" != "y" ]; then
+if [ "$CONFIG_M386" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 16
+else
define_bool CONFIG_X86_WP_WORKS_OK y
define_bool CONFIG_X86_INVLPG y
define_bool CONFIG_X86_CMPXCHG y
define_bool CONFIG_X86_BSWAP y
define_bool CONFIG_X86_POPAD_OK y
fi
-if [ "$CONFIG_M386" = "y" -o "$CONFIG_M486" = "y" ]; then
- define_int CONFIG_X86_L1_CACHE_BYTES 16
-else
- define_int CONFIG_X86_L1_CACHE_BYTES 32
-fi
-if [ "$CONFIG_M486" = "y" -o "$CONFIG_M586" = "y" ]; then
+if [ "$CONFIG_M486" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 16
define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
fi
-if [ "$CONFIG_M586TSC" = "y" ]; then
+if [ "$CONFIG_M586" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
- define_bool CONFIG_X86_TSC y
fi
-if [ "$CONFIG_MK6" = "y" ]; then
+if [ "$CONFIG_M586TSC" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
+ define_bool CONFIG_X86_USE_STRING_486 y
define_bool CONFIG_X86_ALIGNMENT_16 y
define_bool CONFIG_X86_TSC y
- define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
fi
if [ "$CONFIG_M686" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_PGE y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
fi
+if [ "$CONFIG_MK6" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 32
+ define_bool CONFIG_X86_ALIGNMENT_16 y
+ define_bool CONFIG_X86_TSC y
+ define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+fi
if [ "$CONFIG_MK7" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_BYTES 64
define_bool CONFIG_X86_TSC y
define_bool CONFIG_X86_GOOD_APIC y
define_bool CONFIG_X86_USE_3DNOW y
define_bool CONFIG_X86_PGE y
define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
- define_int CONFIG_X86_L1_CACHE_BYTES 64
fi
tristate '/dev/cpu/microcode - Intel P6 CPU microcode support' CONFIG_MICROCODE
# CONFIG_IDEDMA_PCI_EXPERIMENTAL is not set
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD7409 is not set
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD7409 is not set
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD7409 is not set
panic("Bogon SMP message pass.");
}
-/* Protects counters touched during level14 ticker */
-static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-
-#ifdef CONFIG_PROFILE
-
-/* 32-bit Sparc specific profiling function. */
-static inline void sparc_do_profile(unsigned long pc)
-{
- if(prof_buffer && current->pid) {
- extern int _stext;
-
- pc -= (unsigned long) &_stext;
- pc >>= prof_shift;
-
- spin_lock(&ticker_lock);
- if(pc < prof_len)
- prof_buffer[pc]++;
- else
- prof_buffer[prof_len - 1]++;
- spin_unlock(&ticker_lock);
- }
-}
-
-#endif
-
extern unsigned int prof_multiplier[NR_CPUS];
extern unsigned int prof_counter[NR_CPUS];
extern void update_one_process(struct task_struct *p, unsigned long ticks,
unsigned long user, unsigned long system,
int cpu);
-
+
+extern void sparc_do_profile(unsigned long pc, unsigned long o7);
void smp4d_percpu_timer_interrupt(struct pt_regs *regs)
{
show_leds(cpu);
}
-#ifdef CONFIG_PROFILE
if(!user_mode(regs))
- sparc_do_profile(regs->pc);
-#endif
+ sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+
if(!--prof_counter[cpu]) {
int user = user_mode(regs);
+
+ irq_enter(cpu, 0);
if(current->pid) {
update_one_process(current, 1, user, !user, cpu);
current->need_resched = 1;
}
- spin_lock(&ticker_lock);
if(user) {
if(current->priority < DEF_PRIORITY) {
kstat.cpu_nice++;
kstat.cpu_system++;
kstat.per_cpu_system[cpu]++;
}
- spin_unlock(&ticker_lock);
}
prof_counter[cpu] = prof_multiplier[cpu];
+ irq_exit(cpu, 0);
}
}
ccall_info.processors_out[i] = 1;
}
-/* Protects counters touched during level14 ticker */
-static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
-
-/* 32-bit Sparc specific profiling function. */
-static inline void sparc_do_profile(unsigned long pc)
-{
- if(prof_buffer && current->pid) {
- extern int _stext;
-
- pc -= (unsigned long) &_stext;
- pc >>= prof_shift;
-
- spin_lock(&ticker_lock);
- if(pc < prof_len)
- prof_buffer[pc]++;
- else
- prof_buffer[prof_len - 1]++;
- spin_unlock(&ticker_lock);
- }
-}
-
extern unsigned int prof_multiplier[NR_CPUS];
extern unsigned int prof_counter[NR_CPUS];
unsigned long user, unsigned long system,
int cpu);
+extern void sparc_do_profile(unsigned long pc, unsigned long o7);
+
void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
{
int cpu = smp_processor_id();
clear_profile_irq(mid_xlate[cpu]);
if(!user_mode(regs))
- sparc_do_profile(regs->pc);
+ sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
if(!--prof_counter[cpu]) {
int user = user_mode(regs);
-/* $Id: sys_sunos.c,v 1.120 2000/04/08 08:32:14 davem Exp $
+/* $Id: sys_sunos.c,v 1.121 2000/04/13 00:55:48 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: systbls.S,v 1.96 2000/03/15 02:43:32 davem Exp $
+/* $Id: systbls.S,v 1.97 2000/04/13 00:55:49 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
-/* $Id: time.c,v 1.53 2000/02/09 21:11:04 davem Exp $
+/* $Id: time.c,v 1.54 2000/04/13 08:14:30 anton Exp $
* linux/arch/sparc/kernel/time.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
#endif
+static spinlock_t ticker_lock = SPIN_LOCK_UNLOCKED;
+
+/* 32-bit Sparc specific profiling function. */
+void sparc_do_profile(unsigned long pc, unsigned long o7)
+{
+ if(prof_buffer && current->pid) {
+ extern int _stext;
+ extern int __copy_user_begin, __copy_user_end;
+ extern int __atomic_begin, __atomic_end;
+ extern int __bitops_begin, __bitops_end;
+
+ if ((pc >= (unsigned long) &__copy_user_begin &&
+ pc < (unsigned long) &__copy_user_end) ||
+ (pc >= (unsigned long) &__atomic_begin &&
+ pc < (unsigned long) &__atomic_end) ||
+ (pc >= (unsigned long) &__bitops_begin &&
+ pc < (unsigned long) &__bitops_end))
+ pc = o7;
+
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+
+ spin_lock(&ticker_lock);
+ if(pc < prof_len)
+ prof_buffer[pc]++;
+ else
+ prof_buffer[prof_len - 1]++;
+ spin_unlock(&ticker_lock);
+ }
+}
+
__volatile__ unsigned int *master_l10_counter;
__volatile__ unsigned int *master_l10_limit;
/* last time the cmos clock got updated */
static long last_rtc_update=0;
+#ifndef __SMP__
+ if(!user_mode(regs))
+ sparc_do_profile(regs->pc, regs->u_regs[UREG_RETPC]);
+#endif
+
#ifdef CONFIG_SUN4
if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) ||
(idprom->id_machtype == (SM_SUN4 | SM_4_110))) {
.text
.align 4
+ .globl __atomic_begin
+__atomic_begin:
+
#ifndef __SMP__
.globl ___xchg32_sun4c
___xchg32_sun4c:
nop; nop; nop; ! Let the bits set
jmpl %o7, %g0 ! NOTE: not + 8, see callers in atomic.h
mov %g4, %o7 ! Restore %o7
+
+ .globl __atomic_end
+__atomic_end:
.text
.align 4
+ .globl __bitops_begin
+__bitops_begin:
+
/* Take bits in %g2 and set them in word at %g1,
* return whether bits were set in original value
* in %g2. %g4 holds value to restore into %o7
nop; nop; nop
jmpl %o7, %g0
mov %g4, %o7
+
+ .globl __bitops_end
+__bitops_end:
.text
.align 4
+ .globl __copy_user_begin
+__copy_user_begin:
+
.globl C_LABEL(__copy_user)
dword_align:
andcc %o1, 1, %g0
sub %o0, %g3, %o0
ba fixupretl
add %g3, %o2, %g3
+
+ .globl __copy_user_end
+__copy_user_end:
CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
# CONFIG_IDEDMA_PCI_WIP is not set
# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_WDC_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD7409 is not set
-/* $Id: ioctl32.c,v 1.87 2000/03/30 02:09:07 davem Exp $
+/* $Id: ioctl32.c,v 1.88 2000/04/14 10:10:34 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
#define ATM_GETSTATZ32 _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
#define ATM_GETLOOP32 _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
#define ATM_SETLOOP32 _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
+#define ATM_QUERYLOOP32 _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
static struct {
unsigned int cmd32;
{ ATM_GETSTAT32, ATM_GETSTAT },
{ ATM_GETSTATZ32, ATM_GETSTATZ },
{ ATM_GETLOOP32, ATM_GETLOOP },
- { ATM_SETLOOP32, ATM_SETLOOP }
+ { ATM_SETLOOP32, ATM_SETLOOP },
+ { ATM_QUERYLOOP32, ATM_QUERYLOOP }
};
#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
case ATM_GETSTATZ:
case ATM_GETLOOP:
case ATM_SETLOOP:
+ case ATM_QUERYLOOP:
return do_atmif_sioc(fd, cmd, arg);
}
HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl)
HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl)
HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
-/* $Id: power.c,v 1.5 1999/12/19 23:28:00 davem Exp $
+/* $Id: power.c,v 1.6 2000/04/13 00:59:59 davem Exp $
* power.c: Power management driver.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
static char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
char *argv[] = { "/usr/bin/shutdown", "-h", "now", NULL };
- current->session = 1;
- current->pgrp = 1;
+ daemonize();
sprintf(current->comm, "powerd");
again:
-/* $Id: sbus.c,v 1.10 2000/03/10 07:52:08 davem Exp $
+/* $Id: sbus.c,v 1.11 2000/04/14 09:13:04 davem Exp $
* sbus.c: UltraSparc SBUS controller support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t size, int dir)
{
struct sbus_iommu *iommu = sdev->bus->iommu;
- unsigned long npages, phys_base, flags;
+ unsigned long npages, pbase, flags;
iopte_t *iopte;
u32 dma_base, offset;
unsigned long iopte_bits;
if (dir == SBUS_DMA_NONE)
BUG();
- phys_base = (unsigned long) ptr;
- offset = (u32) (phys_base & ~PAGE_MASK);
- size = (PAGE_ALIGN(phys_base + size) - (phys_base & PAGE_MASK));
- phys_base = (unsigned long) __pa(phys_base & PAGE_MASK);
+ pbase = (unsigned long) ptr;
+ offset = (u32) (pbase & ~PAGE_MASK);
+ size = (PAGE_ALIGN(pbase + size) - (pbase & PAGE_MASK));
+ pbase = (unsigned long) __pa(pbase & PAGE_MASK);
spin_lock_irqsave(&iommu->lock, flags);
npages = size >> PAGE_SHIFT;
if (dir != SBUS_DMA_TODEVICE)
iopte_bits |= IOPTE_WRITE;
while (npages--) {
- *iopte++ = __iopte(iopte_bits | (phys_base & IOPTE_PAGE));
- phys_base += PAGE_SIZE;
+ *iopte++ = __iopte(iopte_bits | (pbase & IOPTE_PAGE));
+ pbase += PAGE_SIZE;
}
npages = size >> PAGE_SHIFT;
spin_unlock_irqrestore(&iommu->lock, flags);
-/* $Id: signal32.c,v 1.61 2000/04/08 02:11:46 davem Exp $
+/* $Id: signal32.c,v 1.62 2000/04/12 08:10:19 davem Exp $
* arch/sparc64/kernel/signal32.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
goto sigsegv;
if(pte_present(*ptep)) {
- unsigned long page = (unsigned long)
- __va(pte_pagenr(*ptep) << PAGE_SHIFT);
+ unsigned long page = page_address(pte_page(*ptep));
__asm__ __volatile__("
membar #StoreStore
goto sigsegv;
if(pte_present(*ptep)) {
- unsigned long page = (unsigned long)
- __va(pte_pagenr(*ptep) << PAGE_SHIFT);
+ unsigned long page = page_address(pte_page(*ptep));
__asm__ __volatile__("
membar #StoreStore
smp_cross_call(&xcall_promstop, 0, 0, 0);
}
-static inline void sparc64_do_profile(unsigned long pc, unsigned long o7)
-{
- if (prof_buffer && current->pid) {
- extern int _stext;
- extern int rwlock_impl_begin, rwlock_impl_end;
- extern int atomic_impl_begin, atomic_impl_end;
- extern int __memcpy_begin, __memcpy_end;
- extern int __bitops_begin, __bitops_end;
-
- if ((pc >= (unsigned long) &atomic_impl_begin &&
- pc < (unsigned long) &atomic_impl_end) ||
- (pc >= (unsigned long) &rwlock_impl_begin &&
- pc < (unsigned long) &rwlock_impl_end) ||
- (pc >= (unsigned long) &__memcpy_begin &&
- pc < (unsigned long) &__memcpy_end) ||
- (pc >= (unsigned long) &__bitops_begin &&
- pc < (unsigned long) &__bitops_end))
- pc = o7;
-
- pc -= (unsigned long) &_stext;
- pc >>= prof_shift;
-
- if(pc >= prof_len)
- pc = prof_len - 1;
- atomic_inc((atomic_t *)&prof_buffer[pc]);
- }
-}
+extern void sparc64_do_profile(unsigned long pc, unsigned long o7);
static unsigned long current_tick_offset;
static void __init smp_tune_scheduling (void)
{
- unsigned long flush_base, flags, *p;
+ unsigned long orig_flush_base, flush_base, flags, *p;
unsigned int ecache_size, order;
cycles_t tick1, tick2, raw;
"ecache-size", (512 * 1024));
if (ecache_size > (4 * 1024 * 1024))
ecache_size = (4 * 1024 * 1024);
- flush_base = __get_free_pages(GFP_KERNEL, order = get_order(ecache_size));
+ orig_flush_base = flush_base =
+ __get_free_pages(GFP_KERNEL, order = get_order(ecache_size));
if (flush_base != 0UL) {
__save_and_cli(flags);
*/
cacheflush_time = (raw - (raw >> 2));
- free_pages(flush_base, order);
+ free_pages(orig_flush_base, order);
} else {
cacheflush_time = ((ecache_size << 2) +
(ecache_size << 1));
-/* $Id: sparc64_ksyms.c,v 1.80 2000/03/27 10:38:47 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.81 2000/04/13 04:45:58 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
/* Special internal versions of library functions. */
EXPORT_SYMBOL(__memcpy);
EXPORT_SYMBOL(__memset);
-EXPORT_SYMBOL(clear_page);
-EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(_clear_page);
+EXPORT_SYMBOL(_copy_page);
EXPORT_SYMBOL(clear_user_page);
EXPORT_SYMBOL(copy_user_page);
EXPORT_SYMBOL(__bzero);
-/* $Id: sys_sparc.c,v 1.37 2000/03/17 05:48:46 anton Exp $
+/* $Id: sys_sparc.c,v 1.38 2000/04/13 07:30:34 jj Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
#include <linux/smp_lock.h>
#include <linux/malloc.h>
#include <linux/ipc.h>
+#include <linux/personality.h>
#include <asm/uaccess.h>
#include <asm/ipc.h>
return err;
}
+extern asmlinkage int sys_newuname(struct new_utsname * name);
+
+asmlinkage int sparc64_newuname(struct new_utsname * name)
+{
+ int ret = sys_newuname(name);
+
+ if (current->personality == PER_LINUX32 && !ret) {
+ ret = copy_to_user(name->machine, "sparc\0\0", 8);
+ }
+ return ret;
+}
+
+extern asmlinkage long sys_personality(unsigned long);
+
+asmlinkage int sparc64_personality(unsigned long personality)
+{
+ int ret;
+ lock_kernel();
+ if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+ personality = PER_LINUX32;
+ ret = sys_personality(personality);
+ unlock_kernel();
+ if (ret == PER_LINUX32)
+ ret = PER_LINUX;
+ return ret;
+}
+
/* Linux version of mmap */
asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
unsigned long prot, unsigned long flags, unsigned long fd,
-/* $Id: sys_sparc32.c,v 1.144 2000/04/08 02:11:47 davem Exp $
+/* $Id: sys_sparc32.c,v 1.145 2000/04/13 07:30:34 jj Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
}
-extern asmlinkage int sys_newuname(struct new_utsname * name);
-
-asmlinkage int sys32_newuname(struct new_utsname * name)
-{
- int ret = sys_newuname(name);
-
- if (current->personality == PER_LINUX32 && !ret) {
- ret = copy_to_user(name->machine, "sparc\0\0", 8);
- }
- return ret;
-}
-
extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
size_t count, loff_t pos);
}
-extern asmlinkage long sys_personality(unsigned long);
-
-asmlinkage int sys32_personality(unsigned long personality)
-{
- int ret;
- lock_kernel();
- if (current->personality == PER_LINUX32 && personality == PER_LINUX)
- personality = PER_LINUX32;
- ret = sys_personality(personality);
- unlock_kernel();
- if (ret == PER_LINUX32)
- ret = PER_LINUX;
- return ret;
-}
-
extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
-/* $Id: sys_sunos32.c,v 1.44 2000/04/08 02:11:50 davem Exp $
+/* $Id: sys_sunos32.c,v 1.45 2000/04/13 00:55:49 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: systbls.S,v 1.71 2000/03/15 02:43:36 davem Exp $
+/* $Id: systbls.S,v 1.72 2000/04/13 07:30:34 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getdents
.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_sigpending, sys32_query_module
- .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_newuname
-/*190*/ .word sys32_init_module, sys32_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+ .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
+/*190*/ .word sys32_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
/*200*/ .word sys_ssetmask, sys_sigsuspend, sys32_newlstat, sys_uselib, old32_readdir
.word sys_nis_syscall, sys32_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
/*170*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getdents
.word sys_setsid, sys_fchdir, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
/*180*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_query_module
- .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_newuname
-/*190*/ .word sys_init_module, sys_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
+ .word sys_setpgid, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sparc64_newuname
+/*190*/ .word sys_init_module, sparc64_personality, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_nis_syscall, sys_getppid, sys_nis_syscall, sys_sgetmask
/*200*/ .word sys_ssetmask, sys_nis_syscall, sys_newlstat, sys_uselib, sys_nis_syscall
.word sys_nis_syscall, sys_socketcall, sys_syslog, sys_nis_syscall, sys_nis_syscall
-/* $Id: time.c,v 1.24 2000/03/02 02:00:25 davem Exp $
+/* $Id: time.c,v 1.25 2000/04/13 05:29:44 davem Exp $
* time.c: UltraSparc timer and TOD clock support.
*
* Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
}
}
+void sparc64_do_profile(unsigned long pc, unsigned long o7)
+{
+ if (prof_buffer && current->pid) {
+ extern int _stext;
+ extern int rwlock_impl_begin, rwlock_impl_end;
+ extern int atomic_impl_begin, atomic_impl_end;
+ extern int __memcpy_begin, __memcpy_end;
+ extern int __bitops_begin, __bitops_end;
+
+ if ((pc >= (unsigned long) &atomic_impl_begin &&
+ pc < (unsigned long) &atomic_impl_end) ||
+ (pc >= (unsigned long) &rwlock_impl_begin &&
+ pc < (unsigned long) &rwlock_impl_end) ||
+ (pc >= (unsigned long) &__memcpy_begin &&
+ pc < (unsigned long) &__memcpy_end) ||
+ (pc >= (unsigned long) &__bitops_begin &&
+ pc < (unsigned long) &__bitops_end))
+ pc = o7;
+
+ pc -= (unsigned long) &_stext;
+ pc >>= prof_shift;
+
+ if(pc >= prof_len)
+ pc = prof_len - 1;
+ atomic_inc((atomic_t *)&prof_buffer[pc]);
+ }
+}
+
static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
{
unsigned long ticks, pstate;
write_lock(&xtime_lock);
do {
+#ifndef __SMP__
+ if ((regs->tstate & TSTATE_PRIV) != 0)
+ sparc64_do_profile(regs->tpc, regs->u_regs[UREG_RETPC]);
+#endif
do_timer(regs);
/* Guarentee that the following sequences execute
-/* $Id: blockops.S,v 1.24 2000/03/27 10:38:41 davem Exp $
+/* $Id: blockops.S,v 1.25 2000/04/13 04:45:58 davem Exp $
* blockops.S: UltraSparc block zero optimized routines.
*
* Copyright (C) 1996, 1998, 1999, 2000 David S. Miller (davem@redhat.com)
.text
.align 32
- .globl copy_page
- .type copy_page,@function
-copy_page: /* %o0=dest, %o1=src */
+ .globl _copy_page
+ .type _copy_page,@function
+_copy_page: /* %o0=dest, %o1=src */
VISEntry
membar #LoadStore | #StoreStore | #StoreLoad
ldda [%o1] ASI_BLK_P, %f0
stda %f16, [%o0] ASI_BLK_COMMIT_P
.align 32
- .globl clear_page
- .type clear_page,@function
-clear_page: /* %o0=dest */
+ .globl _clear_page
+ .type _clear_page,@function
+_clear_page: /* %o0=dest */
VISEntryHalf
ba,pt %xcc, clear_page_common
clr %o4
-/* $Id: fault.c,v 1.45 2000/03/27 10:38:51 davem Exp $
+/* $Id: fault.c,v 1.46 2000/04/12 08:10:23 davem Exp $
* arch/sparc64/mm/fault.c: Page fault handlers for the 64-bit Sparc.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
if(!pte_present(pte))
goto out;
- pa = (pte_pagenr(pte) << PAGE_SHIFT) + (tpc & ~PAGE_MASK);
+ pa = phys_base + (pte_pagenr(pte) << PAGE_SHIFT);
+ pa += (tpc & ~PAGE_MASK);
/* Use phys bypass so we don't pollute dtlb/dcache. */
__asm__ __volatile__("lduwa [%1] %2, %0"
-/* $Id: init.c,v 1.149 2000/03/15 14:42:58 jj Exp $
+/* $Id: init.c,v 1.150 2000/04/12 08:10:22 davem Exp $
* arch/sparc64/mm/init.c
*
* Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
*/
pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset, unsigned long color)
{
- unsigned long paddr = __get_free_pages(GFP_KERNEL, 1);
+ struct page *page = alloc_pages(GFP_KERNEL, 1);
- if (paddr) {
- struct page *page2 = mem_map + MAP_NR(paddr + PAGE_SIZE);
+ if (page) {
unsigned long *to_free;
+ unsigned long paddr;
pte_t *pte;
- /* Set count of second page, so we can free it
- * seperately later on.
- */
- atomic_set(&page2->count, 1);
-
- /* Clear out both pages now. */
+ set_page_count((page + 1), 1);
+ paddr = page_address(page);
memset((char *)paddr, 0, (PAGE_SIZE << 1));
- /* Determine which page we give to this request. */
if (!color) {
pte = (pte_t *) paddr;
to_free = (unsigned long *) (paddr + PAGE_SIZE);
}
}
-#undef DEBUG_BOOTMEM
-
extern unsigned long cmdline_memory_size;
-unsigned long __init bootmem_init(void)
+unsigned long __init bootmem_init(unsigned long *pages_avail)
{
unsigned long bootmap_size, start_pfn, end_pfn;
unsigned long end_of_phys_memory = 0UL;
- unsigned long bootmap_pfn;
+ unsigned long bootmap_pfn, bytes_avail, size;
int i;
- /* XXX It is a bit ambiguous here, whether we should
- * XXX treat the user specified mem=xxx as total wanted
- * XXX physical memory, or as a limit to the upper
- * XXX physical address we allow. For now it is the
- * XXX latter. -DaveM
- */
-#ifdef DEBUG_BOOTMEM
- prom_printf("bootmem_init: Scan sp_banks, ");
-#endif
+
+ bytes_avail = 0UL;
for (i = 0; sp_banks[i].num_bytes != 0; i++) {
end_of_phys_memory = sp_banks[i].base_addr +
sp_banks[i].num_bytes;
+ bytes_avail += sp_banks[i].num_bytes;
if (cmdline_memory_size) {
- if (end_of_phys_memory > cmdline_memory_size) {
- if (cmdline_memory_size < sp_banks[i].base_addr) {
- end_of_phys_memory =
- sp_banks[i-1].base_addr +
- sp_banks[i-1].num_bytes;
+ if (bytes_avail > cmdline_memory_size) {
+ unsigned long slack = bytes_avail - cmdline_memory_size;
+
+ bytes_avail -= slack;
+ end_of_phys_memory -= slack;
+
+ sp_banks[i].num_bytes -= slack;
+ if (sp_banks[i].num_bytes == 0)
sp_banks[i].base_addr = 0xdeadbeef;
- sp_banks[i].num_bytes = 0;
- } else {
- sp_banks[i].num_bytes -=
- (end_of_phys_memory -
- cmdline_memory_size);
- end_of_phys_memory = cmdline_memory_size;
- sp_banks[++i].base_addr = 0xdeadbeef;
- sp_banks[i].num_bytes = 0;
- }
+
break;
}
}
}
+ *pages_avail = bytes_avail >> PAGE_SHIFT;
+
/* Start with page aligned address of last symbol in kernel
* image. The kernel is hard mapped below PAGE_OFFSET in a
* 4MB locked TLB translation.
}
#endif
/* Initialize the boot-time allocator. */
-#ifdef DEBUG_BOOTMEM
- prom_printf("init_bootmem(spfn[%lx],bpfn[%lx],epfn[%lx])\n",
- start_pfn, bootmap_pfn, end_pfn);
-#endif
- bootmap_size = init_bootmem(bootmap_pfn, end_pfn);
+ bootmap_size = init_bootmem_node(0, bootmap_pfn, phys_base>>PAGE_SHIFT, end_pfn);
/* Now register the available physical memory with the
* allocator.
*/
- for (i = 0; sp_banks[i].num_bytes != 0; i++) {
-#ifdef DEBUG_BOOTMEM
- prom_printf("free_bootmem: base[%lx] size[%lx]\n",
- sp_banks[i].base_addr,
- sp_banks[i].num_bytes);
-#endif
+ for (i = 0; sp_banks[i].num_bytes != 0; i++)
free_bootmem(sp_banks[i].base_addr,
sp_banks[i].num_bytes);
- }
- /* Reserve the kernel text/data/bss, the bootmem bootmap and initrd. */
-#ifdef DEBUG_BOOTMEM
-#ifdef CONFIG_BLK_DEV_INITRD
- if (initrd_start)
- prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
- initrd_start, initrd_end - initrd_start);
-#endif
- prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
- phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
- prom_printf("reserve_bootmem: base[%lx] size[%lx]\n",
- (bootmap_pfn << PAGE_SHIFT), bootmap_size);
-#endif
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start) {
- reserve_bootmem(initrd_start, initrd_end - initrd_start);
+ size = initrd_end - initrd_start;
+
+ /* Resert the initrd image area. */
+ reserve_bootmem(initrd_start, size);
+ *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+
initrd_start += PAGE_OFFSET;
initrd_end += PAGE_OFFSET;
}
#endif
- reserve_bootmem(phys_base, (start_pfn << PAGE_SHIFT) - phys_base);
- reserve_bootmem((bootmap_pfn << PAGE_SHIFT), bootmap_size);
+ /* Reserve the kernel text/data/bss. */
+ size = (start_pfn << PAGE_SHIFT) - phys_base;
+ reserve_bootmem(phys_base, size);
+ *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+ /* Reserve the bootmem map. We do not account for it
+ * in pages_avail because we will release that memory
+ * in free_all_bootmem.
+ */
+ size = bootmap_size;
+ reserve_bootmem((bootmap_pfn << PAGE_SHIFT), size);
+ *pages_avail -= PAGE_ALIGN(size) >> PAGE_SHIFT;
-#ifdef DEBUG_BOOTMEM
- prom_printf("init_bootmem: return end_pfn[%lx]\n", end_pfn);
-#endif
return end_pfn;
}
extern unsigned int sparc64_vpte_patchme2[1];
unsigned long alias_base = phys_base + PAGE_OFFSET;
unsigned long second_alias_page = 0;
- unsigned long pt, flags, end_pfn;
+ unsigned long pt, flags, end_pfn, pages_avail;
unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
set_bit(0, mmu_context_bmap);
flushi((long)&sparc64_vpte_patchme1[0]);
/* Setup bootmem... */
- last_valid_pfn = end_pfn = bootmem_init();
+ pages_avail = 0;
+ last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
#ifdef CONFIG_SUN_SERIAL
/* This does not logically belong here, but we need to
flush_tlb_all();
{
- unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0};
+ unsigned long zones_size[MAX_NR_ZONES];
+ unsigned long zholes_size[MAX_NR_ZONES];
+ unsigned long npages;
+ int znum;
+
+ for (znum = 0; znum < MAX_NR_ZONES; znum++)
+ zones_size[znum] = zholes_size[znum] = 0;
+
+ npages = end_pfn - (phys_base >> PAGE_SHIFT);
+ zones_size[ZONE_DMA] = npages;
+ zholes_size[ZONE_DMA] = npages - pages_avail;
- zones_size[ZONE_DMA] = end_pfn;
- free_area_init(zones_size);
+ free_area_init_node(0, NULL, zones_size,
+ phys_base, zholes_size);
}
device_scan();
struct sparc_phys_banks saved_sp_banks[SPARC_PHYS_BANKS];
int i;
-#ifdef DEBUG_BOOTMEM
- prom_printf("taint_real_pages: Rescan sp_banks[].\n");
-#endif
for (i = 0; i < SPARC_PHYS_BANKS; i++) {
saved_sp_banks[i].base_addr =
sp_banks[i].base_addr;
goto do_next_page;
}
}
-#ifdef DEBUG_BOOTMEM
- prom_printf("taint: Page went away, reserve page %lx.\n",
- old_start);
-#endif
reserve_bootmem(old_start, PAGE_SIZE);
do_next_page:
}
}
-void __init free_mem_map_range(struct page *first, struct page *last)
-{
- first = (struct page *) PAGE_ALIGN((unsigned long)first);
- last = (struct page *) ((unsigned long)last & PAGE_MASK);
-#ifdef DEBUG_BOOTMEM
- prom_printf("[%p,%p] ", first, last);
-#endif
- while (first < last) {
- ClearPageReserved(mem_map + MAP_NR(first));
- set_page_count(mem_map + MAP_NR(first), 1);
- free_page((unsigned long)first);
- num_physpages++;
-
- first = (struct page *)((unsigned long)first + PAGE_SIZE);
- }
-}
-
-/* Walk through holes in sp_banks regions, if the mem_map array
- * areas representing those holes consume a page or more, free
- * up such pages. This helps a lot on machines where physical
- * ram is configured such that it begins at some hugh value.
- *
- * The sp_banks array is sorted by base address.
- */
-void __init free_unused_mem_map(void)
-{
- int i;
-
-#ifdef DEBUG_BOOTMEM
- prom_printf("free_unused_mem_map: ");
-#endif
- for (i = 0; sp_banks[i].num_bytes; i++) {
- if (i == 0) {
- struct page *first, *last;
-
- first = mem_map;
- last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
- free_mem_map_range(first, last);
- } else {
- struct page *first, *last;
- unsigned long prev_end;
-
- prev_end = sp_banks[i-1].base_addr +
- sp_banks[i-1].num_bytes;
- prev_end = PAGE_ALIGN(prev_end);
- first = &mem_map[prev_end >> PAGE_SHIFT];
- last = &mem_map[sp_banks[i].base_addr >> PAGE_SHIFT];
-
- free_mem_map_range(first, last);
-
- if (!sp_banks[i+1].num_bytes) {
- prev_end = sp_banks[i].base_addr +
- sp_banks[i].num_bytes;
- first = &mem_map[prev_end >> PAGE_SHIFT];
- last = &mem_map[last_valid_pfn];
- free_mem_map_range(first, last);
- }
- }
- }
-#ifdef DEBUG_BOOTMEM
- prom_printf("\n");
-#endif
-}
-
void __init mem_init(void)
{
unsigned long codepages, datapages, initpages;
taint_real_pages();
- max_mapnr = last_valid_pfn;
+ max_mapnr = last_valid_pfn - (phys_base >> PAGE_SHIFT);
high_memory = __va(last_valid_pfn << PAGE_SHIFT);
-#ifdef DEBUG_BOOTMEM
- prom_printf("mem_init: Calling free_all_bootmem().\n");
-#endif
num_physpages = free_all_bootmem();
-#if 0
- free_unused_mem_map();
-#endif
codepages = (((unsigned long) &etext) - ((unsigned long)&_start));
codepages = PAGE_ALIGN(codepages) >> PAGE_SHIFT;
datapages = (((unsigned long) &edata) - ((unsigned long)&etext));
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10),
PAGE_OFFSET, (last_valid_pfn << PAGE_SHIFT));
-
- /* NOTE NOTE NOTE NOTE
- * Please keep track of things and make sure this
- * always matches the code in mm/page_alloc.c -DaveM
- */
- i = nr_free_pages() >> 7;
- if (i < 48)
- i = 48;
- if (i > 256)
- i = 256;
- freepages.min = i;
- freepages.low = i << 1;
- freepages.high = freepages.low + i;
}
void free_initmem (void)
-/* $Id: misc.c,v 1.24 2000/04/08 02:11:55 davem Exp $
+/* $Id: misc.c,v 1.26 2000/04/14 09:59:02 davem Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
fi
fi
if [ "$CONFIG_PCI" = "y" -o "$CONFIG_SBUS" = "y" ]; then
- tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E
- if [ "$CONFIG_ATM_FORE200E" != "n" ]; then
+ tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE
+ if [ "$CONFIG_ATM_FORE200E_MAYBE" != "n" ]; then
if [ "$CONFIG_PCI" = "y" ]; then
bool ' PCA-200E support' CONFIG_ATM_FORE200E_PCA y
if [ "$CONFIG_ATM_FORE200E_PCA" = "y" ]; then
fi
fi
fi
+ fi
+ if [ "$CONFIG_ATM_FORE200E_PCA" = "y" -o "$CONFIG_ATM_FORE200E_SBA" = "y" ]; \
+ then
int ' Maximum number of tx retries' CONFIG_ATM_FORE200E_TX_RETRY 16
int ' Debugging level (0-3)' CONFIG_ATM_FORE200E_DEBUG 0
+ if [ "$CONFIG_ATM_FORE200E_MAYBE" = "y" ]; then
+ define_tristate CONFIG_ATM_FORE200E y
+ else
+ define_tristate CONFIG_ATM_FORE200E m
+ fi
fi
fi
endmenu
endif
endif
-ifeq ($(CONFIG_ATM_TNETA1570),y)
-O_OBJS += tneta1570.o suni.o
-endif
-
ifeq ($(CONFIG_ATM_NICSTAR),y)
O_OBJS += nicstar.o
ifeq ($(CONFIG_ATM_NICSTAR_USE_SUNI),y)
endif
ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
-FORE200E_FW_OBJS += fore200e_pca_fw.o
+ FORE200E_FW_OBJS += fore200e_pca_fw.o
+ ifeq ($(strip $(CONFIG_ATM_FORE200E_PCA_FW)),"")
+ CONFIG_ATM_FORE200E_PCA_DEFAULT_FW := y
+ endif
ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
# guess the target endianess to choose the right PCA-200E firmware image
CONFIG_ATM_FORE200E_PCA_FW := $(shell if test -n "`$(CC) -E -dM ../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo pca200e.bin; else echo pca200e_ecd.bin2; fi)
endif
endif
ifeq ($(CONFIG_ATM_FORE200E_SBA),y)
-FORE200E_FW_OBJS += fore200e_sba_fw.o
+ FORE200E_FW_OBJS += fore200e_sba_fw.o
+ ifeq ($(strip $(CONFIG_ATM_FORE200E_SBA_FW)),"")
+ CONFIG_ATM_FORE200E_SBA_DEFAULT_FW := y
+ endif
ifeq ($(CONFIG_ATM_FORE200E_SBA_DEFAULT_FW),y)
CONFIG_ATM_FORE200E_SBA_FW := sba200e_ecd.bin2
endif
endif
ifeq ($(CONFIG_ATM_FORE200E),y)
-O_OBJS += fore200e.o $(FORE200E_FW_OBJS)
+ O_OBJS += fore200e.o $(FORE200E_FW_OBJS)
else
ifeq ($(CONFIG_ATM_FORE200E),m)
- M_OBJS += fore_200e.o
+ M_OBJS += fore_200e.o
endif
endif
include $(TOPDIR)/Rules.make
+
# FORE Systems 200E-series firmware magic
fore200e_pca_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_PCA_FW)) \
fore200e_mkfirm
./fore200e_mkfirm -k -b _fore200e_pca_fw \
-i $(CONFIG_ATM_FORE200E_PCA_FW) -o $@
+ @ ( \
+ echo 'ifeq ($(strip $(CONFIG_ATM_FORE200E_PCA_FW)), $$(CONFIG_ATM_FORE200E_PCA_FW))'; \
+ echo 'FORE200E_FW_UP_TO_DATE += $@'; \
+ echo 'endif' \
+ ) >.$@.fw
fore200e_sba_fw.c: $(patsubst "%", %, $(CONFIG_ATM_FORE200E_SBA_FW)) \
fore200e_mkfirm
./fore200e_mkfirm -k -b _fore200e_sba_fw \
-i $(CONFIG_ATM_FORE200E_SBA_FW) -o $@
+ @ ( \
+ echo 'ifeq ($(strip $(CONFIG_ATM_FORE200E_SBA_FW)), $$(CONFIG_ATM_FORE200E_SBA_FW))'; \
+ echo 'FORE200E_FW_UP_TO_DATE += $@'; \
+ echo 'endif' \
+ ) >.$@.fw
fore200e_mkfirm: fore200e_mkfirm.c
$(HOSTCC) $(HOSTCFLAGS) $< -o $@
-# deal with the various suffixes of the firmware images
-%.bin: %.data
- objcopy -Iihex $< -Obinary $@.gz
- gzip -df $@.gz
-
-%.bin1: %.data
- objcopy -Iihex $< -Obinary $@.gz
- gzip -df $@.gz
-
-%.bin2: %.data
+# deal with the various suffixes of the binary firmware images
+%.bin %.bin1 %.bin2: %.data
objcopy -Iihex $< -Obinary $@.gz
gzip -df $@.gz
# module build
fore_200e.o: fore200e.o $(FORE200E_FW_OBJS)
$(LD) -r -o $@ $< $(FORE200E_FW_OBJS)
+
+# firmware dependency stuff taken from drivers/sound/Makefile
+FORE200E_FW_UP_TO_DATE :=
+
+FORE200E_FW_FILES := $(wildcard .fore200e_*.fw)
+ifneq ($(FORE200E_FW_FILES),)
+include $(FORE200E_FW_FILES)
+endif
+
+FORE200E_FW_CHANGED := $(filter-out $(FORE200E_FW_UP_TO_DATE), \
+ fore200e_pca_fw.c fore200e_sba_fw.c)
+
+ifneq ($(FORE200E_FW_CHANGED),)
+$(FORE200E_FW_CHANGED): dummy
+endif
}
}
+ // prevent module unload while sleeping (kmalloc/down)
+ // doing this any earlier would complicate more error return paths
+ MOD_INC_USE_COUNT;
+
// get space for our vcc stuff
vcc = kmalloc (sizeof(amb_vcc), GFP_KERNEL);
if (!vcc) {
PRINTK (KERN_ERR, "out of memory!");
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
atm_vcc->dev_data = (void *) vcc;
// indicate readiness
set_bit(ATM_VF_READY,&atm_vcc->flags);
- MOD_INC_USE_COUNT;
return 0;
}
// say the VPI/VCI is free again
clear_bit(ATM_VF_ADDR,&atm_vcc->flags);
+
MOD_DEC_USE_COUNT;
+ return;
}
/********** Debug\17Ioctl **********/
u32 iobase;
u32 * membase;
-#if 0
+#ifdef FILL_RX_POOLS_IN_BH
struct tq_struct bh;
#endif
/* drivers/atm/atmdev_init.c - ATM device driver initialization */
-/* Written 1995-1997 by Werner Almesberger, EPFL LRC */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
#include <linux/config.h>
#include <linux/init.h>
-#ifdef CONFIG_ATM_ENI
-extern int eni_detect(void);
-#endif
#ifdef CONFIG_ATM_ZATM
extern int zatm_detect(void);
#endif
-#ifdef CONFIG_ATM_TNETA1570
-extern int tneta1570_detect(void);
-#endif
#ifdef CONFIG_ATM_NICSTAR
extern int nicstar_detect(void);
#endif
#endif
+/*
+ * For historical reasons, atmdev_init returns the number of devices found.
+ * Note that some detections may not go via atmdev_init (e.g. eni.c), so this
+ * number is meaningless.
+ */
+
int __init atmdev_init(void)
{
int devs;
devs = 0;
-#ifdef CONFIG_ATM_ENI
-// devs += eni_detect();
-#endif
#ifdef CONFIG_ATM_ZATM
devs += zatm_detect();
#endif
-#ifdef CONFIG_ATM_TNETA1570
- devs += tneta1570_detect();
-#endif
#ifdef CONFIG_ATM_NICSTAR
devs += nicstar_detect();
#endif
set_current_state(TASK_UNINTERRUPTIBLE);
}
for (;;) {
- unsigned long flags;
int at_end;
u32 tmp;
- spin_lock_irqsave(&eni_dev->lock,flags);
+ tasklet_disable(&eni_dev->task);
tmp = readl(eni_dev->vci+vcc->vci*16+4) & MID_VCI_READ;
at_end = eni_vcc->rx_pos == tmp >> MID_VCI_READ_SHIFT;
- spin_unlock_irqrestore(&eni_dev->lock,flags);
+ tasklet_enable(&eni_dev->task);
if (at_end) break;
EVENT("drain discard (host 0x%lx, nic 0x%lx)\n",
eni_vcc->rx_pos,tmp);
}
#ifdef CONFIG_ATM_ENI_BURST_TX_16W /* may work with some PCI chipsets ... */
if (words & ~15) {
- DPRINTK("put_dma: %lx DMA: %d*16/%d words\n",paddr,words >> 4,
- words);
+ DPRINTK("put_dma: %lx DMA: %d*16/%d words\n",
+ (unsigned long) paddr,words >> 4,words);
dma[(*j)++] = MID_DT_16W | ((words >> 4) << MID_DMA_COUNT_SHIFT)
| (chan << MID_DMA_CHAN_SHIFT);
dma[(*j)++] = paddr;
#endif
#ifdef CONFIG_ATM_ENI_BURST_TX_4W /* probably useless if TX_8W or TX_16W */
if (words & ~3) {
- DPRINTK("put_dma: %lx DMA: %d*4/%d words\n",paddr,words >> 2,
- words);
+ DPRINTK("put_dma: %lx DMA: %d*4/%d words\n",
+ (unsigned long) paddr,words >> 2,words);
dma[(*j)++] = MID_DT_4W | ((words >> 2) << MID_DMA_COUNT_SHIFT)
| (chan << MID_DMA_CHAN_SHIFT);
dma[(*j)++] = paddr;
#endif
#ifdef CONFIG_ATM_ENI_BURST_TX_2W /* probably useless if TX_4W, TX_8W, ... */
if (words & ~1) {
- DPRINTK("put_dma: %lx DMA: %d*2/%d words\n",paddr,words >> 1,
- words);
+ DPRINTK("put_dma: %lx DMA: %d*2/%d words\n",
+ (unsigned long) paddr,words >> 1,words);
dma[(*j)++] = MID_DT_2W | ((words >> 1) << MID_DMA_COUNT_SHIFT)
| (chan << MID_DMA_CHAN_SHIFT);
dma[(*j)++] = paddr;
if (tx->send)
while ((skb = skb_dequeue(&tx->backlog))) {
res = do_tx(skb);
- if (res == enq_ok) tx->backlog_len--;
+ if (res == enq_ok) atomic_dec(&tx->backlog_len);
else {
DPRINTK("re-queuing TX PDU\n");
skb_queue_head(&tx->backlog,skb);
tx->send = mem;
tx->words = size >> 2;
skb_queue_head_init(&tx->backlog);
- tx->backlog_len = 0;
+ atomic_set(&tx->backlog_len,0);
for (order = 0; size > (1 << (order+10)); order++);
eni_out((order << MID_SIZE_SHIFT) |
((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)),
add_wait_queue(&eni_dev->tx_wait,&wait);
set_current_state(TASK_UNINTERRUPTIBLE);
for (;;) {
- unsigned long flags;
int txing;
- spin_lock_irqsave(&eni_dev->lock,flags);
+ tasklet_disable(&eni_dev->task);
txing = skb_peek(&eni_vcc->tx->backlog) || eni_vcc->txing;
- spin_unlock_irqrestore(&eni_dev->lock,flags);
+ tasklet_enable(&eni_dev->task);
if (!txing) break;
DPRINTK("%d TX left\n",eni_vcc->txing);
schedule();
#endif
-static void misc_int(struct atm_dev *dev,unsigned long reason)
+static void bug_int(struct atm_dev *dev,unsigned long reason)
{
struct eni_dev *eni_dev;
- DPRINTK(">misc_int\n");
+ DPRINTK(">bug_int\n");
eni_dev = ENI_DEV(dev);
- if (reason & MID_STAT_OVFL) {
- EVENT("stat overflow\n",0,0);
- eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
- }
- if (reason & MID_SUNI_INT) {
- EVENT("SUNI int\n",0,0);
- dev->phy->interrupt(dev);
-#if 0
- foo();
-#endif
- }
- if (reason & MID_DMA_ERR_ACK) {
+ if (reason & MID_DMA_ERR_ACK)
printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
"error\n",dev->number);
- EVENT("---dump ends here---\n",0,0);
- printk(KERN_NOTICE "---recent events---\n");
- event_dump();
- }
- if (reason & MID_TX_IDENT_MISM) {
+ if (reason & MID_TX_IDENT_MISM)
printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - ident "
"mismatch\n",dev->number);
- EVENT("---dump ends here---\n",0,0);
- printk(KERN_NOTICE "---recent events---\n");
- event_dump();
- }
- if (reason & MID_TX_DMA_OVFL) {
+ if (reason & MID_TX_DMA_OVFL)
printk(KERN_CRIT DEV_LABEL "(itf %d): driver error - DMA "
"overflow\n",dev->number);
- EVENT("---dump ends here---\n",0,0);
- printk(KERN_NOTICE "---recent events---\n");
- event_dump();
- }
+ EVENT("---dump ends here---\n",0,0);
+ printk(KERN_NOTICE "---recent events---\n");
+ event_dump();
}
{
struct atm_dev *dev;
struct eni_dev *eni_dev;
- unsigned long reason;
+ u32 reason;
DPRINTK(">eni_int\n");
dev = dev_id;
eni_dev = ENI_DEV(dev);
- while ((reason = eni_in(MID_ISA))) {
- DPRINTK(DEV_LABEL ": int 0x%lx\n",reason);
- if (reason & MID_RX_DMA_COMPLETE) {
- EVENT("INT: RX DMA complete, starting dequeue_rx\n",
- 0,0);
- spin_lock(&eni_dev->lock);
- dequeue_rx(dev);
- EVENT("dequeue_rx done, starting poll_rx\n",0,0);
- poll_rx(dev);
- spin_unlock(&eni_dev->lock);
- EVENT("poll_rx done\n",0,0);
- /* poll_tx ? */
- }
- if (reason & MID_SERVICE) {
- EVENT("INT: service, starting get_service\n",0,0);
- spin_lock(&eni_dev->lock);
- get_service(dev);
- EVENT("get_service done, starting poll_rx\n",0,0);
- poll_rx(dev);
- spin_unlock(&eni_dev->lock);
- EVENT("poll_rx done\n",0,0);
- }
- if (reason & MID_TX_DMA_COMPLETE) {
- EVENT("INT: TX DMA COMPLETE\n",0,0);
- spin_lock(&eni_dev->lock);
- dequeue_tx(dev);
- spin_unlock(&eni_dev->lock);
- }
- if (reason & MID_TX_COMPLETE) {
- EVENT("INT: TX COMPLETE\n",0,0);
+ reason = eni_in(MID_ISA);
+ DPRINTK(DEV_LABEL ": int 0x%lx\n",(unsigned long) reason);
+ /*
+ * Must handle these two right now, because reading ISA doesn't clear
+ * them, so they re-occur and we never make it to the tasklet. Since
+ * they're rare, we don't mind the occasional invocation of eni_tasklet
+ * with eni_dev->events == 0.
+ */
+ if (reason & MID_STAT_OVFL) {
+ EVENT("stat overflow\n",0,0);
+ eni_dev->lost += eni_in(MID_STAT) & MID_OVFL_TRASH;
+ }
+ if (reason & MID_SUNI_INT) {
+ EVENT("SUNI int\n",0,0);
+ dev->phy->interrupt(dev);
+#if 0
+ foo();
+#endif
+ }
+ spin_lock(&eni_dev->lock);
+ eni_dev->events |= reason;
+ spin_unlock(&eni_dev->lock);
+ tasklet_schedule(&eni_dev->task);
+}
+
+
+static void eni_tasklet(unsigned long data)
+{
+ struct atm_dev *dev = (struct atm_dev *) data;
+ struct eni_dev *eni_dev = ENI_DEV(dev);
+ unsigned long flags;
+ u32 events;
+
+ DPRINTK("eni_tasklet (dev %p)\n",dev);
+ spin_lock_irqsave(&eni_dev->lock,flags);
+ events = xchg(&eni_dev->events,0);
+ spin_unlock_irqrestore(&eni_dev->lock,flags);
+ if (events & MID_RX_DMA_COMPLETE) {
+ EVENT("INT: RX DMA complete, starting dequeue_rx\n",0,0);
+ dequeue_rx(dev);
+ EVENT("dequeue_rx done, starting poll_rx\n",0,0);
+ poll_rx(dev);
+ EVENT("poll_rx done\n",0,0);
+ /* poll_tx ? */
+ }
+ if (events & MID_SERVICE) {
+ EVENT("INT: service, starting get_service\n",0,0);
+ get_service(dev);
+ EVENT("get_service done, starting poll_rx\n",0,0);
+ poll_rx(dev);
+ EVENT("poll_rx done\n",0,0);
+ }
+ if (events & MID_TX_DMA_COMPLETE) {
+ EVENT("INT: TX DMA COMPLETE\n",0,0);
+ dequeue_tx(dev);
+ }
+ if (events & MID_TX_COMPLETE) {
+ EVENT("INT: TX COMPLETE\n",0,0);
tx_complete++;
- spin_lock(&eni_dev->lock);
- poll_tx(dev);
- spin_unlock(&eni_dev->lock);
- wake_up(&eni_dev->tx_wait);
- /* poll_rx ? */
- }
- if (reason & (MID_STAT_OVFL | MID_SUNI_INT | MID_DMA_ERR_ACK |
- MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {
- EVENT("misc interrupt\n",0,0);
- misc_int(dev,reason);
- }
+ wake_up(&eni_dev->tx_wait);
+ /* poll_rx ? */
+ }
+ if (events & (MID_DMA_ERR_ACK | MID_TX_IDENT_MISM | MID_TX_DMA_OVFL)) {
+ EVENT("bug interrupt\n",0,0);
+ bug_int(dev,events);
}
+ poll_tx(dev);
}
eni_dev->vci,eni_dev->rx_dma,eni_dev->tx_dma,
eni_dev->service,buf);
spin_lock_init(&eni_dev->lock);
+ tasklet_init(&eni_dev->task,eni_tasklet,(unsigned long) dev);
+ eni_dev->events = 0;
/* initialize memory management */
buffer_mem = eni_dev->mem-(buf-eni_dev->ram);
eni_dev->free_list_size = buffer_mem/MID_MIN_BUF_SIZE/2;
struct eni_dev *eni_dev = ENI_DEV(vcc->dev);
struct eni_tx *tx = ENI_VCC(vcc)->tx;
struct sk_buff *skb;
- unsigned long flags;
int error,rate,rsv,shp;
if (qos->txtp.traffic_class == ATM_NONE) return 0;
* Walk through the send buffer and patch the rate information in all
* segmentation buffer descriptors of this VCC.
*/
- spin_lock_irqsave(&eni_dev->lock,flags);
+ tasklet_disable(&eni_dev->task);
for (skb = eni_dev->tx_queue.next; skb !=
(struct sk_buff *) &eni_dev->tx_queue; skb = skb->next) {
unsigned long dsc;
(tx->prescaler << MID_SEG_PR_SHIFT) |
(tx->resolution << MID_SEG_RATE_SHIFT), dsc);
}
- spin_unlock_irqrestore(&eni_dev->lock,flags);
+ tasklet_enable(&eni_dev->task);
return 0;
}
static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb)
{
- unsigned long flags;
-
DPRINTK(">eni_send\n");
if (!ENI_VCC(vcc)->tx) {
if (vcc->pop) vcc->pop(vcc,skb);
}
submitted++;
ATM_SKB(skb)->vcc = vcc;
- spin_lock_irqsave(&ENI_DEV(vcc->dev)->lock,flags); /* brute force */
- if (skb_peek(&ENI_VCC(vcc)->tx->backlog) || do_tx(skb)) {
- skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
- ENI_VCC(vcc)->tx->backlog_len++;
+ skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb);
+ atomic_inc(&ENI_VCC(vcc)->tx->backlog_len);
backlogged++;
- }
- spin_unlock_irqrestore(&ENI_DEV(vcc->dev)->lock,flags);
+ tasklet_schedule(&ENI_DEV(vcc->dev)->task);
return 0;
}
}
if (--left) continue;
return sprintf(page,"%10sbacklog %d bytes\n","",
- tx->backlog_len);
+ atomic_read(&tx->backlog_len));
}
for (vcc = dev->vccs; vcc; vcc = vcc->next) {
struct eni_vcc *eni_vcc = ENI_VCC(vcc);
#include <linux/time.h>
#include <linux/pci.h>
#include <linux/spinlock.h>
+#include <asm/atomic.h>
#include "midway.h"
int reserved; /* reserved peak cell rate */
int shaping; /* shaped peak cell rate */
struct sk_buff_head backlog; /* queue of waiting TX buffers */
- int backlog_len; /* length of backlog in bytes */
+ atomic_t backlog_len; /* length of backlog in bytes */
};
struct eni_vcc {
struct eni_dev {
/*-------------------------------- spinlock */
spinlock_t lock; /* sync with interrupt */
+ struct tasklet_struct task; /* tasklet for interrupt work */
+ u32 events; /* pending events */
/*-------------------------------- base pointers into Midway address
space */
unsigned long phy; /* PHY interface chip registers */
/*
- $Id: fore200e.c,v 1.2 2000/03/21 21:19:24 davem Exp $
+ $Id: fore200e.c,v 1.5 2000/04/14 10:10:34 davem Exp $
A FORE Systems 200E-series driver for ATM on Linux.
- Christophe Lizzi (lizzi@cnam.fr), October 1999-February 2000.
+ Christophe Lizzi (lizzi@cnam.fr), October 1999-March 2000.
Based on the PCA-200E driver from Uwe Dannowski (Uwe.Dannowski@inf.tu-dresden.de).
#include <linux/init.h>
#include <linux/capability.h>
#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/bitops.h>
#include <linux/atmdev.h>
#include <linux/sonet.h>
#include <linux/atm_suni.h>
-#include <linux/bitops.h>
#include <asm/io.h>
#include <asm/string.h>
#include <asm/segment.h>
#define FORE200E_52BYTE_AAL0_SDU
#endif
-#define FORE200E_VERSION "0.2b"
+#define FORE200E_VERSION "0.2d"
#define FORE200E "fore200e: "
}
+
#ifdef CONFIG_ATM_FORE200E_PCA
static u32 fore200e_pca_read(volatile u32* addr)
static void
fore200e_pca_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction);
+ DPRINTK(3, "PCI DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d\n",
+ dma_addr, size, direction);
pci_unmap_single((struct pci_dev*)fore200e->bus_dev, dma_addr, size, direction);
}
(to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
static int
-fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int nbr, int alignment)
+fore200e_pca_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
+ int size, int nbr, int alignment)
{
#if defined(__sparc_v9__)
/* returned chunks are page-aligned */
sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
+ pci_enable_device(pci_dev);
pci_set_master(pci_dev);
return fore200e;
static void
fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction)
{
- DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", dma_addr, size, direction);
+ DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n",
+ dma_addr, size, direction);
sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction);
}
(to hold descriptors, status, queues, etc.) shared by the driver and the adapter */
static int
-fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, int nbr, int alignment)
+fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk,
+ int size, int nbr, int alignment)
{
chunk->alloc_size = chunk->align_size = size * nbr;
}
DPRINTK(3, "valid interrupt on device %c\n", fore200e->name[9]);
- fore200e_irq_rx(fore200e);
+ tasklet_schedule(&fore200e->tasklet);
+
+ fore200e->bus->irq_ack(fore200e);
+}
+
+
+static void
+fore200e_tasklet(unsigned long data)
+{
+ struct fore200e* fore200e = (struct fore200e*) data;
+ fore200e_irq_rx(fore200e);
+
if (fore200e->host_txq.txing)
fore200e_irq_tx(fore200e);
-
- fore200e->bus->irq_ack(fore200e);
}
+
static int
fore200e_select_scheme(struct atm_vcc* vcc)
{
if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC)
return 0;
- set_bit(ATM_VF_ADDR,&vcc->flags);
+ set_bit(ATM_VF_ADDR, &vcc->flags);
vcc->itf = vcc->dev->number;
DPRINTK(2, "opening %d.%d.%d:%d QoS = (tx: cl=%s, pcr=%d-%d, cdv=%d, max_sdu=%d; "
fore200e_vcc->tx_min_pdu = fore200e_vcc->rx_min_pdu = 65536;
fore200e_vcc->tx_max_pdu = fore200e_vcc->rx_max_pdu = 0;
- clear_bit(ATM_VF_READY,&vcc->flags);
+ set_bit(ATM_VF_READY, &vcc->flags);
return 0;
}
fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
up(&fore200e->rate_sf);
}
+
+ clear_bit(ATM_VF_READY, &vcc->flags);
}
struct host_txq_entry* entry;
struct tpd* tpd;
struct tpd_haddr tpd_haddr;
- unsigned long flags;
+ //unsigned long flags;
int retry = CONFIG_ATM_FORE200E_TX_RETRY;
int tx_copy = 0;
int tx_len = skb->len;
retry_here:
- spin_lock_irqsave(&fore200e->tx_lock, flags);
+ tasklet_disable(&fore200e->tasklet);
entry = &txq->host_entry[ txq->head ];
if (*entry->status != STATUS_FREE) {
- spin_unlock_irqrestore(&fore200e->tx_lock, flags);
+ tasklet_enable(&fore200e->tasklet);
/* retry once again? */
if(--retry > 0)
entry->data = kmalloc(tx_len, GFP_ATOMIC | GFP_DMA);
if (entry->data == NULL) {
- spin_unlock_irqrestore(&fore200e->tx_lock, flags);
+ tasklet_enable(&fore200e->tasklet);
if (vcc->pop)
vcc->pop(vcc, skb);
else
FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
txq->txing++;
- spin_unlock_irqrestore(&fore200e->tx_lock, flags);
-
+ tasklet_enable(&fore200e->tasklet);
+
/* ensure DMA synchronisation */
- fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
+ fore200e->bus->dma_sync(fore200e, tpd->tsd[ 0 ].buffer, tpd->tsd[ 0 ].length, FORE200E_DMA_TODEVICE);
DPRINTK(3, "tx on %d.%d.%d:%d, len = %u (%u)\n",
vcc->itf, vcc->vpi, vcc->vci, fore200e_atm2fore_aal(vcc->qos.aal),
return put_user(fore200e->loop_mode, (int*)arg) ? -EFAULT : 0;
case ATM_QUERYLOOP:
- return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ?
- -EFAULT : 0;
+ return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ? -EFAULT : 0;
}
return -ENOSYS; /* not implemented */
/* update rate control parameters */
fore200e_rate_ctrl(qos, &fore200e_vcc->rate);
- set_bit(ATM_VF_HASQOS,&vcc->flags);
+ set_bit(ATM_VF_HASQOS, &vcc->flags);
return 0;
}
printk(FORE200E "IRQ %s reserved for device %s\n",
fore200e_irq_itoa(fore200e->irq), fore200e->name);
+ tasklet_init(&fore200e->tasklet, fore200e_tasklet, (unsigned long)fore200e);
+
fore200e->state = FORE200E_STATE_IRQ;
return 0;
}
DPRINTK(2, "device %s being initialized\n", fore200e->name);
- spin_lock_init(&fore200e->tx_lock);
init_MUTEX(&fore200e->rate_sf);
cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
if (media_index < 0 || media_index > 4)
media_index = 5;
- switch(fore200e->loop_mode) {
+ switch (fore200e->loop_mode) {
case ATM_LM_NONE: oc3_index = 0;
break;
case ATM_LM_LOC_PHY: oc3_index = 1;
#ifdef MODULE
-unsigned int
-init_module(void)
+static unsigned int __init
+fore200e_module_init(void)
{
DPRINTK(1, "module loaded\n");
return fore200e_detect() == 0;
}
-void
-cleanup_module(void)
+static void __exit
+fore200e_module_cleanup(void)
{
while (fore200e_boards) {
fore200e_cleanup(&fore200e_boards);
}
DPRINTK(1, "module being removed\n");
}
+
+module_init(fore200e_module_init);
+module_exit(fore200e_module_cleanup);
#endif
+/* $Id: fore200e.h,v 1.4 2000/04/14 10:10:34 davem Exp $ */
#ifndef _FORE200E_H
#define _FORE200E_H
# else
/* in that case, we'll need to add an extra indirection, e.g.
fore200e->bus->dma_direction[ fore200e_dma_direction ] */
-# error PCI and SBUS DMA direction flags differ!
+# error PCI and SBUS DMA direction flags have different values!
# endif
# else
-# define FORE200E_DMA_BIDIRECTIONAL SBA_DMA_BIDIRECTIONAL
-# define FORE200E_DMA_TODEVICE SBA_DMA_TODEVICE
-# define FORE200E_DMA_FROMDEVICE SBA_DMA_FROMDEVICE
+# define FORE200E_DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL
+# define FORE200E_DMA_TODEVICE SBUS_DMA_TODEVICE
+# define FORE200E_DMA_FROMDEVICE SBUS_DMA_FROMDEVICE
# endif
#else
+# ifndef CONFIG_ATM_FORE200E_PCA
+# warning compiling the fore200e driver without any hardware support enabled!
+# include <linux/pci.h>
+# endif
# define FORE200E_DMA_BIDIRECTIONAL PCI_DMA_BIDIRECTIONAL
# define FORE200E_DMA_TODEVICE PCI_DMA_TODEVICE
# define FORE200E_DMA_FROMDEVICE PCI_DMA_FROMDEVICE
struct stats* stats; /* last snapshot of the stats */
struct semaphore rate_sf; /* protects rate reservation ops */
- spinlock_t tx_lock; /* protects tx ops */
+ struct tasklet_struct tasklet; /* performs interrupt work */
} fore200e_t;
return -EINVAL;
}
+ // prevent module unload while sleeping (kmalloc)
+ // doing this any earlier would complicate more error return paths
+ MOD_INC_USE_COUNT;
+
// get space for our vcc stuff and copy parameters into it
vccp = kmalloc (sizeof(hrz_vcc), GFP_KERNEL);
if (!vccp) {
PRINTK (KERN_ERR, "out of memory!");
+ MOD_DEC_USE_COUNT;
return -ENOMEM;
}
*vccp = vcc;
if (error) {
PRINTD (DBG_QOS|DBG_VCC, "insufficient cell rate resources");
kfree (vccp);
+ MOD_DEC_USE_COUNT;
return error;
}
if (rxtp->traffic_class != ATM_NONE) {
if (dev->rxer[channel]) {
PRINTD (DBG_ERR|DBG_VCC, "VC already open for RX");
- return -EBUSY;
+ error = -EBUSY;
}
- error = hrz_open_rx (dev, channel);
+ if (!error)
+ error = hrz_open_rx (dev, channel);
if (error) {
kfree (vccp);
+ MOD_DEC_USE_COUNT;
return error;
}
// this link allows RX frames through
// indicate readiness
set_bit(ATM_VF_READY,&atm_vcc->flags);
- MOD_INC_USE_COUNT;
return 0;
}
return fetch_stats(dev,(struct sonet_stats *) arg,
cmd == SONET_GETSTATZ);
case SONET_SETFRAMING:
- return set_framing(dev,(int) arg);
+ return set_framing(dev,(int) (long) arg);
case SONET_GETFRAMING:
return put_user(PRIV(dev)->framing,(int *) arg) ?
-EFAULT : 0;
if ((cdi = cdrom_find_device(dev)) == NULL)
return -ENODEV;
- /* just CD-RW for now. DVD-RW will come soon, CD-R and DVD-R
- * need to be handled differently. */
- if ((fp->f_mode & FMODE_WRITE) && !CDROM_CAN(CDC_CD_RW))
- return -EROFS;
+ if (fp->f_mode & FMODE_WRITE)
+ return -EROFS;
/* if this was a O_NONBLOCK open and we should honor the flags,
* do a quick open without drive/disc integrity checks. */
if (tracks.data > 0) return CDS_DATA_1;
/* Policy mode off */
- cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognise!\n");
+ cdinfo(CD_WARNING,"This disc doesn't have any tracks I recognize!\n");
return CDS_NO_INFO;
}
initialized = 1;
}
-#endif /* endif CONFIG_SYSCTL */
-
-#ifdef MODULE
static void cdrom_sysctl_unregister(void)
{
-#ifdef CONFIG_SYSCTL
unregister_sysctl_table(cdrom_sysctl_header);
-#endif
}
-int init_module(void)
+#endif /* CONFIG_SYSCTL */
+
+static int cdrom_init(void)
{
#ifdef CONFIG_SYSCTL
cdrom_sysctl_register();
#endif
- devfs_handle = devfs_mk_dir (NULL, "cdroms", 6, NULL);
+ devfs_handle = devfs_mk_dir(NULL, "cdroms", 6, NULL);
return 0;
}
-void cleanup_module(void)
+static void cdrom_exit(void)
{
printk(KERN_INFO "Uniform CD-ROM driver unloaded\n");
#ifdef CONFIG_SYSCTL
cdrom_sysctl_unregister();
-#endif /* CONFIG_SYSCTL */
- devfs_unregister (devfs_handle);
+#endif
+ devfs_unregister(devfs_handle);
}
-#endif /* endif MODULE */
+module_init(cdrom_init);
+module_exit(cdrom_exit);
*
* Revision history:
* $Log: sx.c,v $
- * Revision 1.32 2000/03/07 90:00:00 wolff,pvdl
+ * Revision 1.33 2000/03/09 10:00:00 pvdl,wolff
+ * - Fixed module and port counting
+ * - Fixed signal handling
+ * - Fixed an Ooops
+ *
+ * Revision 1.32 2000/03/07 09:00:00 wolff,pvdl
* - Fixed some sx_dprintk typos
* - added detection for an invalid board/module configuration
*
* */
-#define RCS_ID "$Id: sx.c,v 1.32 2000/03/07 17:01:02 wolff, pvdl Exp $"
-#define RCS_REV "$Revision: 1.32 $"
+#define RCS_ID "$Id: sx.c,v 1.33 2000/03/08 10:01:02 wolff, pvdl Exp $"
+#define RCS_REV "$Revision: 1.33 $"
#include <linux/module.h>
#include "sxboards.h"
#include "sxwindow.h"
-#include <linux/generic_serial.h>
+
#include <linux/compatmac.h>
+#include <linux/generic_serial.h>
#include "sx.h"
if you want more than 4 boards. */
-
/* Why the hell am I defining these here? */
#define SX_TYPE_NORMAL 1
#define SX_TYPE_CALLOUT 2
+
#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
#endif
if (rts >= 0) t = rts? (t | OP_RTS): (t & ~OP_RTS);
sx_write_channel_byte (port, hi_op, t);
sx_dprintk (SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
+
func_exit ();
}
func_enter2();
+ if (!port->gs.tty)
+ return 0;
+
/* What is this doing here? -- REW
Ha! figured it out. It is to allow you to get DTR active again
if you've dropped it with stty 0. Moved to set_baud, where it
sx_disable_tx_interrupts (port);
}
- if (port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+ if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {
if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
port->gs.tty->ldisc.write_wakeup)
(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
sx_interrupt (0, board, NULL);
+ init_timer(&board->timer);
+
board->timer.expires = jiffies + sx_poll;
add_timer (&board->timer);
func_exit ();
func_enter();
port->gs.flags &= ~ GS_ACTIVE;
- if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
+ if (port->gs.tty && (port->gs.tty->termios->c_cflag & HUPCL)) {
sx_setsignals (port, 0, 0);
sx_reconfigure_port(port);
}
tty->driver_data = port;
port->gs.tty = tty;
+ if (!port->gs.count)
+ MOD_INC_USE_COUNT;
port->gs.count++;
sx_dprintk (SX_DEBUG_OPEN, "starting port\n");
sx_dprintk (SX_DEBUG_OPEN, "done gs_init\n");
if (retval) {
port->gs.count--;
+ if (port->gs.count) MOD_DEC_USE_COUNT;
return retval;
}
port->gs.flags |= GS_ACTIVE;
sx_setsignals (port, 1,1);
- sx_dprintk (SX_DEBUG_OPEN, "before inc_use_count (count=%d.\n",
- port->gs.count);
- if (port->gs.count == 1) {
- MOD_INC_USE_COUNT;
- }
- sx_dprintk (SX_DEBUG_OPEN, "after inc_use_count\n");
-
#if 0
if (sx_debug & SX_DEBUG_OPEN)
my_hd ((unsigned char *)port, sizeof (*port));
if (sx_send_command (port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
printk (KERN_ERR "sx: Card didn't respond to LOPEN command.\n");
- MOD_DEC_USE_COUNT;
port->gs.count--;
+ if (!port->gs.count) MOD_DEC_USE_COUNT;
return -EIO;
}
retval, port->gs.count);
if (retval) {
- MOD_DEC_USE_COUNT;
- port->gs.count--;
+ /*
+ * Don't lower gs.count here because sx_close() will be called later
+ */
+
return retval;
}
/* tty->low_latency = 1; */
exit minicom. I expect an "oops". -- REW */
static void sx_hungup (void *ptr)
{
+ struct sx_port *port = ptr;
func_enter ();
+
+ sx_setsignals (port, 0, 0);
+ sx_reconfigure_port(port);
+ sx_send_command (port, HS_CLOSE, 0, 0);
+
+ if (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED) {
+ if (sx_send_command (port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED) != 1) {
+ printk (KERN_ERR
+ "sx: sent the force_close command, but card didn't react\n");
+ } else
+ sx_dprintk (SX_DEBUG_CLOSE, "sent the force_close command.\n");
+ }
+
MOD_DEC_USE_COUNT;
func_exit ();
}
int to = 5 * HZ;
func_enter ();
+
+ sx_setsignals (port, 0, 0);
+ sx_reconfigure_port(port);
sx_send_command (port, HS_CLOSE, 0, 0);
while (to-- && (sx_read_channel_byte (port, hi_hstat) != HS_IDLE_CLOSED)) {
sx_dprintk (SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
5 * HZ - to - 1, port->gs.count);
+ if(port->gs.count) {
+ sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n", port->gs.count);
+ port->gs.count = 0;
+ }
+
MOD_DEC_USE_COUNT;
func_exit ();
}
define_bool CONFIG_IDEDMA_PCI_EXPERIMENTAL $CONFIG_EXPERIMENTAL
dep_bool ' ATA Work(s) In Progress (EXPERIMENTAL)' CONFIG_IDEDMA_PCI_WIP $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_EXPERIMENTAL
dep_bool ' Good-Bad DMA Model-Firmware (WIP)' CONFIG_IDEDMA_NEW_DRIVE_LISTINGS $CONFIG_IDEDMA_PCI_WIP
- dep_bool ' AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210 $CONFIG_BLK_DEV_IDEDMA_PCI
- dep_mbool ' AEC6210 Tuning support (WIP)' CONFIG_AEC6210_TUNING $CONFIG_BLK_DEV_AEC6210 $CONFIG_IDEDMA_PCI_WIP
+ dep_bool ' AEC62XX chipset support' CONFIG_BLK_DEV_AEC62XX $CONFIG_BLK_DEV_IDEDMA_PCI
+ dep_mbool ' AEC62XX Tuning support (WIP)' CONFIG_AEC62XX_TUNING $CONFIG_BLK_DEV_AEC62XX $CONFIG_IDEDMA_PCI_WIP
dep_bool ' ALI M15x3 chipset support' CONFIG_BLK_DEV_ALI15X3 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_mbool ' ALI M15x3 WDC support (DANGEROUS)' CONFIG_WDC_ALI15X3 $CONFIG_BLK_DEV_ALI15X3
dep_bool ' AMD Viper support' CONFIG_BLK_DEV_AMD7409 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' SiS5513 chipset support' CONFIG_BLK_DEV_SIS5513 $CONFIG_BLK_DEV_IDEDMA_PCI $CONFIG_X86
dep_bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 $CONFIG_BLK_DEV_IDEDMA_PCI
dep_bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX $CONFIG_BLK_DEV_IDEDMA_PCI
+ dep_mbool ' VIA82CXXX Tuning support (WIP)' CONFIG_VIA82CXXX_TUNING $CONFIG_BLK_DEV_VIA82CXXX $CONFIG_IDEDMA_PCI_WIP
fi
if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then
bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
fi
if [ "$CONFIG_IDE_CHIPSETS" = "y" -o \
- "$CONFIG_BLK_DEV_AEC6210" = "y" -o \
+ "$CONFIG_BLK_DEV_AEC62XX" = "y" -o \
"$CONFIG_BLK_DEV_ALI15X3" = "y" -o \
"$CONFIG_BLK_DEV_AMD7409" = "y" -o \
"$CONFIG_BLK_DEV_CMD640" = "y" -o \
"$CONFIG_BLK_DEV_PDC202XX" = "y" -o \
"$CONFIG_BLK_DEV_PIIX" = "y" -o \
"$CONFIG_BLK_DEV_SIS5513" = "y" -o \
- "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then
+ "$CONFIG_BLK_DEV_SL82C105" = "y" -o \
+ "$CONFIG_BLK_DEV_VIA82CXXX" = "y" ]; then
define_bool CONFIG_BLK_DEV_IDE_MODES y
else
define_bool CONFIG_BLK_DEV_IDE_MODES n
LX_OBJS :=
MX_OBJS :=
-ifeq ($(CONFIG_BLK_DEV_AEC6210),y)
-IDE_OBJS += aec6210.o
+ifeq ($(CONFIG_BLK_DEV_AEC62XX),y)
+IDE_OBJS += aec62xx.o
endif
ifeq ($(CONFIG_BLK_DEV_ALI14XX),y)
+++ /dev/null
-/*
- * linux/drivers/ide/aec6210.c Version 0.06 Mar. 18, 2000
- *
- * Copyright (C) 1998-2000 Andre Hedrick (andre@suse.com)
- * May be copied or modified under the terms of the GNU General Public License
- *
- * pio 0 :: 40: 00 07 00 00 00 00 00 00 02 07 a6 04 00 02 00 02
- * pio 1 :: 40: 0a 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
- * pio 2 :: 40: 08 07 00 00 00 00 00 00 02 07 a6 05 00 02 00 02
- * pio 3 :: 40: 03 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * pio 4 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * dma 0 :: 40: 0a 07 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * dma 1 :: 40: 02 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * dma 2 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * 50: ff ff ff ff 00 06 04 00 00 00 00 00 00 00 00 00
- *
- * udma 0 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
- *
- * udma 1 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * 50: ff ff ff ff 01 06 04 00 00 00 00 00 00 00 00 00
- *
- * udma 2 :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
- *
- * auto :: 40: 01 04 00 00 00 00 00 00 02 05 a6 05 00 02 00 02
- * 50: ff ff ff ff 02 06 04 00 00 00 00 00 00 00 00 00
- *
- * auto :: 40: 01 04 01 04 01 04 01 04 02 05 a6 cf 00 02 00 02
- * 50: ff ff ff ff aa 06 04 00 00 00 00 00 00 00 00 00
- *
- * NO-Devices
- * 40: 00 00 00 00 00 00 00 00 02 05 a6 00 00 02 00 02
- * 50: ff ff ff ff 00 06 00 00 00 00 00 00 00 00 00 00
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include "ide_modes.h"
-
-#define ACARD_DEBUG_DRIVE_INFO 0
-
-#undef DISPLAY_AEC6210_TIMINGS
-
-#if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS)
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-
-static int aec6210_get_info(char *, char **, off_t, int);
-extern int (*aec6210_display_info)(char *, char **, off_t, int); /* ide-proc.c */
-extern char *ide_media_verbose(ide_drive_t *);
-static struct pci_dev *bmide_dev;
-
-static int aec6210_get_info (char *buffer, char **addr, off_t offset, int count)
-{
- char *p = buffer;
-
- u32 bibma = bmide_dev->resource[4].start;
- u8 c0 = 0, c1 = 0;
-
- p += sprintf(p, "\n AEC6210 Chipset.\n");
-
- /*
- * at that point bibma+0x2 et bibma+0xa are byte registers
- * to investigate:
- */
- c0 = inb_p((unsigned short)bibma + 0x02);
- c1 = inb_p((unsigned short)bibma + 0x0a);
-
- p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
- p += sprintf(p, " %sabled %sabled\n",
- (c0&0x80) ? "dis" : " en",
- (c1&0x80) ? "dis" : " en");
- p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
- p += sprintf(p, "DMA enabled: %s %s %s %s\n",
- (c0&0x20) ? "yes" : "no ", (c0&0x40) ? "yes" : "no ",
- (c1&0x20) ? "yes" : "no ", (c1&0x40) ? "yes" : "no " );
-
- p += sprintf(p, "UDMA\n");
- p += sprintf(p, "DMA\n");
- p += sprintf(p, "PIO\n");
- return p-buffer;/* => must be less than 4k! */
-}
-#endif /* defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS) */
-
-byte aec6210_proc = 0;
-
-#ifdef CONFIG_AEC6210_TUNING
-
-struct chipset_bus_clock_list_entry {
- byte xfer_speed;
- unsigned short chipset_settings;
- byte ultra_settings;
-};
-
-struct chipset_bus_clock_list_entry aec6210_base [] = {
- { XFER_UDMA_2, 0x0401, 0x02 },
- { XFER_UDMA_1, 0x0401, 0x01 },
- { XFER_UDMA_0, 0x0401, 0x01 },
-
- { XFER_MW_DMA_2, 0x0401, 0x00 },
- { XFER_MW_DMA_1, 0x0402, 0x00 },
- { XFER_MW_DMA_0, 0x070a, 0x00 },
-
- { XFER_PIO_4, 0x0401, 0x00 },
- { XFER_PIO_3, 0x0403, 0x00 },
- { XFER_PIO_2, 0x0708, 0x00 },
- { XFER_PIO_1, 0x070a, 0x00 },
- { XFER_PIO_0, 0x0700, 0x00 },
- { 0, 0x0000, 0x00 }
-};
-
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-/*
- * TO DO: active tuning and correction of cards without a bios.
- */
-
-static unsigned short pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
-{
- for ( ; chipset_table->xfer_speed ; chipset_table++)
- if (chipset_table->xfer_speed == speed) {
- return chipset_table->chipset_settings;
- }
- return 0x0000;
-}
-
-static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
-{
- for ( ; chipset_table->xfer_speed ; chipset_table++)
- if (chipset_table->xfer_speed == speed) {
- return chipset_table->ultra_settings;
- }
- return 0x00;
-}
-
-static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
-{
- ide_hwif_t *hwif = HWIF(drive);
-
- int err;
- byte drive_pci;
- unsigned short drive_conf = 0x0000;
- byte ultra = 0x00, ultra_conf = 0x00;
- byte tmp1 = 0x00, tmp2 = 0x00;
-
- int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-
- switch(drive_number) {
- case 0: drive_pci = 0x40; break;
- case 1: drive_pci = 0x42; break;
- case 2: drive_pci = 0x44; break;
- case 3: drive_pci = 0x46; break;
- default: return -1;
- }
-
- pci_read_config_word(HWIF(drive)->pci_dev, drive_pci, &drive_conf);
- drive_conf = pci_bus_clock_list(speed, aec6210_base);
- pci_write_config_word(HWIF(drive)->pci_dev, drive_pci, drive_conf);
-
- pci_read_config_byte(HWIF(drive)->pci_dev, 0x54, &ultra);
- tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
- ultra_conf = pci_bus_clock_list_ultra(speed, aec6210_base);
- tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
- pci_write_config_byte(HWIF(drive)->pci_dev, 0x54, tmp2);
-
- err = ide_config_drive_speed(drive, speed);
-
-#if ACARD_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d 0x04%x 0x02%x 0x02%x 0x02%x 0x02%x\n",
- drive->name, ide_xfer_verbose(speed), drive_number,
- drive_conf, ultra, tmp1, ultra_conf, tmp2);
-#endif /* ACARD_DEBUG_DRIVE_INFO */
-
- return(err);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
-{
- struct hd_driveid *id = drive->id;
- byte speed = -1;
-
- if (drive->media != ide_disk)
- return ((int) ide_dma_off_quietly);
-
- if (((id->dma_ultra & 0x0010) ||
- (id->dma_ultra & 0x0008) ||
- (id->dma_ultra & 0x0004)) && (ultra)) {
- speed = XFER_UDMA_2;
- } else if ((id->dma_ultra & 0x0002) && (ultra)) {
- speed = XFER_UDMA_1;
- } else if ((id->dma_ultra & 0x0001) && (ultra)) {
- speed = XFER_UDMA_0;
- } else if (id->dma_mword & 0x0004) {
- speed = XFER_MW_DMA_2;
- } else if (id->dma_mword & 0x0002) {
- speed = XFER_MW_DMA_1;
- } else if (id->dma_mword & 0x0001) {
- speed = XFER_MW_DMA_0;
- } else if (id->dma_1word & 0x0004) {
- speed = XFER_SW_DMA_2;
- } else if (id->dma_1word & 0x0002) {
- speed = XFER_SW_DMA_1;
- } else if (id->dma_1word & 0x0001) {
- speed = XFER_SW_DMA_0;
- } else {
- return ((int) ide_dma_off_quietly);
- }
- (void) aec6210_tune_chipset(drive, speed);
-
- return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off :
- ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
- ((id->dma_mword >> 8) & 7) ? ide_dma_on :
- ((id->dma_1word >> 8) & 7) ? ide_dma_on :
- ide_dma_off_quietly);
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-
-static void aec6210_tune_drive (ide_drive_t *drive, byte pio)
-{
- byte speed;
-
- switch(pio) {
- case 5:
- speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
- case 4:
- speed = XFER_PIO_4; break;
- case 3:
- speed = XFER_PIO_3; break;
- case 2:
- speed = XFER_PIO_2; break;
- case 1:
- speed = XFER_PIO_1; break;
- default:
- speed = XFER_PIO_0; break;
- }
- (void) aec6210_tune_chipset(drive, speed);
-}
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int config_drive_xfer_rate (ide_drive_t *drive)
-{
- struct hd_driveid *id = drive->id;
- ide_dma_action_t dma_func = ide_dma_on;
-
- if (id && (id->capability & 1) && HWIF(drive)->autodma) {
- /* Consult the list of known "bad" drives */
- if (ide_dmaproc(ide_dma_bad_drive, drive)) {
- dma_func = ide_dma_off;
- goto fast_ata_pio;
- }
- dma_func = ide_dma_off_quietly;
- if (id->field_valid & 4) {
- if (id->dma_ultra & 0x001F) {
- /* Force if Capable UltraDMA */
- dma_func = config_chipset_for_dma(drive, 1);
- if ((id->field_valid & 2) &&
- (dma_func != ide_dma_on))
- goto try_dma_modes;
- }
- } else if (id->field_valid & 2) {
-try_dma_modes:
- if ((id->dma_mword & 0x0007) ||
- (id->dma_1word & 0x0007)) {
- /* Force if Capable regular DMA modes */
- dma_func = config_chipset_for_dma(drive, 0);
- if (dma_func != ide_dma_on)
- goto no_dma_set;
- }
- } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
- if (id->eide_dma_time > 150) {
- goto no_dma_set;
- }
- /* Consult the list of known "good" drives */
- dma_func = config_chipset_for_dma(drive, 0);
- if (dma_func != ide_dma_on)
- goto no_dma_set;
- } else {
- goto fast_ata_pio;
- }
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
- dma_func = ide_dma_off_quietly;
-no_dma_set:
- aec6210_tune_drive(drive, 5);
- }
- return HWIF(drive)->dmaproc(dma_func, drive);
-}
-
-/*
- * aec6210_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
- */
-int aec6210_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
-{
- switch (func) {
- case ide_dma_check:
- return config_drive_xfer_rate(drive);
- default:
- break;
- }
- return ide_dmaproc(func, drive); /* use standard DMA stuff */
-}
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-#endif /* CONFIG_AEC6210_TUNING */
-
-unsigned int __init pci_init_aec6210 (struct pci_dev *dev, const char *name)
-{
- if (dev->resource[PCI_ROM_RESOURCE].start) {
- pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
- printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
- }
-
-#if defined(DISPLAY_AEC6210_TIMINGS) && defined(CONFIG_PROC_FS)
- aec6210_proc = 1;
- bmide_dev = dev;
- aec6210_display_info = &aec6210_get_info;
-#endif /* DISPLAY_AEC6210_TIMINGS && CONFIG_PROC_FS */
-
- return dev->irq;
-}
-
-void __init ide_init_aec6210 (ide_hwif_t *hwif)
-{
-#ifdef CONFIG_AEC6210_TUNING
- hwif->tuneproc = &aec6210_tune_drive;
- hwif->drives[0].autotune = 1;
- hwif->drives[1].autotune = 1;
-
-#ifdef CONFIG_BLK_DEV_IDEDMA
- if (hwif->dma_base)
- hwif->dmaproc = &aec6210_dmaproc;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
-#endif /* CONFIG_AEC6210_TUNING */
-}
-
-void __init ide_dmacapable_aec6210 (ide_hwif_t *hwif, unsigned long dmabase)
-{
- byte dma_new = 0;
- byte dma_old = inb(dmabase+2);
- byte reg54h = 0;
- byte masterdma = hwif->channel ? 0x30 : 0x03;
- byte slavedma = hwif->channel ? 0xc0 : 0x0c;
- unsigned long flags;
-
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
-
- dma_new = dma_old;
-
- pci_read_config_byte(hwif->pci_dev, 0x54, ®54h);
-
- if (reg54h & masterdma) dma_new |= 0x20;
- if (reg54h & slavedma) dma_new |= 0x40;
- if (dma_new != dma_old) outb(dma_new, dmabase+2);
-
- __restore_flags(flags); /* local CPU only */
-
- ide_setup_dma(hwif, dmabase, 8);
-}
--- /dev/null
+/*
+ * linux/drivers/ide/aec62xx.c Version 0.08 Mar. 28, 2000
+ *
+ * Copyright (C) 2000 Andre Hedrick (andre@suse.com)
+ * May be copied or modified under the terms of the GNU General Public License
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "ide_modes.h"
+
+#define DISPLAY_AEC62XX_TIMINGS
+
+#ifndef HIGH_4
+#define HIGH_4(H) ((H)=(H>>4))
+#endif
+#ifndef LOW_4
+#define LOW_4(L) ((L)=(L-((L>>4)<<4)))
+#endif
+#ifndef SPLIT_BYTE
+#define SPLIT_BYTE(B,H,L) ((H)=(B>>4), (L)=(B-((B>>4)<<4)))
+#endif
+#ifndef MAKE_WORD
+#define MAKE_WORD(W,HB,LB) ((W)=((HB<<8)+LB))
+#endif
+
+
+#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+
+static int aec62xx_get_info(char *, char **, off_t, int);
+extern int (*aec62xx_display_info)(char *, char **, off_t, int); /* ide-proc.c */
+extern char *ide_media_verbose(ide_drive_t *);
+static struct pci_dev *bmide_dev;
+
+static int aec62xx_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+ char *p = buffer;
+
+ u32 bibma = bmide_dev->resource[4].start;
+ u8 c0 = 0, c1 = 0;
+ u8 art = 0, uart = 0;
+
+ switch(bmide_dev->device) {
+ case PCI_DEVICE_ID_ARTOP_ATP850UF:
+ p += sprintf(p, "\n AEC6210 Chipset.\n");
+ break;
+ case PCI_DEVICE_ID_ARTOP_ATP860:
+ p += sprintf(p, "\n AEC6260 No Bios Chipset.\n");
+ break;
+ case PCI_DEVICE_ID_ARTOP_ATP860R:
+ p += sprintf(p, "\n AEC6260 Chipset.\n");
+ break;
+ default:
+ p += sprintf(p, "\n AEC62?? Chipset.\n");
+ break;
+ }
+
+ /*
+ * at that point bibma+0x2 et bibma+0xa are byte registers
+ * to investigate:
+ */
+ c0 = inb_p((unsigned short)bibma + 0x02);
+ c1 = inb_p((unsigned short)bibma + 0x0a);
+
+ p += sprintf(p, "--------------- Primary Channel ---------------- Secondary Channel -------------\n");
+ (void) pci_read_config_byte(bmide_dev, 0x4a, &art);
+ p += sprintf(p, " %sabled %sabled\n",
+ (art&0x02)?" en":"dis",(art&0x04)?" en":"dis");
+ p += sprintf(p, "--------------- drive0 --------- drive1 -------- drive0 ---------- drive1 ------\n");
+ p += sprintf(p, "DMA enabled: %s %s %s %s\n",
+ (c0&0x20)?"yes":"no ",(c0&0x40)?"yes":"no ",(c1&0x20)?"yes":"no ",(c1&0x40)?"yes":"no ");
+
+ switch(bmide_dev->device) {
+ case PCI_DEVICE_ID_ARTOP_ATP850UF:
+ (void) pci_read_config_byte(bmide_dev, 0x54, &art);
+ p += sprintf(p, "DMA Mode: %s(%s) %s(%s) %s(%s) %s(%s)\n",
+ (c0&0x20)?((art&0x03)?"UDMA":" DMA"):" PIO",
+ (art&0x02)?"2":(art&0x01)?"1":"0",
+ (c0&0x40)?((art&0x0c)?"UDMA":" DMA"):" PIO",
+ (art&0x08)?"2":(art&0x04)?"1":"0",
+ (c1&0x20)?((art&0x30)?"UDMA":" DMA"):" PIO",
+ (art&0x20)?"2":(art&0x10)?"1":"0",
+ (c1&0x40)?((art&0xc0)?"UDMA":" DMA"):" PIO",
+ (art&0x80)?"2":(art&0x40)?"1":"0");
+ (void) pci_read_config_byte(bmide_dev, 0x40, &art);
+ p += sprintf(p, "Active: 0x%02x", art);
+ (void) pci_read_config_byte(bmide_dev, 0x42, &art);
+ p += sprintf(p, " 0x%02x", art);
+ (void) pci_read_config_byte(bmide_dev, 0x44, &art);
+ p += sprintf(p, " 0x%02x", art);
+ (void) pci_read_config_byte(bmide_dev, 0x46, &art);
+ p += sprintf(p, " 0x%02x\n", art);
+ (void) pci_read_config_byte(bmide_dev, 0x41, &art);
+ p += sprintf(p, "Recovery: 0x%02x", art);
+ (void) pci_read_config_byte(bmide_dev, 0x43, &art);
+ p += sprintf(p, " 0x%02x", art);
+ (void) pci_read_config_byte(bmide_dev, 0x45, &art);
+ p += sprintf(p, " 0x%02x", art);
+ (void) pci_read_config_byte(bmide_dev, 0x47, &art);
+ p += sprintf(p, " 0x%02x\n", art);
+ break;
+ case PCI_DEVICE_ID_ARTOP_ATP860:
+ case PCI_DEVICE_ID_ARTOP_ATP860R:
+ (void) pci_read_config_byte(bmide_dev, 0x44, &art);
+ p += sprintf(p, "DMA Mode: %s(%s) %s(%s)",
+ (c0&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
+ ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?",
+ (c0&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
+ ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?");
+ (void) pci_read_config_byte(bmide_dev, 0x45, &art);
+ p += sprintf(p, " %s(%s) %s(%s)\n",
+ (c1&0x20)?((art&0x07)?"UDMA":" DMA"):" PIO",
+ ((art&0x06)==0x06)?"4":((art&0x05)==0x05)?"4":((art&0x04)==0x04)?"3":((art&0x03)==0x03)?"2":((art&0x02)==0x02)?"1":((art&0x01)==0x01)?"0":"?",
+ (c1&0x40)?((art&0x70)?"UDMA":" DMA"):" PIO",
+ ((art&0x60)==0x60)?"4":((art&0x50)==0x50)?"4":((art&0x40)==0x40)?"3":((art&0x30)==0x30)?"2":((art&0x20)==0x20)?"1":((art&0x10)==0x10)?"0":"?");
+ (void) pci_read_config_byte(bmide_dev, 0x40, &art);
+ p += sprintf(p, "Active: 0x%02x", HIGH_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x41, &art);
+ p += sprintf(p, " 0x%02x", HIGH_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x42, &art);
+ p += sprintf(p, " 0x%02x", HIGH_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x43, &art);
+ p += sprintf(p, " 0x%02x\n", HIGH_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x40, &art);
+ p += sprintf(p, "Recovery: 0x%02x", LOW_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x41, &art);
+ p += sprintf(p, " 0x%02x", LOW_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x42, &art);
+ p += sprintf(p, " 0x%02x", LOW_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x43, &art);
+ p += sprintf(p, " 0x%02x\n", LOW_4(art));
+ (void) pci_read_config_byte(bmide_dev, 0x49, &uart);
+ p += sprintf(p, "reg49h = 0x%02x ", uart);
+ (void) pci_read_config_byte(bmide_dev, 0x4a, &uart);
+ p += sprintf(p, "reg4ah = 0x%02x\n", uart);
+ break;
+ default:
+ break;
+ }
+
+ return p-buffer;/* => must be less than 4k! */
+}
+#endif /* defined(DISPLAY_AEC62xx_TIMINGS) && defined(CONFIG_PROC_FS) */
+
+byte aec62xx_proc = 0;
+
+#ifdef CONFIG_AEC62XX_TUNING
+
+struct chipset_bus_clock_list_entry {
+ byte xfer_speed;
+
+ byte chipset_settings_34;
+ byte ultra_settings_34;
+
+ byte chipset_settings_33;
+ byte ultra_settings_33;
+};
+
+struct chipset_bus_clock_list_entry aec62xx_base [] = {
+ { XFER_UDMA_4, 0x41, 0x04, 0x31, 0x05 },
+ { XFER_UDMA_3, 0x41, 0x03, 0x31, 0x04 },
+ { XFER_UDMA_2, 0x41, 0x02, 0x31, 0x03 },
+ { XFER_UDMA_1, 0x41, 0x01, 0x31, 0x02 },
+ { XFER_UDMA_0, 0x41, 0x01, 0x31, 0x01 },
+
+ { XFER_MW_DMA_2, 0x41, 0x00, 0x31, 0x00 },
+ { XFER_MW_DMA_1, 0x42, 0x00, 0x31, 0x00 },
+ { XFER_MW_DMA_0, 0x7a, 0x00, 0x0a, 0x00 },
+
+ { XFER_PIO_4, 0x41, 0x00, 0x31, 0x00 },
+ { XFER_PIO_3, 0x43, 0x00, 0x33, 0x00 },
+ { XFER_PIO_2, 0x78, 0x00, 0x08, 0x00 },
+ { XFER_PIO_1, 0x7a, 0x00, 0x0a, 0x00 },
+ { XFER_PIO_0, 0x70, 0x00, 0x00, 0x00 },
+ { 0, 0x00, 0x00, 0x00, 0x00 }
+};
+
+extern char *ide_xfer_verbose (byte xfer_rate);
+
+/*
+ * TO DO: active tuning and correction of cards without a bios.
+ */
+
+static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+ for ( ; chipset_table->xfer_speed ; chipset_table++)
+ if (chipset_table->xfer_speed == speed) {
+ return ((byte) ((1) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
+ }
+ return 0x00;
+}
+
+static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+{
+ for ( ; chipset_table->xfer_speed ; chipset_table++)
+ if (chipset_table->xfer_speed == speed) {
+ return ((byte) ((1) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
+ }
+ return 0x00;
+}
+
+static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+ byte unit = (drive->select.b.unit & 0x01);
+ int drive_number = ((hwif->channel ? 2 : 0) + unit);
+ int err = 0;
+ unsigned short d_conf = 0x0000;
+ byte ultra = 0x00;
+ byte ultra_conf = 0x00;
+ byte tmp0 = 0x00;
+ byte tmp1 = 0x00;
+ byte tmp2 = 0x00;
+ unsigned long flags;
+
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
+
+ pci_read_config_word(dev, 0x40|(2*drive_number), &d_conf);
+ tmp0 = pci_bus_clock_list(speed, aec62xx_base);
+ SPLIT_BYTE(tmp0,tmp1,tmp2);
+ MAKE_WORD(d_conf,tmp1,tmp2);
+ pci_write_config_word(dev, 0x40|(2*drive_number), d_conf);
+
+ tmp1 = 0x00;
+ tmp2 = 0x00;
+ pci_read_config_byte(dev, 0x54, &ultra);
+ tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
+ ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
+ tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
+ pci_write_config_byte(dev, 0x54, tmp2);
+
+ __restore_flags(flags); /* local CPU only */
+
+ err = ide_config_drive_speed(drive, speed);
+ return(err);
+}
+
+static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ struct pci_dev *dev = hwif->pci_dev;
+ byte unit = (drive->select.b.unit & 0x01);
+ int drive_number = ((hwif->channel ? 2 : 0) + unit);
+ byte ultra_pci = hwif->channel ? 0x45 : 0x44;
+ int err = 0;
+ byte drive_conf = 0x00;
+ byte ultra_conf = 0x00;
+ byte ultra = 0x00;
+ byte tmp1 = 0x00;
+ byte tmp2 = 0x00;
+
+ unsigned long flags;
+
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
+
+ pci_read_config_byte(dev, 0x40|drive_number, &drive_conf);
+ drive_conf = pci_bus_clock_list(speed, aec62xx_base);
+ pci_write_config_byte(dev, 0x40|drive_number, drive_conf);
+
+ pci_read_config_byte(dev, ultra_pci, &ultra);
+ tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
+ ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
+ tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
+ pci_write_config_byte(dev, ultra_pci, tmp2);
+ __restore_flags(flags); /* local CPU only */
+
+ err = ide_config_drive_speed(drive, speed);
+ return(err);
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+ struct hd_driveid *id = drive->id;
+ ide_hwif_t *hwif = HWIF(drive);
+ byte unit = (drive->select.b.unit & 0x01);
+ unsigned long dma_base = hwif->dma_base;
+ byte speed = -1;
+
+ if (drive->media != ide_disk)
+ return ((int) ide_dma_off_quietly);
+
+ if (((id->dma_ultra & 0x0010) ||
+ (id->dma_ultra & 0x0008) ||
+ (id->dma_ultra & 0x0004)) && (ultra)) {
+ speed = XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ speed = XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ speed = XFER_UDMA_0;
+ } else if (id->dma_mword & 0x0004) {
+ speed = XFER_MW_DMA_2;
+ } else if (id->dma_mword & 0x0002) {
+ speed = XFER_MW_DMA_1;
+ } else if (id->dma_mword & 0x0001) {
+ speed = XFER_MW_DMA_0;
+ } else if (id->dma_1word & 0x0004) {
+ speed = XFER_SW_DMA_2;
+ } else if (id->dma_1word & 0x0002) {
+ speed = XFER_SW_DMA_1;
+ } else if (id->dma_1word & 0x0001) {
+ speed = XFER_SW_DMA_0;
+ } else {
+ return ((int) ide_dma_off_quietly);
+ }
+
+ outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+ (void) aec6210_tune_chipset(drive, speed);
+
+ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_off :
+ ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+ ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+ ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+ ide_dma_off_quietly);
+}
+
+static int config_aec6260_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+ struct hd_driveid *id = drive->id;
+ ide_hwif_t *hwif = HWIF(drive);
+ byte unit = (drive->select.b.unit & 0x01);
+ unsigned long dma_base = hwif->dma_base;
+ byte speed = -1;
+ byte ultra66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+
+ if (drive->media != ide_disk)
+ return ((int) ide_dma_off_quietly);
+
+ if ((id->dma_ultra & 0x0010) && (ultra) && (ultra66)) {
+ speed = XFER_UDMA_4;
+ } else if ((id->dma_ultra & 0x0008) && (ultra) && (ultra66)) {
+ speed = XFER_UDMA_3;
+ } else if ((id->dma_ultra & 0x0004) && (ultra)) {
+ speed = XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ speed = XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ speed = XFER_UDMA_0;
+ } else if (id->dma_mword & 0x0004) {
+ speed = XFER_MW_DMA_2;
+ } else if (id->dma_mword & 0x0002) {
+ speed = XFER_MW_DMA_1;
+ } else if (id->dma_mword & 0x0001) {
+ speed = XFER_MW_DMA_0;
+ } else if (id->dma_1word & 0x0004) {
+ speed = XFER_SW_DMA_2;
+ } else if (id->dma_1word & 0x0002) {
+ speed = XFER_SW_DMA_1;
+ } else if (id->dma_1word & 0x0001) {
+ speed = XFER_SW_DMA_0;
+ } else {
+ return ((int) ide_dma_off_quietly);
+ }
+
+ outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+ (void) aec6260_tune_chipset(drive, speed);
+
+ return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
+ ((id->dma_ultra >> 8) & 7) ? ide_dma_on :
+ ((id->dma_mword >> 8) & 7) ? ide_dma_on :
+ ((id->dma_1word >> 8) & 7) ? ide_dma_on :
+ ide_dma_off_quietly);
+}
+
+static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
+{
+ switch(HWIF(drive)->pci_dev->device) {
+ case PCI_DEVICE_ID_ARTOP_ATP850UF:
+ return config_aec6210_chipset_for_dma(drive, ultra);
+ case PCI_DEVICE_ID_ARTOP_ATP860:
+ case PCI_DEVICE_ID_ARTOP_ATP860R:
+ return config_aec6260_chipset_for_dma(drive, ultra);
+ default:
+ return ((int) ide_dma_off_quietly);
+ }
+}
+
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+static void aec62xx_tune_drive (ide_drive_t *drive, byte pio)
+{
+ byte speed;
+ byte new_pio = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+
+ switch(pio) {
+ case 5: speed = new_pio; break;
+ case 4: speed = XFER_PIO_4; break;
+ case 3: speed = XFER_PIO_3; break;
+ case 2: speed = XFER_PIO_2; break;
+ case 1: speed = XFER_PIO_1; break;
+ default: speed = XFER_PIO_0; break;
+ }
+
+ switch(HWIF(drive)->pci_dev->device) {
+ case PCI_DEVICE_ID_ARTOP_ATP850UF:
+ (void) aec6210_tune_chipset(drive, speed);
+ case PCI_DEVICE_ID_ARTOP_ATP860:
+ case PCI_DEVICE_ID_ARTOP_ATP860R:
+ (void) aec6260_tune_chipset(drive, speed);
+ default:
+ break;
+ }
+}
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+static int config_drive_xfer_rate (ide_drive_t *drive)
+{
+ struct hd_driveid *id = drive->id;
+ ide_dma_action_t dma_func = ide_dma_on;
+
+ if (id && (id->capability & 1) && HWIF(drive)->autodma) {
+ /* Consult the list of known "bad" drives */
+ if (ide_dmaproc(ide_dma_bad_drive, drive)) {
+ dma_func = ide_dma_off;
+ goto fast_ata_pio;
+ }
+ dma_func = ide_dma_off_quietly;
+ if (id->field_valid & 4) {
+ if (id->dma_ultra & 0x001F) {
+ /* Force if Capable UltraDMA */
+ dma_func = config_chipset_for_dma(drive, 1);
+ if ((id->field_valid & 2) &&
+ (dma_func != ide_dma_on))
+ goto try_dma_modes;
+ }
+ } else if (id->field_valid & 2) {
+try_dma_modes:
+ if ((id->dma_mword & 0x0007) ||
+ (id->dma_1word & 0x0007)) {
+ /* Force if Capable regular DMA modes */
+ dma_func = config_chipset_for_dma(drive, 0);
+ if (dma_func != ide_dma_on)
+ goto no_dma_set;
+ }
+ } else if (ide_dmaproc(ide_dma_good_drive, drive)) {
+ if (id->eide_dma_time > 150) {
+ goto no_dma_set;
+ }
+ /* Consult the list of known "good" drives */
+ dma_func = config_chipset_for_dma(drive, 0);
+ if (dma_func != ide_dma_on)
+ goto no_dma_set;
+ } else {
+ goto fast_ata_pio;
+ }
+ } else if ((id->capability & 8) || (id->field_valid & 2)) {
+fast_ata_pio:
+ dma_func = ide_dma_off_quietly;
+no_dma_set:
+ aec62xx_tune_drive(drive, 5);
+ }
+ return HWIF(drive)->dmaproc(dma_func, drive);
+}
+
+/*
+ * aec62xx_dmaproc() initiates/aborts (U)DMA read/write operations on a drive.
+ */
+int aec62xx_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+ switch (func) {
+ case ide_dma_check:
+ return config_drive_xfer_rate(drive);
+ default:
+ break;
+ }
+ return ide_dmaproc(func, drive); /* use standard DMA stuff */
+}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif /* CONFIG_AEC62XX_TUNING */
+
+unsigned int __init pci_init_aec62xx (struct pci_dev *dev, const char *name)
+{
+ if (dev->resource[PCI_ROM_RESOURCE].start) {
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE);
+ printk("%s: ROM enabled at 0x%08lx\n", name, dev->resource[PCI_ROM_RESOURCE].start);
+ }
+
+#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS)
+ if (!aec62xx_proc) {
+ aec62xx_proc = 1;
+ bmide_dev = dev;
+ aec62xx_display_info = &aec62xx_get_info;
+ }
+#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */
+
+ return dev->irq;
+}
+
+unsigned int __init ata66_aec62xx (ide_hwif_t *hwif)
+{
+ byte mask = hwif->channel ? 0x02 : 0x01;
+ byte ata66 = 0;
+
+ pci_read_config_byte(hwif->pci_dev, 0x49, &ata66);
+#if 1
+ printk("AEC6260: reg49h=0x%02x ATA-%s Cable Port%d\n", ata66, (ata66 & mask) ? "33" : "66", hwif->channel);
+#endif
+ return ((ata66 & mask) ? 0 : 1);
+}
+
+void __init ide_init_aec62xx (ide_hwif_t *hwif)
+{
+#ifdef CONFIG_AEC62XX_TUNING
+ hwif->tuneproc = &aec62xx_tune_drive;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (hwif->dma_base)
+ hwif->dmaproc = &aec62xx_dmaproc;
+#else /* !CONFIG_BLK_DEV_IDEDMA */
+ hwif->drives[0].autotune = 1;
+ hwif->drives[1].autotune = 1;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+#endif /* CONFIG_AEC62XX_TUNING */
+}
+
+void __init ide_dmacapable_aec62xx (ide_hwif_t *hwif, unsigned long dmabase)
+{
+#ifdef CONFIG_AEC62XX_TUNING
+ unsigned long flags;
+ byte reg54h = 0;
+
+ __save_flags(flags); /* local CPU only */
+ __cli(); /* local CPU only */
+
+ pci_read_config_byte(hwif->pci_dev, 0x54, ®54h);
+ pci_write_config_byte(hwif->pci_dev, 0x54, reg54h & ~(hwif->channel ? 0xF0 : 0x0F));
+
+ __restore_flags(flags); /* local CPU only */
+#endif /* CONFIG_AEC62XX_TUNING */
+ ide_setup_dma(hwif, dmabase, 8);
+}
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
byte param1, param2, param3, param4;
unsigned long flags;
ide_pio_data_t d;
- int bus_speed = ide_system_bus_speed();
+ int bus_speed = system_bus_clock();
pio = ide_get_best_pio_mode(drive, pio, ALI_MAX_PIO, &d);
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
int s_time, a_time, c_time;
byte s_clc, a_clc, r_clc;
unsigned long flags;
- int bus_speed = ide_system_bus_speed();
+ int bus_speed = system_bus_clock();
int port = hwif->index ? 0x5c : 0x58;
int portFIFO = hwif->channel ? 0x55 : 0x54;
byte cd_dma_fifo = 0;
static byte ali15x3_can_ultra (ide_drive_t *drive)
{
-#ifdef CONFIG_WDC_ALI15X3
+#ifndef CONFIG_WDC_ALI15X3
struct hd_driveid *id = drive->id;
#endif /* CONFIG_WDC_ALI15X3 */
if (m5229_revision <= 0x20) {
return 0;
} else if ((m5229_revision < 0xC2) &&
-#ifdef CONFIG_WDC_ALI15X3
+#ifndef CONFIG_WDC_ALI15X3
((chip_is_1543c_e && strstr(id->model, "WDC ")) ||
(drive->media!=ide_disk))) {
#else /* CONFIG_WDC_ALI15X3 */
#include <linux/hdreg.h>
#include <linux/interrupt.h>
+#include <linux/init.h>
#include <linux/pci.h>
#include <linux/ide.h>
#include <linux/hdreg.h>
#include <linux/zorro.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
{
int setup_time, active_time, recovery_time, clock_time;
byte setup_count, active_count, recovery_count, recovery_count2, cycle_count;
- int bus_speed = ide_system_bus_speed();
+ int bus_speed = system_bus_clock();
if (pio_mode > 5)
pio_mode = 5;
#include <linux/delay.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
+
#include "ide_modes.h"
#ifndef SPLIT_BYTE
int setup_time, active_time, recovery_time, clock_time, pio_mode, cycle_time;
byte recovery_count2, cycle_count;
int setup_count, active_count, recovery_count;
- int bus_speed = ide_system_bus_speed();
+ int bus_speed = system_bus_clock();
/*byte b;*/
ide_pio_data_t d;
#endif
(void) pci_write_config_byte(dev, DRWTIM23, 0x3f);
(void) pci_write_config_byte(dev, DRWTIM3, 0x3f);
+#ifdef CONFIG_PPC
+ (void) pci_write_config_byte(dev, UDIDETCR0, 0xf0);
+#endif /* CONFIG_PPC */
#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS)
if (!cmd64x_proc) {
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
static void compute_clocks (byte pio, pio_clocks_t *p_pclk)
{
int clk1, clk2;
- int bus_speed;
+ int bus_speed = system_bus_clock(); /* get speed of PCI bus */
- bus_speed = ide_system_bus_speed(); /* get speed of PCI bus */
/* we don't check against CY82C693's min and max speed,
* so you can play with the idebus=xx parameter
*/
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
static byte ht_pio2timings(ide_drive_t *drive, byte pio)
{
- int bus_speed, active_time, recovery_time;
+ int active_time, recovery_time;
int active_cycles, recovery_cycles;
ide_pio_data_t d;
+ int bus_speed = system_bus_clock();
if (pio) {
pio = ide_get_best_pio_mode(drive, pio, 5, &d);
* actual cycle time for recovery and activity
* according system bus speed.
*/
- bus_speed = ide_system_bus_speed();
active_time = ide_pio_timings[pio].active_time;
recovery_time = d.cycle_time
- active_time
#include <linux/errno.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/dma.h>
#include <asm/ecard.h>
*
* Copyright (C) 1994, 1995, 1996 scott snyder <snyder@fnald0.fnal.gov>
* Copyright (C) 1996-1998 Erik Andersen <andersee@debian.org>
- * Copyright (C) 1998, 1999 Jens Axboe <axboe@image.dk>
+ * Copyright (C) 1998-2000 Jens Axboe <axboe@suse.de>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
* and comply with the latest Mt. Fuji (SFF8090 version 4) and ATAPI
* (SFF-8020i rev 2.6) standards. These documents can be obtained by
* anonymous ftp from:
- * ftp://fission.dt.wdc.com/pub/standards/SFF/specs/INF-8020.PDF
- * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r01.pdf
+ * ftp://fission.dt.wdc.com/pub/standards/SFF_atapi/spec/SFF8020-r2.6/PS/8020r26.ps
+ * ftp://ftp.avc-pioneer.com/Mtfuji4/Spec/Fuji4r10.pdf
*
* Drives that deviate from these standards will be accomodated as much
* as possible via compile time or command-line options. Since I only have
* - Fixed a problem with WPI CDS-32X drive - it
* failed the capabilities
*
+ * 4.57 Apr 7, 2000 - Fixed sense reporting.
+ * - Fixed possible oops in ide_cdrom_get_last_session()
+ * - Fix locking mania and make ide_cdrom_reset relock
+ * - Stop spewing errors to log when magicdev polls with
+ * TEST_UNIT_READY on some drives.
+ * - Various fixes from Tobias Ringstrom:
+ * tray if it was locked prior to the reset.
+ * - cdrom_read_capacity returns one frame too little.
+ * - Fix real capacity reporting.
*
*************************************************************************/
-#define IDECD_VERSION "4.56"
+#define IDECD_VERSION "4.57"
#include <linux/config.h>
#include <linux/module.h>
static
-void cdrom_analyze_sense_data (ide_drive_t *drive, struct request_sense *reqbuf,
- struct packet_command *failed_command)
+void cdrom_analyze_sense_data(ide_drive_t *drive,
+ struct packet_command *failed_command,
+ struct request_sense *sense)
{
- if (reqbuf->sense_key == NOT_READY ||
- reqbuf->sense_key == UNIT_ATTENTION) {
+ if (sense->sense_key == NOT_READY ||
+ sense->sense_key == UNIT_ATTENTION) {
/* Make good and sure we've seen this potential media change.
Some drives (i.e. Creative) fail to present the correct
sense key in the error register. */
uses this command to poll the drive, and we don't want
to fill the syslog with useless errors. */
if (failed_command &&
- failed_command->c[0] == GPCMD_READ_SUBCHANNEL)
+ (failed_command->c[0] == GPCMD_READ_SUBCHANNEL ||
+ failed_command->c[0] == GPCMD_TEST_UNIT_READY))
return;
}
- if (reqbuf->error_code == 0x70 && reqbuf->sense_key == 0x02
- && ((reqbuf->asc == 0x3a && reqbuf->ascq == 0x00) ||
- (reqbuf->asc == 0x04 && reqbuf->ascq == 0x01)))
+ if (sense->error_code == 0x70 && sense->sense_key == 0x02
+ && ((sense->asc == 0x3a && sense->ascq == 0x00) ||
+ (sense->asc == 0x04 && sense->ascq == 0x01)))
{
/*
* Suppress the following errors:
char buf[80];
printk ("ATAPI device %s:\n", drive->name);
- if (reqbuf->error_code==0x70)
+ if (sense->error_code==0x70)
printk(" Error: ");
- else if (reqbuf->error_code==0x71)
+ else if (sense->error_code==0x71)
printk(" Deferred Error: ");
+ else if (sense->error_code == 0x7f)
+ printk(" Vendor-specific Error: ");
else
printk(" Unknown Error Type: ");
- if ( reqbuf->sense_key < ARY_LEN (sense_key_texts))
- s = sense_key_texts[reqbuf->sense_key];
+ if (sense->sense_key < ARY_LEN(sense_key_texts))
+ s = sense_key_texts[sense->sense_key];
else
s = "bad sense key!";
- printk ("%s -- (Sense key=0x%02x)\n", s, reqbuf->sense_key);
+ printk("%s -- (Sense key=0x%02x)\n", s, sense->sense_key);
- if (reqbuf->asc == 0x40) {
- sprintf (buf, "Diagnostic failure on component 0x%02x",
- reqbuf->ascq);
+ if (sense->asc == 0x40) {
+ sprintf(buf, "Diagnostic failure on component 0x%02x",
+ sense->ascq);
s = buf;
} else {
- int lo=0, mid, hi=ARY_LEN (sense_data_texts);
- unsigned long key = (reqbuf->sense_key << 16);
- key |= (reqbuf->asc << 8);
- if ( ! (reqbuf->ascq >= 0x80 && reqbuf->ascq <= 0xdd) )
- key |= reqbuf->ascq;
+ int lo = 0, mid, hi = ARY_LEN(sense_data_texts);
+ unsigned long key = (sense->sense_key << 16);
+ key |= (sense->asc << 8);
+ if (!(sense->ascq >= 0x80 && sense->ascq <= 0xdd))
+ key |= sense->ascq;
s = NULL;
while (hi > lo) {
}
if (s == NULL) {
- if (reqbuf->asc > 0x80)
+ if (sense->asc > 0x80)
s = "(vendor-specific error)";
else
s = "(reserved error code)";
}
- printk (" %s -- (asc=0x%02x, ascq=0x%02x)\n",
- s, reqbuf->asc, reqbuf->ascq);
+ printk(" %s -- (asc=0x%02x, ascq=0x%02x)\n",
+ s, sense->asc, sense->ascq);
if (failed_command != NULL) {
* In the case of NOT_READY, if SKSV is set the drive can
* give us nice ETA readings.
*/
- if (reqbuf->sense_key == NOT_READY && (reqbuf->sks[0] & 0x80)) {
- int progress = (reqbuf->sks[1] << 8 | reqbuf->sks[2]) * 100;
+ if (sense->sense_key == NOT_READY && (sense->sks[0] & 0x80)) {
+ int progress = (sense->sks[1] << 8 | sense->sks[2]) * 100;
printk(" Command is %02d%% complete\n", progress / 0xffff);
}
- if (reqbuf->sense_key == ILLEGAL_REQUEST &&
- (reqbuf->sks[0] & 0x80) != 0) {
- printk (" Error in %s byte %d",
- (reqbuf->sks[0] & 0x40) != 0 ?
+ if (sense->sense_key == ILLEGAL_REQUEST &&
+ (sense->sks[0] & 0x80) != 0) {
+ printk(" Error in %s byte %d",
+ (sense->sks[0] & 0x40) != 0 ?
"command packet" : "command data",
- (reqbuf->sks[1] << 8) + reqbuf->sks[2]);
+ (sense->sks[1] << 8) + sense->sks[2]);
- if ((reqbuf->sks[0] & 0x40) != 0)
- printk (" bit %d", reqbuf->sks[0] & 0x07);
+ if ((sense->sks[0] & 0x40) != 0)
+ printk (" bit %d", sense->sks[0] & 0x07);
printk ("\n");
}
/* Suppress printing unit attention and `in progress of becoming ready'
errors when we're not being verbose. */
- if (reqbuf->sense_key == UNIT_ATTENTION ||
- (reqbuf->sense_key == NOT_READY && (reqbuf->asc == 4 ||
- reqbuf->asc == 0x3a)))
+ if (sense->sense_key == UNIT_ATTENTION ||
+ (sense->sense_key == NOT_READY && (sense->asc == 4 ||
+ sense->asc == 0x3a)))
return;
- printk ("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
+ printk("%s: error code: 0x%02x sense_key: 0x%02x asc: 0x%02x ascq: 0x%02x\n",
drive->name,
- reqbuf->error_code, reqbuf->sense_key,
- reqbuf->asc, reqbuf->ascq);
+ sense->error_code, sense->sense_key,
+ sense->asc, sense->ascq);
#endif /* not VERBOSE_IDE_CD_ERRORS */
}
-static void cdrom_queue_request_sense (ide_drive_t *drive,
- struct semaphore *sem,
- struct packet_command *failed_command)
+static void cdrom_queue_request_sense(ide_drive_t *drive,
+ struct semaphore *sem,
+ struct request_sense *sense,
+ struct packet_command *failed_command)
{
struct cdrom_info *info = drive->driver_data;
struct request *rq;
- struct packet_command *pc;
+ struct packet_command *pc = &info->request_sense_pc;
- /* Make up a new request to retrieve sense information. */
- pc = &info->request_sense_pc;
- memset(pc, 0, sizeof (*pc));
+ if (sense == NULL)
+ sense = &info->sense_data;
+ memset(pc, 0, sizeof(struct packet_command));
pc->c[0] = GPCMD_REQUEST_SENSE;
-
- /* just get the first 18 bytes of the sense info, there might not
- * be more available */
pc->c[4] = pc->buflen = 18;
- pc->buffer = (char *)&info->sense_data;
- pc->sense_data = (struct request_sense *)failed_command;
+ pc->buffer = (char *) sense;
+ pc->sense = (struct request_sense *) failed_command;
/* stuff the sense request in front of our current request */
rq = &info->request_sense_request;
- ide_init_drive_cmd (rq);
+ ide_init_drive_cmd(rq);
rq->cmd = REQUEST_SENSE_COMMAND;
- rq->buffer = (char *)pc;
+ rq->buffer = (char *) pc;
rq->sem = sem;
- (void) ide_do_drive_cmd (drive, rq, ide_preempt);
+ (void) ide_do_drive_cmd(drive, rq, ide_preempt);
}
struct request *rq = HWGROUP(drive)->rq;
if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) {
- struct packet_command *pc = (struct packet_command *)
- rq->buffer;
- cdrom_analyze_sense_data (drive,
- (struct request_sense *) (pc->buffer - pc->c[4]),
- (struct packet_command *) pc->sense_data);
+ struct packet_command *pc = (struct packet_command *)rq->buffer;
+ cdrom_analyze_sense_data(drive,
+ (struct packet_command *) pc->sense,
+ (struct request_sense *) (pc->buffer - pc->c[4]));
}
if (rq->cmd == READ && !rq->current_nr_sectors)
uptodate = 1;
{
struct request *rq = HWGROUP(drive)->rq;
int stat, cmd, err, sense_key;
- struct packet_command *pc = (struct packet_command *) rq->buffer;
+ struct packet_command *pc;
/* Check for errors. */
stat = GET_STAT();
from the drive (probably while trying
to recover from a former error). Just give up. */
+ pc = (struct packet_command *) rq->buffer;
pc->stat = 1;
cdrom_end_request (1, drive);
*startstop = ide_error (drive, "request sense failure", stat);
/* All other functions, except for READ. */
struct semaphore *sem = NULL;
+ pc = (struct packet_command *) rq->buffer;
/* Check for tray open. */
if (sense_key == NOT_READY) {
cdrom_end_request (1, drive);
if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense(drive, sem, pc);
+ cdrom_queue_request_sense(drive, sem, pc->sense,
+ pc);
} else {
/* Handle errors from READ requests. */
/* If we got a CHECK_CONDITION status,
queue a request sense command. */
if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense(drive, NULL, NULL);
+ cdrom_queue_request_sense(drive, NULL, NULL, NULL);
}
}
pc.c[0] = GPCMD_READ_10;
pc.c[7] = (nframes >> 8);
pc.c[8] = (nframes & 0xff);
- put_unaligned(htonl (frame), (unsigned int *) &pc.c[2]);
+ put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]);
/* Send the command to the drive and return. */
- return cdrom_transfer_packet_command (drive, pc.c, sizeof (pc.c),
- &cdrom_read_intr);
+ return cdrom_transfer_packet_command(drive, pc.c, sizeof(pc.c),
+ &cdrom_read_intr);
}
*/
/* Forward declarations. */
-static int cdrom_lockdoor(ide_drive_t *drive, int lockflag);
+static int cdrom_lockdoor(ide_drive_t *drive, int lockflag,
+ struct request_sense *sense);
/* Interrupt routine for packet command completion. */
static ide_startstop_t cdrom_pc_intr (ide_drive_t *drive)
int ireason, len, stat, thislen;
struct request *rq = HWGROUP(drive)->rq;
struct packet_command *pc = (struct packet_command *)rq->buffer;
- struct cdrom_info *info = drive->driver_data;
ide_startstop_t startstop;
- pc->sense_data = &info->sense_data;
-
/* Check for errors. */
if (cdrom_decode_status (&startstop, drive, 0, &stat))
return startstop;
static
int cdrom_queue_packet_command(ide_drive_t *drive, struct packet_command *pc)
{
- int retries = 10;
+ struct request_sense sense;
struct request req;
+ int retries = 10;
+
+ if (pc->sense == NULL)
+ pc->sense = &sense;
/* Start of retry loop. */
do {
/* The request failed. Retry if it was due to a unit
attention status
(usually means media was changed). */
- struct request_sense *reqbuf = pc->sense_data;
+ struct request_sense *reqbuf = pc->sense;
if (reqbuf->sense_key == UNIT_ATTENTION)
cdrom_saw_media_change (drive);
} while (pc->stat != 0 && retries >= 0);
/* Return an error if the command failed. */
- if (pc->stat)
- return -EIO;
-
- /* The command succeeded. If it was anything other than
- a request sense, eject, or door lock command,
- and we think that the door is presently unlocked, lock it
- again. (The door was probably unlocked via an explicit
- CDROMEJECT ioctl.) */
- if (CDROM_STATE_FLAGS (drive)->door_locked == 0 &&
- (pc->c[0] != GPCMD_TEST_UNIT_READY &&
- pc->c[0] != GPCMD_REQUEST_SENSE &&
- pc->c[0] != GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL &&
- pc->c[0] != GPCMD_START_STOP_UNIT &&
- pc->c[0] != GPCMD_MODE_SENSE_10 &&
- pc->c[0] != GPCMD_MODE_SELECT_10)) {
- (void) cdrom_lockdoor (drive, 1);
- }
- return 0;
+ return pc->stat ? -EIO : 0;
}
/****************************************************************************
return (((m * CD_SECS) + s) * CD_FRAMES + f) - CD_MSF_OFFSET;
}
-static int cdrom_check_status (ide_drive_t *drive)
+static int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense)
{
struct packet_command pc;
struct cdrom_info *info = drive->driver_data;
struct cdrom_device_info *cdi = &info->devinfo;
memset(&pc, 0, sizeof(pc));
+ pc.sense = sense;
pc.c[0] = GPCMD_TEST_UNIT_READY;
/* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */
static int
-cdrom_lockdoor(ide_drive_t *drive, int lockflag)
+cdrom_lockdoor(ide_drive_t *drive, int lockflag, struct request_sense *sense)
{
- struct request_sense *sense;
+ struct request_sense my_sense;
struct packet_command pc;
int stat;
+ if (sense == NULL)
+ sense = &my_sense;
+
/* If the drive cannot lock the door, just pretend. */
- if (CDROM_CONFIG_FLAGS (drive)->no_doorlock)
+ if (CDROM_CONFIG_FLAGS(drive)->no_doorlock) {
stat = 0;
- else {
+ } else {
memset(&pc, 0, sizeof(pc));
+ pc.sense = sense;
pc.c[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
pc.c[4] = (lockflag != 0);
stat = cdrom_queue_packet_command (drive, &pc);
}
- sense = pc.sense_data;
-
/* If we got an illegal field error, the drive
probably cannot lock the door. */
if (stat != 0 &&
/* Eject the disk if EJECTFLAG is 0.
If EJECTFLAG is 1, try to reload the disk. */
-static int cdrom_eject(ide_drive_t *drive, int ejectflag)
+static int cdrom_eject(ide_drive_t *drive, int ejectflag,
+ struct request_sense *sense)
{
struct packet_command pc;
return 0;
memset(&pc, 0, sizeof (pc));
+ pc.sense = sense;
pc.c[0] = GPCMD_START_STOP_UNIT;
pc.c[4] = 0x02 + (ejectflag != 0);
return cdrom_queue_packet_command (drive, &pc);
}
-static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity)
+static int cdrom_read_capacity(ide_drive_t *drive, unsigned *capacity,
+ struct request_sense *sense)
{
struct {
__u32 lba;
int stat;
struct packet_command pc;
- memset(&pc, 0, sizeof (pc));
+ memset(&pc, 0, sizeof(pc));
+ pc.sense = sense;
pc.c[0] = GPCMD_READ_CDVD_CAPACITY;
pc.buffer = (char *)&capbuf;
stat = cdrom_queue_packet_command(drive, &pc);
if (stat == 0)
- *capacity = be32_to_cpu(capbuf.lba);
+ *capacity = 1 + be32_to_cpu(capbuf.lba);
return stat;
}
static int cdrom_read_tocentry(ide_drive_t *drive, int trackno, int msf_flag,
- int format, char *buf, int buflen)
+ int format, char *buf, int buflen,
+ struct request_sense *sense)
{
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
+ pc.sense = sense;
pc.buffer = buf;
pc.buflen = buflen;
/* Try to read the entire TOC for the disk into our internal buffer. */
-static int cdrom_read_toc (ide_drive_t *drive)
+static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
{
int stat, ntracks, i;
struct cdrom_info *info = drive->driver_data;
struct atapi_toc *toc = info->toc;
- int minor = drive->select.b.unit << PARTN_BITS;
struct {
struct atapi_toc_header hdr;
struct atapi_toc_entry ent;
/* Check to see if the existing data is still valid.
If it is, just return. */
if (CDROM_STATE_FLAGS (drive)->toc_valid)
- (void) cdrom_check_status(drive);
+ (void) cdrom_check_status(drive, sense);
if (CDROM_STATE_FLAGS (drive)->toc_valid) return 0;
/* First read just the header, so we know how long the TOC is. */
- stat = cdrom_read_tocentry (drive, 0, 1, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header));
+ stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
+ sizeof(struct atapi_toc_header), sense);
if (stat) return stat;
#if ! STANDARD_ATAPI
if (ntracks > MAX_TRACKS) ntracks = MAX_TRACKS;
/* Now read the whole schmeer. */
- stat = cdrom_read_tocentry (drive, toc->hdr.first_track, 1, 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- (ntracks + 1) *
- sizeof (struct atapi_toc_entry));
+ stat = cdrom_read_tocentry(drive, toc->hdr.first_track, 1, 0,
+ (char *)&toc->hdr,
+ sizeof(struct atapi_toc_header) +
+ (ntracks + 1) *
+ sizeof(struct atapi_toc_entry), sense);
if (stat && toc->hdr.first_track > 1) {
/* Cds with CDI tracks only don't have any TOC entries,
the readable TOC is empty (CDI tracks are not included)
and only holds the Leadout entry. Heiko Eißfeldt */
ntracks = 0;
- stat = cdrom_read_tocentry (drive, CDROM_LEADOUT, 1,
- 0, (char *)&toc->hdr,
- sizeof (struct atapi_toc_header) +
- (ntracks+1) *
- sizeof (struct atapi_toc_entry));
+ stat = cdrom_read_tocentry(drive, CDROM_LEADOUT, 1, 0,
+ (char *)&toc->hdr,
+ sizeof(struct atapi_toc_header) +
+ (ntracks + 1) *
+ sizeof(struct atapi_toc_entry),
+ sense);
if (stat) {
return stat;
}
/* Read the multisession information. */
if (toc->hdr.first_track != CDROM_LEADOUT) {
/* Read the multisession information. */
- stat = cdrom_read_tocentry (drive, 0, 1, 1,
- (char *)&ms_tmp, sizeof (ms_tmp));
+ stat = cdrom_read_tocentry(drive, 0, 1, 1, (char *)&ms_tmp,
+ sizeof(ms_tmp), sense);
if (stat) return stat;
} else {
ms_tmp.ent.addr.msf.minute = 0;
(long *)&toc->capacity);
if (stat)
#endif
- stat = cdrom_read_capacity (drive, &toc->capacity);
+ stat = cdrom_read_capacity(drive, &toc->capacity, sense);
if (stat) toc->capacity = 0x1fffff;
- /* for general /dev/cdrom like mounting, one big disc */
- drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
- HWIF(drive)->gd->sizes[minor] = (toc->capacity * SECTORS_PER_FRAME) >>
- (BLOCK_SIZE_BITS - 9);
-
/* Remember that we've read this stuff. */
CDROM_STATE_FLAGS (drive)->toc_valid = 1;
- /* should be "if multisession", but it does no harm. */
- if (ntracks == 1)
- return 0;
-
- /* setup each minor to respond to a session */
- minor++;
- i = toc->hdr.first_track;
- while ((i <= ntracks) && ((minor & CD_PART_MASK) < CD_PART_MAX)) {
- drive->part[minor & PARTN_MASK].start_sect = 0;
- drive->part[minor & PARTN_MASK].nr_sects =
- (toc->ent[i].addr.lba *
- SECTORS_PER_FRAME) << (BLOCK_SIZE_BITS - 9);
- HWIF(drive)->gd->sizes[minor] = (toc->ent[i].addr.lba *
- SECTORS_PER_FRAME) >> (BLOCK_SIZE_BITS - 9);
- i++;
- minor++;
- }
-
return 0;
}
static int cdrom_read_subchannel(ide_drive_t *drive, int format, char *buf,
- int buflen)
+ int buflen, struct request_sense *sense)
{
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
+ pc.sense = sense;
pc.buffer = buf;
pc.buflen = buflen;
/* ATAPI cdrom drives are free to select the speed you request or any slower
rate :-( Requesting too fast a speed will _not_ produce an error. */
-static int cdrom_select_speed (ide_drive_t *drive, int speed)
+static int cdrom_select_speed(ide_drive_t *drive, int speed,
+ struct request_sense *sense)
{
struct packet_command pc;
memset(&pc, 0, sizeof(pc));
+ pc.sense = sense;
if (speed == 0)
speed = 0xffff; /* set to max */
pc.c[5] = speed & 0xff;
}
- return cdrom_queue_packet_command (drive, &pc);
+ return cdrom_queue_packet_command(drive, &pc);
}
pc.buffer = cgc->buffer;
pc.buflen = cgc->buflen;
cgc->stat = cdrom_queue_packet_command(drive, &pc);
-
- /* There was an error, assign sense. */
- if (cgc->stat)
- cgc->sense = pc.sense_data;
+ cgc->sense = pc.sense;
return cgc->stat;
}
struct atapi_toc *toc;
/* Make sure our saved TOC is valid. */
- stat = cdrom_read_toc(drive);
+ stat = cdrom_read_toc(drive, NULL);
if (stat) return stat;
toc = info->toc;
int ide_cdrom_reset (struct cdrom_device_info *cdi)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct request_sense sense;
struct request req;
+ int ret;
ide_init_drive_cmd (&req);
req.cmd = RESET_DRIVE_COMMAND;
- return ide_do_drive_cmd (drive, &req, ide_wait);
+ ret = ide_do_drive_cmd(drive, &req, ide_wait);
+
+ /*
+ * A reset will unlock the door. If it was previously locked,
+ * lock it again.
+ */
+ if (CDROM_STATE_FLAGS(drive)->door_locked)
+ (void) cdrom_lockdoor(drive, 1, &sense);
+
+ return ret;
}
int ide_cdrom_tray_move (struct cdrom_device_info *cdi, int position)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct request_sense sense;
if (position) {
- int stat = cdrom_lockdoor (drive, 0);
+ int stat = cdrom_lockdoor(drive, 0, &sense);
if (stat) return stat;
}
- return cdrom_eject(drive, !position);
+ return cdrom_eject(drive, !position, &sense);
}
static
int ide_cdrom_lock_door (struct cdrom_device_info *cdi, int lock)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- return cdrom_lockdoor (drive, lock);
+ return cdrom_lockdoor(drive, lock, NULL);
}
#undef __ACER50__
int ide_cdrom_select_speed (struct cdrom_device_info *cdi, int speed)
{
#ifndef __ACER50__
- int stat, attempts = 3;
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_generic_command cgc;
+ int attempts = 3;
struct {
char pad[8];
struct atapi_capabilities_page cap;
} buf;
#else
- int stat;
- ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_generic_command cgc;
struct get_capabilities_buf buf;
#endif /* __ACER50__ */
+ ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ struct cdrom_generic_command cgc;
+ struct request_sense sense;
+ int stat;
- if ((stat = cdrom_select_speed (drive, speed)) < 0)
+ if ((stat = cdrom_select_speed (drive, speed, &sense)) < 0)
return stat;
init_cdrom_command(&cgc, &buf, sizeof(buf), CGC_DATA_UNKNOWN);
int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
- struct cdrom_info *info = drive->driver_data;
if (slot_nr == CDSL_CURRENT) {
- struct request_sense *sense = &info->sense_data;
- int stat = cdrom_check_status(drive);
- if (stat == 0 || sense->sense_key == UNIT_ATTENTION)
+ struct request_sense sense;
+ int stat = cdrom_check_status(drive, &sense);
+ if (stat == 0 || sense.sense_key == UNIT_ATTENTION)
return CDS_DISC_OK;
- if (sense->sense_key == NOT_READY && sense->asc == 0x04 &&
- sense->ascq == 0x04)
+ if (sense.sense_key == NOT_READY && sense.asc == 0x04 &&
+ sense.ascq == 0x04)
return CDS_DISC_OK;
- if (sense->sense_key == NOT_READY) {
+ if (sense.sense_key == NOT_READY) {
/* ATAPI doesn't have anything that can help
us decide whether the drive is really
emtpy or the tray is just open. irk. */
}
return CDS_DRIVE_NOT_READY;
- } else {
- return -EINVAL;
}
+ return -EINVAL;
}
static
struct atapi_toc *toc;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
struct cdrom_info *info = drive->driver_data;
+ struct request_sense sense;
+ int ret;
toc = info->toc;
+ if (!CDROM_STATE_FLAGS(drive)->toc_valid || toc == NULL)
+ if ((ret = cdrom_read_toc(drive, &sense)))
+ return ret;
+
ms_info->addr.lba = toc->last_session_lba;
ms_info->xa_flag = toc->xa_flag;
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
/* get MCN */
- if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf))))
+ if ((stat = cdrom_read_subchannel(drive, 2, mcnbuf, sizeof (mcnbuf), NULL)))
return stat;
memcpy (mcn_info->medium_catalog_number, mcnbuf+9,
int slot_nr)
{
ide_drive_t *drive = (ide_drive_t*) cdi->handle;
+ int retval;
if (slot_nr == CDSL_CURRENT) {
- (void) cdrom_check_status(drive);
+ (void) cdrom_check_status(drive, NULL);
+ retval = CDROM_STATE_FLAGS (drive)->media_changed;
CDROM_STATE_FLAGS (drive)->media_changed = 0;
- return CDROM_STATE_FLAGS (drive)->media_changed;
+ return retval;
} else {
return -EINVAL;
}
(drive->select.b.unit)<<PARTN_BITS));
}
+static
+void ide_cdrom_revalidate (ide_drive_t *drive)
+{
+ struct cdrom_info *info = drive->driver_data;
+ struct atapi_toc *toc;
+ int minor = drive->select.b.unit << PARTN_BITS;
+ struct request_sense sense;
+
+ cdrom_read_toc(drive, &sense);
+
+ if (!CDROM_STATE_FLAGS(drive)->toc_valid)
+ return;
+
+ toc = info->toc;
+
+ /* for general /dev/cdrom like mounting, one big disc */
+ drive->part[0].nr_sects = toc->capacity * SECTORS_PER_FRAME;
+ HWIF(drive)->gd->sizes[minor] = toc->capacity * BLOCKS_PER_FRAME;
+
+ blk_size[HWIF(drive)->major] = HWIF(drive)->gd->sizes;
+}
+
+static
+unsigned long ide_cdrom_capacity (ide_drive_t *drive)
+{
+ unsigned capacity;
+
+ capacity = cdrom_read_capacity(drive, &capacity, NULL);
+ return capacity ? 0 : capacity * SECTORS_PER_FRAME;
+}
+
static
int ide_cdrom_cleanup(ide_drive_t *drive)
{
ide_cdrom_open, /* open */
ide_cdrom_release, /* release */
ide_cdrom_check_media_change, /* media_change */
+ ide_cdrom_revalidate, /* revalidate */
NULL, /* pre_reset */
- NULL, /* capacity */
+ ide_cdrom_capacity, /* capacity */
NULL, /* special */
NULL /* proc */
};
-int ide_cdrom_init (void);
+int ide_cdrom_init(void);
static ide_module_t ide_cdrom_module = {
IDE_DRIVER_MODULE,
ide_cdrom_init,
}
#endif /* MODULE */
-int ide_cdrom_init (void)
+int ide_cdrom_init(void)
{
ide_drive_t *drive;
struct cdrom_info *info;
#define SECTOR_BUFFER_SIZE (CD_FRAMESIZE * 32)
#define SECTORS_BUFFER (SECTOR_BUFFER_SIZE / SECTOR_SIZE)
+#define BLOCKS_PER_FRAME (CD_FRAMESIZE / BLOCK_SIZE)
+
#define MIN(a,b) ((a) < (b) ? (a) : (b))
/* special command codes for strategy routine. */
char *buffer;
int buflen;
int stat;
- struct request_sense *sense_data;
+ struct request_sense *sense;
unsigned char c[12];
};
return drive->removable; /* if removable, always assume it was changed */
}
+static void idedisk_revalidate (ide_drive_t *drive)
+{
+ grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
+ 1<<PARTN_BITS,
+ current_capacity(drive));
+}
+
/*
* Compute drive->capacity, the full capacity of the drive
* Called with drive->id != NULL.
idedisk_open, /* open */
idedisk_release, /* release */
idedisk_media_change, /* media_change */
+ idedisk_revalidate, /* revalidate */
idedisk_pre_reset, /* pre_reset */
idedisk_capacity, /* capacity */
idedisk_special, /* special */
}
} else if ((id->field_valid & 4) &&
(id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
- printk(", UDMA(33)"); /* UDMA BIOS-enabled! */
+ if ((id->dma_ultra >> 10) & 1) {
+ printk(", UDMA(33)"); /* UDMA BIOS-enabled! */
+ } else if ((id->dma_ultra >> 9) & 1) {
+ printk(", UDMA(25)"); /* UDMA BIOS-enabled! */
+ } else {
+ printk(", UDMA(16)"); /* UDMA BIOS-enabled! */
+ }
} else if (id->field_valid & 4) {
printk(", (U)DMA"); /* Can be BIOS-enabled! */
} else {
return test_and_clear_bit (IDEFLOPPY_MEDIA_CHANGED, &floppy->flags);
}
+/*
+ * Revalidate the new media. Should set blk_size[]
+ */
+static void idefloppy_revalidate (ide_drive_t *drive)
+{
+ grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
+ 1<<PARTN_BITS,
+ current_capacity(drive));
+}
+
/*
* Return the current floppy capacity to ide.c.
*/
idefloppy_open, /* open */
idefloppy_release, /* release */
idefloppy_media_change, /* media_change */
+ idefloppy_revalidate, /* media_change */
NULL, /* pre_reset */
idefloppy_capacity, /* capacity */
NULL, /* special */
#define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415})
#define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
#define DEVID_AEC6210 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP850UF})
+#define DEVID_AEC6260 ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860})
+#define DEVID_AEC6260R ((ide_pci_devid_t){PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_ATP860R})
#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})
#define DEVID_UM8673F ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8673F})
#define DEVID_UM8886A ((ide_pci_devid_t){PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886A})
#define IDE_IGNORE ((void *)-1)
-#ifdef CONFIG_BLK_DEV_AEC6210
-extern unsigned int pci_init_aec6210(struct pci_dev *, const char *);
-extern void ide_init_aec6210(ide_hwif_t *);
-extern void ide_dmacapable_aec6210(ide_hwif_t *, unsigned long);
-#define PCI_AEC6210 &pci_init_aec6210
-#define INIT_AEC6210 &ide_init_aec6210
-#define DMA_AEC6210 &ide_dmacapable_aec6210
+#ifdef CONFIG_BLK_DEV_AEC62XX
+extern unsigned int pci_init_aec62xx(struct pci_dev *, const char *);
+extern unsigned int ata66_aec62xx(ide_hwif_t *);
+extern void ide_init_aec62xx(ide_hwif_t *);
+extern void ide_dmacapable_aec62xx(ide_hwif_t *, unsigned long);
+#define PCI_AEC62XX &pci_init_aec62xx
+#define ATA66_AEC62XX &ata66_aec62xx
+#define INIT_AEC62XX &ide_init_aec62xx
+#define DMA_AEC62XX &ide_dmacapable_aec62xx
#else
-#define PCI_AEC6210 NULL
-#define INIT_AEC6210 NULL
-#define DMA_AEC6210 NULL
+#define PCI_AEC62XX NULL
+#define ATA66_AEC62XX NULL
+#define INIT_AEC62XX NULL
+#define DMA_AEC62XX NULL
#endif
#ifdef CONFIG_BLK_DEV_ALI15X3
{DEVID_OPTI621X,"OPTI621X", NULL, NULL, INIT_OPTI621, NULL, {{0x45,0x80,0x00}, {0x40,0x08,0x00}}, ON_BOARD, 0 },
{DEVID_TRM290, "TRM290", NULL, NULL, INIT_TRM290, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_NS87415, "NS87415", NULL, NULL, INIT_NS87415, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
- {DEVID_AEC6210, "AEC6210", PCI_AEC6210, NULL, INIT_AEC6210, DMA_AEC6210, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, OFF_BOARD, 0 },
+ {DEVID_AEC6210, "AEC6210", PCI_AEC62XX, NULL, INIT_AEC62XX, DMA_AEC62XX, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 },
+ {DEVID_AEC6260, "AEC6260", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, NEVER_BOARD, 0 },
+ {DEVID_AEC6260R,"AEC6260R", PCI_AEC62XX, ATA66_AEC62XX, INIT_AEC62XX, NULL, {{0x4a,0x02,0x02}, {0x4a,0x04,0x04}}, OFF_BOARD, 0 },
{DEVID_W82C105, "W82C105", NULL, NULL, INIT_W82C105, DMA_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}}, ON_BOARD, 0 },
{DEVID_UM8673F, "UM8673F", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
{DEVID_UM8886A, "UM8886A", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
case PCI_DEVICE_ID_PROMISE_20246:
case PCI_DEVICE_ID_PROMISE_20262:
case PCI_DEVICE_ID_ARTOP_ATP850UF:
+ case PCI_DEVICE_ID_ARTOP_ATP860:
+ case PCI_DEVICE_ID_ARTOP_ATP860R:
return dev->irq;
default:
break;
}
#ifdef CONFIG_BLK_DEV_IDEDMA
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_SIS5513) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X))
autodma = 0;
if (autodma)
if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20262) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6210) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260) ||
+ IDE_PCI_DEVID_EQ(d->devid, DEVID_AEC6260R) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) ||
IDE_PCI_DEVID_EQ(d->devid, DEVID_CS5530) ||
*/
#include <linux/ide.h>
+#include <linux/init.h>
+
#include <linux/isapnp.h>
#ifndef PREPARE_FUNC
hd_status = IDE_STATUS_REG;
}
+ /* set features register for atapi identify command to be sure of reply */
+ if ((cmd == WIN_PIDENTIFY))
+ OUT_BYTE(0,IDE_FEATURE_REG); /* disable dma & overlap */
+
#if CONFIG_BLK_DEV_PDC4030
if (HWIF(drive)->chipset == ide_pdc4030) {
/* DC4030 hosted drives need their own identify... */
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
-#ifdef CONFIG_BLK_DEV_AEC6210
-extern byte aec6210_proc;
-int (*aec6210_display_info)(char *, char **, off_t, int) = NULL;
-#endif /* CONFIG_BLK_DEV_AEC6210 */
+#ifdef CONFIG_BLK_DEV_AEC62XX
+extern byte aec62xx_proc;
+int (*aec62xx_display_info)(char *, char **, off_t, int) = NULL;
+#endif /* CONFIG_BLK_DEV_AEC62XX */
#ifdef CONFIG_BLK_DEV_ALI15X3
extern byte ali_proc;
int (*ali_display_info)(char *, char **, off_t, int) = NULL;
create_proc_read_entry("drivers", 0, proc_ide_root,
proc_ide_read_drivers, NULL);
-#ifdef CONFIG_BLK_DEV_AEC6210
- if ((aec6210_display_info) && (aec6210_proc))
- create_proc_info_entry("aec6210", 0, proc_ide_root, aec6210_display_info);
-#endif /* CONFIG_BLK_DEV_AEC6210 */
+#ifdef CONFIG_BLK_DEV_AEC62XX
+ if ((aec62xx_display_info) && (aec62xx_proc))
+ create_proc_info_entry("aec62xx", 0, proc_ide_root, aec62xx_display_info);
+#endif /* CONFIG_BLK_DEV_AEC62XX */
#ifdef CONFIG_BLK_DEV_ALI15X3
if ((ali_display_info) && (ali_proc))
create_proc_info_entry("ali", 0, proc_ide_root, ali_display_info);
* Mmmm.. does this free up all resources,
* or do we need to do a more proper cleanup here ??
*/
-#ifdef CONFIG_BLK_DEV_AEC6210
- if ((aec6210_display_info) && (aec6210_proc))
- remove_proc_entry("ide/aec6210",0);
-#endif /* CONFIG_BLK_DEV_AEC6210 */
+#ifdef CONFIG_BLK_DEV_AEC62XX
+ if ((aec62xx_display_info) && (aec62xx_proc))
+ remove_proc_entry("ide/aec62xx",0);
+#endif /* CONFIG_BLK_DEV_AEC62XX */
#ifdef CONFIG_BLK_DEV_ALI15X3
if ((ali_display_info) && (ali_proc))
remove_proc_entry("ide/ali",0);
idetape_blkdev_open, /* open */
idetape_blkdev_release, /* release */
NULL, /* media_change */
+ NULL, /* revalidate */
idetape_pre_reset, /* pre_reset */
NULL, /* capacity */
NULL, /* special */
system_bus_speed = idebus_parameter; /* user supplied value */
#ifdef CONFIG_PCI
else if (pci_present())
- system_bus_speed = 40; /* safe default value for PCI */
+ system_bus_speed = 33; /* safe default value for PCI */
#endif /* CONFIG_PCI */
else
system_bus_speed = 50; /* safe default value for VESA and PCI */
#endif
block = rq->sector;
blockend = block + rq->nr_sectors;
-#if 0
+
if ((rq->cmd == READ || rq->cmd == WRITE) &&
- (drive->media == ide_disk || drive->media == ide_floppy))
-#endif
- {
+ (drive->media == ide_disk || drive->media == ide_floppy)) {
if ((blockend < block) || (blockend > drive->part[minor&PARTN_MASK].nr_sects)) {
printk("%s%c: bad access: block=%ld, count=%ld\n", drive->name,
(minor&PARTN_MASK)?'0'+(minor&PARTN_MASK):' ', block, rq->nr_sectors);
drive->part[p].nr_sects = 0;
};
- grok_partitions(HWIF(drive)->gd, drive->select.b.unit,
- (drive->media != ide_disk &&
- drive->media != ide_floppy) ? 1 : 1<<PARTN_BITS,
- current_capacity(drive));
+ DRIVER(drive)->revalidate(drive);
drive->busy = 0;
wake_up(&drive->wqueue);
hwif->config_data = old_hwif.config_data;
hwif->select_data = old_hwif.select_data;
hwif->proc = old_hwif.proc;
+#ifndef CONFIG_BLK_DEV_IDECS
hwif->irq = old_hwif.irq;
+#endif /* CONFIG_BLK_DEV_IDECS */
hwif->major = old_hwif.major;
hwif->chipset = old_hwif.chipset;
hwif->autodma = old_hwif.autodma;
*/
void ide_delay_50ms (void)
{
+#if 0
unsigned long timeout = jiffies + ((HZ + 19)/20) + 1;
while (0 < (signed long)(timeout - jiffies));
+#else
+ __set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(HZ/20);
+#endif
+}
+
+int system_bus_clock (void)
+{
+ return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
}
static int ide_ioctl (struct inode *inode, struct file *file,
static unsigned long default_capacity (ide_drive_t *drive)
{
- return 0x7fffffff; /* cdrom or tape */
+ return 0x7fffffff;
}
static ide_startstop_t default_special (ide_drive_t *drive)
EXPORT_SYMBOL(get_info_ptr);
EXPORT_SYMBOL(current_capacity);
+EXPORT_SYMBOL(system_bus_clock);
+
/*
* This is gets invoked once during initialization, to set *everything* up
*/
if (!banner_printed) {
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
ide_devfs_handle = devfs_mk_dir (NULL, "ide", 3, NULL);
- (void) ide_system_bus_speed();
+ system_bus_speed = ide_system_bus_speed();
banner_printed = 1;
}
#include <linux/hdreg.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/machw.h>
#include <asm/macintosh.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
static void compute_clocks(int pio, pio_clocks_t *clks)
{
if (pio != PIO_NOT_EXIST) {
- int adr_setup, data_pls, bus_speed;
- bus_speed = ide_system_bus_speed();
+ int adr_setup, data_pls;
+ int bus_speed = system_bus_clock();
+
adr_setup = ide_pio_timings[pio].setup_time;
data_pls = ide_pio_timings[pio].active_time;
clks->address_time = cmpt_clk(adr_setup, bus_speed);
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/delay.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <linux/blkdev.h>
#include <linux/errno.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/ecard.h>
#include <linux/hdreg.h>
#include <linux/pci.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/init.h>
#include <asm/io.h>
/*
- * linux/drivers/ide/via82cxxx.c Version 0.08 Mar. 18, 2000
+ * linux/drivers/ide/via82cxxx.c Version 0.09 Apr. 02, 2000
*
* Copyright (C) 1998-99 Michel Aubry, Maintainer
* Copyright (C) 1999 Jeff Garzik, MVP4 Support
#include <asm/io.h>
+#include "ide_modes.h"
+
static struct pci_dev *host_dev = NULL;
static struct pci_dev *isa_dev = NULL;
+struct chipset_bus_clock_list_entry {
+ byte xfer_speed;
+
+ byte chipset_settings_25;
+ byte ultra_settings_25;
+ byte chipset_settings_33;
+ byte ultra_settings_33;
+ byte chipset_settings_37;
+ byte ultra_settings_37;
+ byte chipset_settings_41;
+ byte ultra_settings_41;
+};
+
+static struct chipset_bus_clock_list_entry * via82cxxx_table = NULL;
+
+struct chipset_bus_clock_list_entry via82cxxx_type_one [] = {
+ /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+ { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { XFER_UDMA_2, 0x60, 0x20, 0x60, 0x20, 0x60, 0x21, 0x00, 0x00 },
+ { XFER_UDMA_1, 0x61, 0x20, 0x61, 0x20, 0x61, 0x21, 0x00, 0x00 },
+ { XFER_UDMA_0, 0x62, 0x20, 0x62, 0x20, 0x62, 0x21, 0x00, 0x00 },
+
+ { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 },
+ { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 },
+ { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 },
+
+ { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 },
+ { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 },
+ { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x76, 0x00, 0x00 },
+ { XFER_PIO_1, 0x03, 0x65, 0x03, 0x65, 0x03, 0x76, 0x00, 0x00 },
+ { XFER_PIO_0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA9, 0x00, 0x00 },
+ { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xA9, 0x00, 0x00 }
+};
+
+struct chipset_bus_clock_list_entry via82cxxx_type_two [] = {
+ /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+ { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 },
+ { XFER_UDMA_1, 0xE1, 0x20, 0xE1, 0x20, 0xE2, 0x31, 0xE2, 0x32 },
+ { XFER_UDMA_0, 0xE2, 0x20, 0xE2, 0x20, 0xE2, 0x31, 0xE2, 0x32 },
+
+ { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
+ { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
+ { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
+
+ { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
+ { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
+ { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 },
+ { XFER_PIO_1, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 },
+ { XFER_PIO_0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE },
+ { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE }
+};
+
+struct chipset_bus_clock_list_entry via82cxxx_type_three [] = {
+ /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+ { XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+ { XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 },
+ { XFER_UDMA_1, 0xE1, 0x20, 0xE1, 0x20, 0xE2, 0x31, 0xE2, 0x32 },
+ { XFER_UDMA_0, 0xE2, 0x20, 0xE2, 0x20, 0xE2, 0x31, 0xE2, 0x32 },
+
+ { XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
+ { XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
+ { XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
+
+ { XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
+ { XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
+ { XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 },
+ { XFER_PIO_1, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 },
+ { XFER_PIO_0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE },
+ { 0, 0x03, 0xA8, 0x03, 0xA8, 0x03, 0xDB, 0x03, 0xFE }
+};
+
+struct chipset_bus_clock_list_entry via82cxxx_type_four [] = {
+ /* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+ { XFER_UDMA_4, 0x00, 0x00, 0xE0, 0x20, 0xE1, 0x31, 0x00, 0x00 },
+ { XFER_UDMA_3, 0x00, 0x00, 0xE1, 0x20, 0xE2, 0x31, 0x00, 0x00 },
+ { XFER_UDMA_2, 0x00, 0x00, 0xE2, 0x20, 0xE4, 0x31, 0x00, 0x00 },
+ { XFER_UDMA_1, 0x00, 0x00, 0xE4, 0x20, 0xE6, 0x31, 0x00, 0x00 },
+ { XFER_UDMA_0, 0x00, 0x00, 0xE6, 0x20, 0xE6, 0x31, 0x00, 0x00 },
+
+ { XFER_MW_DMA_2, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 },
+ { XFER_MW_DMA_1, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 },
+ { XFER_MW_DMA_0, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 },
+
+ { XFER_PIO_4, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 },
+ { XFER_PIO_3, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 },
+ { XFER_PIO_2, 0x00, 0x00, 0x03, 0x65, 0x03, 0x87, 0x00, 0x00 },
+ { XFER_PIO_1, 0x00, 0x00, 0x03, 0x65, 0x03, 0x87, 0x00, 0x00 },
+ { XFER_PIO_0, 0x00, 0x00, 0x03, 0xA8, 0x03, 0xDB, 0x00, 0x00 },
+ { 0, 0x00, 0x00, 0x03, 0xA8, 0x03, 0xDB, 0x00, 0x00 }
+};
+
static const struct {
const char *name;
+ unsigned short vendor_id;
unsigned short host_id;
} ApolloHostChipInfo[] = {
- { "VT 82C585 Apollo VP1/VPX", PCI_DEVICE_ID_VIA_82C585, },
- { "VT 82C595 Apollo VP2", PCI_DEVICE_ID_VIA_82C595, },
- { "VT 82C597 Apollo VP3", PCI_DEVICE_ID_VIA_82C597_0, },
- { "VT 82C598 Apollo MVP3", PCI_DEVICE_ID_VIA_82C598_0, },
- { "VT 82C598 Apollo MVP3", PCI_DEVICE_ID_VIA_82C598_0, },
- { "VT 82C680 Apollo P6", PCI_DEVICE_ID_VIA_82C680, },
- { "VT 82C691 Apollo Pro", PCI_DEVICE_ID_VIA_82C691, },
- { "VT 82C693 Apollo Pro Plus", PCI_DEVICE_ID_VIA_82C693, },
- { "Apollo MVP4", PCI_DEVICE_ID_VIA_8501_0, },
- { "VT 8371", PCI_DEVICE_ID_VIA_8371_0, },
- { "VT 8601", PCI_DEVICE_ID_VIA_8601_0, },
+ { "VT 82C585 Apollo VP1/VPX", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C585, },
+ { "VT 82C595 Apollo VP2", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C595, },
+ { "VT 82C597 Apollo VP3", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, },
+ { "VT 82C598 Apollo MVP3", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_0, },
+ { "VT 82C598 Apollo MVP3", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C598_0, },
+ { "VT 82C680 Apollo P6", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C680, },
+ { "VT 82C691 Apollo Pro", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C691, },
+ { "VT 82C693 Apollo Pro Plus", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C693, },
+ { "Apollo MVP4", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8501_0, },
+ { "VT 8371", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_0, },
+ { "VT 8601", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8601_0, },
+ { "AMD IronGate", PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_7006, },
};
#define NUM_APOLLO_ISA_CHIP_DEVICES 2
+#define VIA_FLAG_NULL 0x00000000
#define VIA_FLAG_CHECK_REV 0x00000001
#define VIA_FLAG_ATA_66 0x00000002
unsigned short host_id;
unsigned short isa_id;
unsigned int flags;
+ struct chipset_bus_clock_list_entry * chipset_table;
} ApolloISAChipInfo[] = {
- { PCI_DEVICE_ID_VIA_82C585, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV },
- { PCI_DEVICE_ID_VIA_82C595, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV },
- { PCI_DEVICE_ID_VIA_82C597_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV },
- { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV },
- { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C596, 0 },
- { PCI_DEVICE_ID_VIA_82C680, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV },
- { PCI_DEVICE_ID_VIA_82C691, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_ATA_66 },
- { PCI_DEVICE_ID_VIA_82C693, PCI_DEVICE_ID_VIA_82C596, 0 },
- { PCI_DEVICE_ID_VIA_8501_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66 },
- { PCI_DEVICE_ID_VIA_8371_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66 },
- { PCI_DEVICE_ID_VIA_8601_0, PCI_DEVICE_ID_VIA_8231, VIA_FLAG_ATA_66 },
+ { PCI_DEVICE_ID_VIA_82C585, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_82C595, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_82C597_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_82C598_0, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_NULL, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_82C680, PCI_DEVICE_ID_VIA_82C586_1, VIA_FLAG_CHECK_REV, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_82C691, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_ATA_66, via82cxxx_type_two },
+ { PCI_DEVICE_ID_VIA_82C693, PCI_DEVICE_ID_VIA_82C596, VIA_FLAG_NULL, via82cxxx_type_one },
+ { PCI_DEVICE_ID_VIA_8501_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66, via82cxxx_type_two },
+ { PCI_DEVICE_ID_VIA_8371_0, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66, via82cxxx_type_two },
+ { PCI_DEVICE_ID_VIA_8601_0, PCI_DEVICE_ID_VIA_8231, VIA_FLAG_ATA_66, via82cxxx_type_two },
+ { PCI_DEVICE_ID_AMD_FE_GATE_7006, PCI_DEVICE_ID_VIA_82C686, VIA_FLAG_ATA_66, via82cxxx_type_two },
};
#define arraysize(x) (sizeof(x)/sizeof(*(x)))
}
#ifdef CONFIG_VIA82CXXX_TUNING
+static byte pci_bus_clock_list (byte speed, int ide_clock, struct chipset_bus_clock_list_entry * chipset_table)
+{
+ for ( ; chipset_table->xfer_speed ; chipset_table++)
+ if (chipset_table->xfer_speed == speed) {
+ switch(ide_clock) {
+ case 25: return chipset_table->chipset_settings_25;
+ case 33: return chipset_table->chipset_settings_33;
+ case 37: return chipset_table->chipset_settings_37;
+ case 41: return chipset_table->chipset_settings_41;
+ default: break;
+ }
+ }
+ return 0x00;
+}
-struct chipset_bus_clock_list_entry {
- unsigned short bus_speed;
- byte xfer_speed;
- byte chipset_settings;
-};
-
-PCI_DEVICE_ID_VIA_82C586_1
-PCI_DEVICE_ID_VIA_82C596
-PCI_DEVICE_ID_VIA_82C686
-PCI_DEVICE_ID_VIA_8231
-
-PCI_DEVICE_ID_VIA_82C586_1 TYPE_1
-PCI_DEVICE_ID_VIA_82C596 TYPE_2
-PCI_DEVICE_ID_VIA_82C686 TYPE_2
-PCI_DEVICE_ID_VIA_82C596 TYPE_3
-PCI_DEVICE_ID_VIA_82C686 TYPE_3
-PCI_DEVICE_ID_VIA_8231 TYPE_4
-
-struct chipset_bus_clock_list_entry ultra_33_base [] = {
-{ TYPE_1,25,0x00,0x00,0x60,0x61,0x62,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_1,33,0x00,0x00,0x60,0x61,0x62,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_1,37,0x00,0x00,0x60,0x61,0x62,0x03,0x21,0x32,0x76,0x76,0xA9 },
-{ TYPE_2,25,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_2,33,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_2,37,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x31,0x42,0x87,0x87,0xDB },
-{ TYPE_2,41,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x32,0x53,0xA8,0xA8,0xFE },
-{ TYPE_3,25,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_3,33,0x00,0x00,0xE0,0xE1,0xE2,0x03,0x20,0x31,0x65,0x65,0xA8 },
-{ TYPE_3,37,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x31,0x42,0x87,0x87,0xDB },
-{ TYPE_3,41,0x00,0x00,0xE1,0xE2,0xE2,0x03,0x32,0x53,0xA8,0xA8,0xFE },
-{ TYPE_4,0,0,0,0,0,0,0,0,0,0,0,0 },
-{ 0,0,0,0,0,0,0,0,0,0,0,0,0 }
-};
-
-struct chipset_bus_clock_list_entry timing_66_base [] = {
- { 37, XFER_PIO_4, 0x21 },
- { 37, XFER_PIO_3, 0x32 },
- { 37, XFER_PIO_2, 0x76 },
- { 37, XFER_PIO_1, 0x76 },
- { 37, XFER_PIO_0, 0xA9 },
- { ANY, XFER_PIO_4, 0x20 },
- { ANY, XFER_PIO_3, 0x31 },
- { ANY, XFER_PIO_2, 0x65 },
- { ANY, XFER_PIO_1, 0x65 },
- { ANY, XFER_PIO_0, 0xA8 },
-};
-
-static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
+static byte pci_bus_clock_list_ultra (byte speed, int ide_clock, struct chipset_bus_clock_list_entry * chipset_table)
{
for ( ; chipset_table->xfer_speed ; chipset_table++)
if (chipset_table->xfer_speed == speed) {
- return chipset_table->chipset_settings;
+ switch(ide_clock) {
+ case 25: return chipset_table->ultra_settings_25;
+ case 33: return chipset_table->ultra_settings_33;
+ case 37: return chipset_table->ultra_settings_37;
+ case 41: return chipset_table->ultra_settings_41;
+ default: break;
+ }
}
- return 0x01208585;
+ return 0x00;
}
static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
{
- struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- unsigned long dma_base = hwif->dma_base;
byte unit = (drive->select.b.unit & 0x01);
int drive_number = ((hwif->channel ? 2 : 0) + unit);
byte ultra = 0x00;
int err;
- int bus_speed = ide_system_bus_speed();
+ int bus_speed = system_bus_clock();
switch(drive_number) {
- case 0: ata2_pci = 0x48; ata3_pci = 0x50; break;
- case 1: ata2_pci = 0x49; ata3_pci = 0x51; break;
- case 2: ata2_pci = 0x4a; ata3_pci = 0x52; break;
- case 3: ata2_pci = 0x4b; ata3_pci = 0x53; break;
+ case 0: ata2_pci = 0x4b; ata3_pci = 0x53; break;
+ case 1: ata2_pci = 0x4a; ata3_pci = 0x52; break;
+ case 2: ata2_pci = 0x49; ata3_pci = 0x51; break;
+ case 3: ata2_pci = 0x48; ata3_pci = 0x50; break;
default:
return -1;
}
pci_read_config_byte(dev, ata2_pci, &timing);
- pci_read_config_byte(dev, ata3_pci, &ultra);
-
- switch(speed) {
- case XFER_UDMA_4:
- case XFER_UDMA_3:
- case XFER_UDMA_2:
- case XFER_UDMA_1:
- case XFER_UDMA_0:
- case XFER_MW_DMA_2:
- case XFER_MW_DMA_1:
- case XFER_MW_DMA_0:
- case XFER_SW_DMA_2:
- case XFER_SW_DMA_1:
- case XFER_SW_DMA_0:
- case XFER_PIO_4:
- case XFER_PIO_3:
- case XFER_PIO_2:
- case XFER_PIO_1:
- case XFER_PIO_0:
- case XFER_PIO_SLOW:
- default:
- break;
- }
-
+ timing = pci_bus_clock_list(speed, bus_speed, via82cxxx_table);
pci_write_config_byte(dev, ata2_pci, timing);
+
+ pci_read_config_byte(dev, ata3_pci, &ultra);
+ ultra = pci_bus_clock_list_ultra(speed, bus_speed, via82cxxx_table);
pci_write_config_byte(dev, ata3_pci, ultra);
err = ide_config_drive_speed(drive, speed);
if (ata33 | ata66)
printk(" Chipset Core ATA-%s", ata66 ? "66" : "33");
+
+ via82cxxx_table = ApolloISAChipInfo[j].chipset_table;
}
printk("\n");
}
unsigned int __init ata66_via82cxxx (ide_hwif_t *hwif)
{
- /* (Jeff Garzik) FIXME!!! for MVP4 */
- return 0;
+ byte ata66 = 0;
+ byte ata66reg = hwif->channel ? 0x50 : 0x52;
+ pci_read_config_byte(hwif->pci_dev, ata66reg, &ata66);
+
+ return ((ata66 & 0x04) ? 1 : 0);
}
void __init ide_init_via82cxxx (ide_hwif_t *hwif)
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/param.h>
#include <linux/module.h>
#include <linux/string.h>
-#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/locks.h>
#include <linux/major.h>
#include <linux/malloc.h>
-#include <linux/stat.h>
-#include <linux/tty.h>
#include <linux/ctype.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
u8 tmp8;
int rc;
u32 pio_start, pio_end, pio_flags, pio_len;
- u32 mmio_start, mmio_end, mmio_flags, mmio_len;
+ unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
DPRINTK ("ENTER\n");
#define NEXT_DEV (&sbni0_dev)
#endif
+/* S/390 channels */
+#ifdef CONFIG_CTC
+ extern int ctc_probe(struct net_device *dev);
+ static struct net_device ctc7_dev =
+ {"ctc7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV, ctc_probe};
+ static struct net_device ctc6_dev =
+ {"ctc6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc7_dev, ctc_probe};
+ static struct net_device ctc5_dev =
+ {"ctc5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc6_dev, ctc_probe};
+ static struct net_device ctc4_dev =
+ {"ctc4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc5_dev, ctc_probe};
+ static struct net_device ctc3_dev =
+ {"ctc3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc4_dev, ctc_probe};
+ static struct net_device ctc2_dev =
+ {"ctc2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc3_dev, ctc_probe};
+ static struct net_device ctc1_dev =
+ {"ctc1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc2_dev, ctc_probe};
+ static struct net_device ctc0_dev =
+ {"ctc0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc1_dev, ctc_probe};
+
+ static struct net_device escon7_dev =
+ {"escon7", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc0_dev, ctc_probe};
+ static struct net_device escon6_dev =
+ {"escon6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon7_dev, ctc_probe};
+ static struct net_device escon5_dev =
+ {"escon5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon6_dev, ctc_probe};
+ static struct net_device escon4_dev =
+ {"escon4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon5_dev, ctc_probe};
+ static struct net_device escon3_dev =
+ {"escon3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon4_dev, ctc_probe};
+ static struct net_device escon2_dev =
+ {"escon2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon3_dev, ctc_probe};
+ static struct net_device escon1_dev =
+ {"escon1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon2_dev, ctc_probe};
+ static struct net_device escon0_dev =
+ {"escon0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon1_dev, ctc_probe};
+
+#undef NEXT_DEV
+#define NEXT_DEV (&escon0_dev)
+#endif
/*
: Don't call netif_wake_queue() in net_send_packet()
: Fixed an out-of-mem bug in dma_rx()
: Updated Documentation/cs89x0.txt
+
+ Andrew Morton : andrewm@uow.edu.au / Kernel 2.3.99-pre1
+ : Use skb_reserve to longword align IP header (two places)
+ : Remove a delay loop from dma_rx()
+ : Replace '100' with HZ
+ : Clean up a couple of skb API abuses
+ : Added 'cs89x0_dma=N' kernel boot option
+ : Correctly initialise lp->lock in non-module compile
+
+ Andrew Morton : andrewm@uow.edu.au / Kernel 2.3.99-pre4-1
+ : MOD_INC/DEC race fix (see
+ : http://www.uwsg.indiana.edu/hypermail/linux/kernel/0003.3/1532.html)
+
*/
static char *version =
-"cs89x0.c: (kernel 2.3.48) Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
+"cs89x0.c: v2.3.99-pre1-2 Russell Nelson <nelson@crynwr.com>, Andrew Morton <andrewm@uow.edu.au>\n";
/* ======================= end of configuration ======================= */
{ 0x300, 0x320, 0x340, 0x360, 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 0};
#if DEBUGGING
-static unsigned int net_debug = 5;
+static unsigned int net_debug = DEBUGGING;
#else
#define net_debug 0 /* gcc will remove all the debug code for us */
#endif
/* Example routines you must write ;->. */
#define tx_done(dev) 1
+/*
+ * Permit 'cs89x0_dma=N' in the kernel boot environment
+ */
+#if !defined(MODULE) && (ALLOW_DMA != 0)
+static int g_cs89x0_dma;
+
+static int __init dma_fn(char *str)
+{
+ g_cs89x0_dma = simple_strtol(str,NULL,0);
+ return 1;
+}
+
+__setup("cs89x0_dma=", dma_fn);
+#endif /* !defined(MODULE) && (ALLOW_DMA != 0) */
+
\f
/* Check for a network adaptor of this type, and return '0' iff one exists.
If dev->base_addr == 0, probe all likely locations.
retval = ENOMEM;
goto out;
}
- memset(dev->priv, 0, sizeof(struct net_local));
+ lp = (struct net_local *)dev->priv;
+ memset(lp, 0, sizeof(*lp));
+ spin_lock_init(&lp->lock);
+#if !defined(MODULE) && (ALLOW_DMA != 0)
+ if (g_cs89x0_dma)
+ {
+ lp->use_dma = 1;
+ lp->dma = g_cs89x0_dma;
+ lp->dmasize = 16; /* Could make this an option... */
+ }
+#endif
}
lp = (struct net_local *)dev->priv;
int status, length;
unsigned char *bp = lp->rx_dma_ptr;
- {
- int i;
- for (i = 0; i < 1000; i++)
- ;
- }
-
status = bp[0] + (bp[1]<<8);
length = bp[2] + (bp[3]<<8);
bp += 4;
}
/* Malloc up new buffer. */
- skb = alloc_skb(length, GFP_ATOMIC);
+ skb = dev_alloc_skb(length + 2);
if (skb == NULL) {
if (net_debug) /* I don't think we want to do this to a stressed system */
printk("%s: Memory squeeze, dropping packet.\n", dev->name);
lp->rx_dma_ptr = bp;
return;
}
-
- skb->len = length;
+ skb_reserve(skb, 2); /* longword align L3 header */
skb->dev = dev;
if (bp + length > lp->end_dma_buff) {
writereg(dev, PP_SelfCTL, selfcontrol);
/* Wait for the DC/DC converter to power up - 500ms */
- while (jiffies - timenow < 100)
+ while (jiffies - timenow < HZ)
;
}
struct net_local *lp = (struct net_local *)dev->priv;
int result = 0;
int i;
+ int ret;
+
+ MOD_INC_USE_COUNT;
if (dev->irq < 2) {
/* Allow interrupts to be generated by the chip */
writereg(dev, PP_BusCTL, 0); /* disable interrupts. */
if (net_debug)
printk("cs89x0: can't get an interrupt\n");
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto bad_out;
}
} else {
if (((1 << dev->irq) & lp->irq_map) == 0) {
printk(KERN_ERR "%s: IRQ %d is not in our map of allowable IRQs, which is %x\n",
dev->name, dev->irq, lp->irq_map);
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto bad_out;
}
/* FIXME: Cirrus' release had this: */
writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL)|ENABLE_IRQ );
if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev)) {
if (net_debug)
printk("cs89x0: request_irq(%d) failed\n", dev->irq);
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto bad_out;
}
}
#endif
writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) & ~(SERIAL_TX_ON | SERIAL_RX_ON));
free_irq(dev->irq, dev);
- return -EAGAIN;
+ ret = -EAGAIN;
+ goto bad_out;
}
/* set the hardware to the configured choice */
| dma_busctl(dev)
#endif
);
- MOD_INC_USE_COUNT;
netif_start_queue(dev);
if (net_debug)
printk("cs89x0: net_open() succeeded\n");
return 0;
+bad_out:
+ MOD_DEC_USE_COUNT;
+ return ret;
}
static void net_timeout(struct net_device *dev)
}
/* Malloc up new buffer. */
- skb = alloc_skb(length, GFP_ATOMIC);
+ skb = dev_alloc_skb(length + 2);
if (skb == NULL) {
#if 0 /* Again, this seems a cruel thing to do */
printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
lp->stats.rx_dropped++;
return;
}
- skb->len = length;
+ skb_reserve(skb, 2); /* longword align L3 header */
skb->dev = dev;
- insw(ioaddr + RX_FRAME_PORT, skb->data, length >> 1);
+ insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);
if (length & 1)
skb->data[length-1] = inw(ioaddr + RX_FRAME_PORT);
* PPP driver, written by Michael Callahan and Al Longyear, and
* subsequently hacked by Paul Mackerras.
*
- * ==FILEVERSION 20000406==
+ * ==FILEVERSION 20000412==
*/
#include <linux/config.h>
size_t count);
static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
unsigned int cmd, unsigned long arg);
-static void ppp_xmit_process(struct ppp *ppp, int wakeup);
+static void ppp_xmit_process(struct ppp *ppp);
static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
static void ppp_push(struct ppp *ppp);
static void ppp_channel_push(struct channel *pch);
switch (pf->kind) {
case INTERFACE:
- ppp_xmit_process(PF_TO_PPP(pf), 0);
+ ppp_xmit_process(PF_TO_PPP(pf));
break;
case CHANNEL:
ppp_channel_push(PF_TO_CHANNEL(pf));
netif_stop_queue(dev);
skb_queue_tail(&ppp->file.xq, skb);
- ppp_xmit_process(ppp, 0);
+ ppp_xmit_process(ppp);
return 0;
outf:
* that can now be done.
*/
static void
-ppp_xmit_process(struct ppp *ppp, int wakeup)
+ppp_xmit_process(struct ppp *ppp)
{
struct sk_buff *skb;
ppp_xmit_lock(ppp);
- if (wakeup)
- ppp_push(ppp);
+ ppp_push(ppp);
while (ppp->xmit_pending == 0
&& (skb = skb_dequeue(&ppp->file.xq)) != 0)
ppp_send_frame(ppp, skb);
spin_lock_bh(&pch->downl);
if (pch->chan) {
if (pch->chan->ops->start_xmit(pch->chan, skb))
- skb = 0;
+ ppp->xmit_pending = 0;
} else {
/* channel got unregistered */
kfree_skb(skb);
- skb = 0;
- }
- if (skb_queue_len(&pch->file.xq) == 0 && skb == 0)
ppp->xmit_pending = 0;
+ }
spin_unlock_bh(&pch->downl);
return;
}
ppp_channel_push(struct channel *pch)
{
struct sk_buff *skb;
+ struct ppp *ppp;
spin_lock_bh(&pch->downl);
if (pch->chan != 0) {
skb_queue_purge(&pch->file.xq);
}
spin_unlock_bh(&pch->downl);
+ /* see if there is anything from the attached unit to be sent */
+ if (skb_queue_len(&pch->file.xq) == 0) {
+ read_lock_bh(&pch->upl);
+ ppp = pch->ppp;
+ if (ppp != 0)
+ ppp_xmit_process(ppp);
+ read_unlock_bh(&pch->upl);
+ }
}
/*
ppp_output_wakeup(struct ppp_channel *chan)
{
struct channel *pch = chan->ppp;
- struct ppp *ppp;
if (pch == 0)
return;
ppp_channel_push(pch);
- if (skb_queue_len(&pch->file.xq) == 0) {
- read_lock_bh(&pch->upl);
- ppp = pch->ppp;
- if (ppp != 0)
- ppp_xmit_process(ppp, 1);
- read_unlock_bh(&pch->upl);
- }
}
/*
next_tick = 3*HZ;
}
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ /* mod_timer synchronizes us with potential add_timer calls
+ * from interrupts.
+ */
+ mod_timer(&tp->timer, RUN_AT(next_tick));
}
dev->name, csr14);
outl(0x0001, ioaddr + CSR13);
outl(csr14, ioaddr + CSR14);
- tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
+ if (tp->chip_id == PNIC2)
+ tp->csr6 = 0x01a80000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
+ else
+ tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? 0x0200 : 0);
tulip_outl_CSR6(tp, tp->csr6);
if (tp->mtable && tp->mtable->csr15dir) {
outl(tp->mtable->csr15dir, ioaddr + CSR15);
}
break;
}
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ /* mod_timer synchronizes us with potential add_timer calls
+ * from interrupts.
+ */
+ mod_timer(&tp->timer, RUN_AT(next_tick));
}
inl(ioaddr + CSR12));
}
if (next_tick) {
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ mod_timer(&tp->timer, RUN_AT(next_tick));
}
}
printk(KERN_DEBUG "%s: Comet link status %4.4x partner capability "
"%4.4x.\n",
dev->name, inl(ioaddr + 0xB8), inl(ioaddr + 0xC8));
- tp->timer.expires = RUN_AT(next_tick);
- add_timer(&tp->timer);
+ /* mod_timer synchronizes us with potential add_timer calls
+ * from interrupts.
+ */
+ mod_timer(&tp->timer, RUN_AT(next_tick));
}
*/
-static const char version[] = "Linux Tulip driver version 0.9.4.2 (Mar 21, 2000)\n";
+static const char version[] = "Linux Tulip driver version 0.9.4.3 (Apr 14, 2000)\n";
#include <linux/module.h>
#include "tulip.h"
1191 Artop Electronic Corp
0004 ATP8400
0005 ATP850UF
+ 0006 ATP860 NO-BIOS
+ 0007 ATP860
8002 AEC6710 SCSI-2 Host Adapter
8010 AEC6712UW SCSI
8020 AEC6712U SCSI
-/* $Id: sab82532.c,v 1.41 2000/03/13 03:54:17 davem Exp $
+/* $Id: sab82532.c,v 1.42 2000/04/13 07:22:35 ecd Exp $
* sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
#define NR_EBRG_VALUES (sizeof(ebrg_table)/sizeof(struct ebrg_struct))
-#define SAB82532_MAX_TEC_DELAY 2000 /* 2 ms */
+#define SAB82532_MAX_TEC_TIMEOUT 200000 /* 1 character time (at 50 baud) */
+#define SAB82532_MAX_CEC_TIMEOUT 50000 /* 2.5 TX CLKs (at 50 baud) */
static __inline__ void sab82532_tec_wait(struct sab82532 *info)
{
- int count = SAB82532_MAX_TEC_DELAY;
- while ((readb(&info->regs->r.star) & SAB82532_STAR_TEC) && --count)
+ int timeout = info->tec_timeout;
+
+ while ((readb(&info->regs->r.star) & SAB82532_STAR_TEC) && --timeout)
+ udelay(1);
+}
+
+static __inline__ void sab82532_cec_wait(struct sab82532 *info)
+{
+ int timeout = info->cec_timeout;
+
+ while ((readb(&info->regs->r.star) & SAB82532_STAR_CEC) && --timeout)
udelay(1);
}
}
/* Issue a Transmit Frame command. */
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr);
out:
tmp = readb(&info->regs->rw.rfc);
tmp &= ~(SAB82532_RFC_RFDF);
writeb(tmp, &info->regs->rw.rfc);
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
#ifndef __sparc_v9__
* Reset FIFO to character + status mode.
*/
writeb(saved_rfc, &info->regs->w.rfc);
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
}
free_fifo++;
}
- if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
- count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
- free_fifo++;
- }
-
/* Issue a FIFO read command in case we where idle. */
if (stat->sreg.isr0 & SAB82532_ISR0_TIME) {
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_RFRD, &info->regs->w.cmdr);
+ /* Wait for command execution, to catch the TCD below. */
+ sab82532_cec_wait(info);
+ }
+
+ if (stat->sreg.isr0 & SAB82532_ISR0_TCD) {
+ count = readb(&info->regs->r.rbcl) & (info->recv_fifo_size - 1);
+ if (count == 0)
+ count = info->recv_fifo_size;
+ free_fifo++;
}
if (stat->sreg.isr0 & SAB82532_ISR0_RFO) {
/* Issue Receive Message Complete command. */
if (free_fifo) {
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_RMC, &info->regs->w.cmdr);
}
}
/* Issue a Transmit Frame command. */
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_XF, &info->regs->w.cmdr);
if (info->xmit_cnt < WAKEUP_CHARS)
/*
* Wait for any commands or immediate characters
*/
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
sab82532_tec_wait(info);
/*
* Clear the FIFO buffers.
*/
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
writeb(SAB82532_CMDR_RRES, &info->regs->w.cmdr);
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
writeb(SAB82532_CMDR_XRES, &info->regs->w.cmdr);
/*
ebrg |= (ebrg_table[i].m << 6);
info->baud = ebrg_table[i].baud;
- if (info->baud)
+ if (info->baud) {
info->timeout = (info->xmit_fifo_size * HZ * bits) / info->baud;
- else
+ info->tec_timeout = (10 * 1000000) / info->baud;
+ info->cec_timeout = info->tec_timeout >> 2;
+ } else {
info->timeout = 0;
+ info->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
+ info->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
+ }
info->timeout += HZ / 50; /* Add .02 seconds of slop */
/* CTS flow control flags */
SAB82532_ISR0_TIME;
save_flags(flags); cli();
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
sab82532_tec_wait(info);
writeb(dafo, &info->regs->w.dafo);
writeb(ebrg & 0xff, &info->regs->w.bgr);
static inline void __init show_serial_version(void)
{
- char *revision = "$Revision: 1.41 $";
+ char *revision = "$Revision: 1.42 $";
char *version, *p;
version = strchr(revision, ' ');
info->custom_divisor = 16;
info->close_delay = 5*HZ/10;
info->closing_wait = 30*HZ;
+ info->tec_timeout = SAB82532_MAX_TEC_TIMEOUT;
+ info->cec_timeout = SAB82532_MAX_CEC_TIMEOUT;
info->x_char = 0;
info->event = 0;
info->blocked_open = 0;
info->flags |= ASYNC_CHECK_CD;
save_flags(flags); cli();
- if (readb(&info->regs->r.star) & SAB82532_STAR_CEC)
- udelay(1);
+ sab82532_cec_wait(info);
sab82532_tec_wait(info);
writeb(dafo, &info->regs->w.dafo);
writeb(ebrg & 0xff, &info->regs->w.bgr);
idescsi_open, /* open */
idescsi_ide_release, /* release */
NULL, /* media_change */
+ NULL, /* revalidate */
NULL, /* pre_reset */
NULL, /* capacity */
NULL, /* special */
return -EFAULT;
return 0;
}
+ case HDIO_GETGEO_BIG:
+ {
+ struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
+
+ if(!loc)
+ return -EINVAL;
+
+ host = rscsi_disks[DEVICE_NR(dev)].device->host;
+
+ /* default to most commonly used values */
+
+ diskinfo[0] = 0x40;
+ diskinfo[1] = 0x20;
+ diskinfo[2] = rscsi_disks[DEVICE_NR(dev)].capacity >> 11;
+
+ /* override with calculated, extended default, or driver values */
+
+ if(host->hostt->bios_param != NULL)
+ host->hostt->bios_param(&rscsi_disks[DEVICE_NR(dev)],
+ dev,
+ &diskinfo[0]);
+ else scsicam_bios_param(&rscsi_disks[DEVICE_NR(dev)],
+ dev, &diskinfo[0]);
+
+ if (put_user(diskinfo[0], &loc->heads) ||
+ put_user(diskinfo[1], &loc->sectors) ||
+ put_user(diskinfo[2], (unsigned int *) &loc->cylinders) ||
+ put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start))
+ return -EFAULT;
+ return 0;
+ }
case BLKGETSIZE: /* Return device size */
if (!arg)
return -EINVAL;
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
obj-$(CONFIG_SOUND_NM256) += nm256_audio.o ac97.o
-obj-$(CONFIG_SOUND_NM256) += i810_audio.o ac97.o
+obj-$(CONFIG_SOUND_ICH) += i810_audio.o ac97.o
obj-$(CONFIG_SOUND_SONICVIBES) += sonicvibes.o
obj-$(CONFIG_SOUND_CMPCI) += cmpci.o
obj-$(CONFIG_SOUND_ES1370) += es1370.o
* 26-03-2000 Fixed acer, esstype and sm_games module options.
* Alessandro Zummo <azummo@ita.flashnet.it>
*
- * 27-03-2000 ISAPnP multiple card detection, cleanup, and reorg.
+ * 12-04-2000 ISAPnP cleanup, reorg, fixes, and multiple card support.
* Thanks to Gaël Quéri and Alessandro Zummo for testing and fixes.
* Paul E. Laufer <pelaufer@csupomona.edu>
*
static struct address_info cfg_mpu[SB_CARDS_MAX];
struct pci_dev *sb_dev[SB_CARDS_MAX] = {NULL},
- *mpu_dev[SB_CARDS_MAX] = {NULL};
+ *mpu_dev[SB_CARDS_MAX] = {NULL},
+ *opl_dev[SB_CARDS_MAX] = {NULL};
#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
static int audio_activated[SB_CARDS_MAX] = {0};
static int mpu_activated[SB_CARDS_MAX] = {0};
+static int opl_activated[SB_CARDS_MAX] = {0};
#else
static int isapnp = 0;
static int multiple = 1;
/* Please add new entries at the end of the table */
static struct {
char *name;
- unsigned short card_vendor, card_device, audio_vendor, audio_function, mpu_vendor, mpu_function;
+ unsigned short card_vendor, card_device,
+ audio_vendor, audio_function,
+ mpu_vendor, mpu_function,
+ opl_vendor, opl_function;
short dma, dma2, mpu_io, mpu_irq; /* see sb_init() */
} sb_isapnp_list[] __initdata = {
{"Sound Blaster 16",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster 16",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster 16",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster 16",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster 16",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster Vibra16S",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster Vibra16C",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster Vibra16CL",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster Vibra16X",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 32",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64 Gold",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"Sound Blaster AWE 64",
ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4),
ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
- 0,0,
+ 0,0,0,0,
0,1,1,-1},
{"ESS 1868",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
- 0,0,
+ 0,0,0,0,
0,1,2,-1},
{"ESS 1868",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611),
- 0,0,
+ 0,0,0,0,
0,1,2,-1},
{"ESS 1869 PnP AudioDrive",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
- 0,0,
+ 0,0,0,0,
0,1,2,-1},
{"ESS 1869",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869),
- 0,0,
+ 0,0,0,0,
0,1,2,-1},
{"ESS 1878",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878),
- 0,0,
+ 0,0,0,0,
0,1,2,-1},
{"ESS 1879",
ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879),
ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879),
- 0,0,
+ 0,0,0,0,
0,1,2,-1},
{"CMI 8330 SoundPRO",
ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
+ ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
0,1,0,-1},
{"Diamond DT0197H",
ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
0,-1,0,0},
{"ALS007",
ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
0,-1,0,0},
{"ALS100",
ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
1,0,0,0},
{"ALS110",
ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
1,0,0,0},
{"ALS120",
ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
1,0,0,0},
{"ALS200",
ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
1,0,0,0},
{"RTL3000",
ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001),
ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
+ ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
1,0,0,0},
{0}
};
} else
return(NULL);
+ /* Cards with separate OPL3 device (ALS, CMI, etc.)
+ * This is just to activate the device... */
+ if(sb_isapnp_list[slot].opl_vendor || sb_isapnp_list[slot].opl_function) {
+ if((opl_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].opl_vendor, sb_isapnp_list[slot].opl_function, NULL))) {
+ int ret = opl_dev[card]->prepare(opl_dev[card]);
+ /* If device is active, assume configured with
+ * /proc/isapnp and use anyway */
+ if(ret && ret != -EBUSY) {
+ printk(KERN_ERR "sb: OPL device could not be autoconfigured.\n");
+ return(sb_dev[card]);
+ }
+ if(ret == -EBUSY)
+ opl_activated[card] = 1;
+
+ /* Some have irq and dma for opl. the opl3 driver wont
+ * use 'em so don't configure 'em and hope it works -PEL */
+ opl_dev[card]->irq_resource[0].flags = 0;
+ opl_dev[card]->dma_resource[0].flags = 0;
+
+ opl_dev[card] = activate_dev(sb_isapnp_list[slot].name, "opl3", opl_dev[card]);
+ } else
+ printk(KERN_ERR "sb: %s isapnp panic: opl3 device not found\n", sb_isapnp_list[slot].name);
+ }
+
/* Cards with MPU as part of Audio device (CTL and ESS) */
if(!sb_isapnp_list[slot].mpu_vendor) {
mpu_config->io_base = sb_dev[card]->resource[sb_isapnp_list[slot].mpu_io].start;
return(sb_dev[card]);
}
-
- /* Cards with separate MPU device (ALS, CMI, etc */
+
+ /* Cards with separate MPU device (ALS, CMI, etc.) */
if(!uart401)
return(sb_dev[card]);
if((mpu_dev[card] = isapnp_find_dev(bus, sb_isapnp_list[slot].mpu_vendor, sb_isapnp_list[slot].mpu_function, NULL)))
if(ret == -EBUSY)
mpu_activated[card] = 1;
- /* Some mpus use audio device irq? Need to test... -PEL */
+ /* Some cards ask for irq but don't need them - azummo */
if(sb_isapnp_list[slot].mpu_irq == -1)
mpu_dev[card]->irq_resource[0].flags = 0;
}
}
else
- printk(KERN_ERR "sb: %s panic: mpu not found\n", sb_isapnp_list[slot].name);
+ printk(KERN_ERR "sb: %s isapnp panic: mpu not found\n", sb_isapnp_list[slot].name);
return(sb_dev[card]);
}
for(card = 0; card < max; card++, sb_cards_num++) {
#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
- /* Please remember that even with CONFIG_ISAPNP defined one should still be
- able to disable PNP support for this single driver! */
+ /* Please remember that even with CONFIG_ISAPNP defined one
+ * should still be able to disable PNP support for this
+ * single driver! */
if(isapnp && (sb_isapnp_probe(&cfg[card], &cfg_mpu[card], card) < 0) ) {
if(!sb_cards_num) {
printk(KERN_NOTICE "sb: No ISAPnP cards found, trying standard ones...\n");
sb_dev[i]->deactivate(sb_dev[i]);
if(!mpu_activated[i] && mpu_dev[i])
mpu_dev[i]->deactivate(mpu_dev[i]);
+ if(!opl_activated[i] && opl_dev[i])
+ opl_dev[i]->deactivate(opl_dev[i]);
#endif
}
SOUND_LOCK_END;
#ifndef MODULE
static int __init setup_sb(char *str)
{
- /* io, irq, dma, dma2 */
+ /* io, irq, dma, dma2 - just the basics */
int ints[5];
str = get_options(str, ARRAY_SIZE(ints), ints);
#ifndef MODULE
static const char *mode_option __initdata = NULL;
#endif
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
static void *bios_seg = NULL;
#endif
static struct fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128
*board_list, struct fb_info_aty128 *new_node);
static int aty128find_ROM(struct fb_info_aty128 *info);
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
static void aty128_get_pllinfo(struct fb_info_aty128 *info);
#endif
static void aty128_timings(struct fb_info_aty128 *info);
printk(KERN_INFO "aty128fb: Rage128 BIOS not located. Guessing...\n");
aty128_timings(info);
}
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
else
aty128_get_pllinfo(info);
#endif /* CONFIG_PCI */
-/* PPC cannot read video ROM, so we fail by default */
+/* PPC and Sparc cannot read video ROM, so we fail by default */
static int __init
aty128find_ROM(struct fb_info_aty128 *info)
{
int flag = 0;
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
u32 segstart;
char *rom_base;
char *rom;
}
-#ifndef CONFIG_PPC
+#if !defined(CONFIG_PPC) && !defined(__sparc__)
static void __init
aty128_get_pllinfo(struct fb_info_aty128 *info)
{
#include <linux/fb.h>
#include <asm/byteorder.h>
+
+#ifdef __mc68000__
#include <asm/setup.h>
+#endif
#include <video/fbcon.h>
#include <video/fbcon-iplan2p2.h>
#include <linux/fb.h>
#include <asm/byteorder.h>
+
+#ifdef __mc68000__
#include <asm/setup.h>
+#endif
#include <video/fbcon.h>
#include <video/fbcon-iplan2p4.h>
#include <linux/fb.h>
#include <asm/byteorder.h>
+
+#ifdef __mc68000__
#include <asm/setup.h>
+#endif
#include <video/fbcon.h>
#include <video/fbcon-iplan2p8.h>
static int nopan = 0;
static int nowrap = 1; // not implemented (yet)
static int inverse = 0;
+#ifdef CONFIG_MTRR
static int nomtrr = 0;
+#endif
static int nohwcursor = 0;
static char __initdata fontname[40] = { 0 };
static const char *mode_option __initdata = NULL;
fb_info.regbase_phys = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
fb_info.regbase_size = 1 << 24;
fb_info.regbase_virt =
- (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+ (unsigned long)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
if(!fb_info.regbase_virt) {
printk("fb: Can't remap %s register area.\n", name);
return;
return;
}
fb_info.bufbase_virt =
- (u32)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
+ (unsigned long)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
if(!fb_info.regbase_virt) {
printk("fb: Can't remap %s framebuffer.\n", name);
iounmap((void*)fb_info.regbase_virt);
fb_info.regbase_phys = pdev->resource[0].start;
fb_info.regbase_size = 1 << 24;
fb_info.regbase_virt =
- (u32)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
+ (unsigned long)ioremap_nocache(fb_info.regbase_phys, 1 << 24);
if(!fb_info.regbase_virt) {
printk("fb: Can't remap %s register area.\n", name);
return -ENXIO;
return -ENXIO;
}
fb_info.bufbase_virt =
- (u32)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
+ (unsigned long)ioremap_nocache(fb_info.bufbase_phys, fb_info.bufbase_size);
if(!fb_info.regbase_virt) {
printk("fb: Can't remap %s framebuffer.\n", name);
iounmap((void*)fb_info.regbase_virt);
dep_tristate 'ADFS file system support' CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
dep_mbool ' ADFS write support (DANGEROUS)' CONFIG_ADFS_FS_RW $CONFIG_ADFS_FS $CONFIG_EXPERIMENTAL
-tristate 'Amiga FFS file system support' CONFIG_AFFS_FS
+dep_tristate 'Amiga FFS file system support (EXPERIMENTAL)' CONFIG_AFFS_FS $CONFIG_EXPERIMENTAL
dep_tristate 'Apple Macintosh file system support (EXPERIMENTAL)' CONFIG_HFS_FS $CONFIG_EXPERIMENTAL
Please direct bug reports to: hjw@zvw.de
+Version 3.11
+------------
+
+- Converted to use 2.3.x page cache [Dave Jones <dave@powertweak.com>]
+- Corruption in truncate() bugfix [Ken Tyler <kent@werple.net.au>]
+
Version 3.10
------------
for (index = 0; index < 4; index++) {
kc = &inode->u.affs_i.i_ec->kc[index];
+ if (kc->kc_last == -1)
+ continue; /* don't look in cache if invalid. */
if (*ext == kc->kc_this_seq) {
return kc->kc_this_key;
} else if (*ext == kc->kc_this_seq + 1) {
/* Invalidate cache */
if (inode->u.affs_i.i_ec) {
inode->u.affs_i.i_ec->max_ext = 0;
- for (key = 0; key < 3; key++) {
+ for (key = 0; key < 4; key++) {
inode->u.affs_i.i_ec->kc[key].kc_next_key = 0;
inode->u.affs_i.i_ec->kc[key].kc_last = -1;
}
/* File operations for device entries follow */
-static int devfs_read (struct file *file, char *buf, size_t len, loff_t *ppos)
+static ssize_t devfs_read (struct file *file, char *buf, size_t len, loff_t *ppos)
{
if ( S_ISDIR (file->f_dentry->d_inode->i_mode) ) return -EISDIR;
return -EINVAL;
if (r == 0)
r = adfspart_check_POWERTEC(hd, dev, first_sector, first_part_minor);
#endif
- if (r < 0)
- if (warn_no_part) printk(" unable to read boot sectors / partition sectors\n");
- else if (r)
+ if (r < 0) {
+ if (warn_no_part)
+ printk(" unable to read boot sectors / partition sectors\n");
+ } else if (r) {
printk("\n");
+ }
return r;
}
#include <linux/string.h>
#include <linux/blk.h>
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
#include <linux/ide.h> /* IDE xlate */
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
#include <asm/system.h>
unsigned char *data;
int mask = (1 << hd->minor_shift) - 1;
int sector_size = get_hardsect_size(dev) / 512;
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
int tested_for_xlate = 0;
read_mbr:
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
if (!(bh = bread(dev,0,get_ptable_blocksize(dev)))) {
if (warn_no_part) printk(" unable to read partition table\n");
return -1;
}
data = bh->b_data;
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
check_table:
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
/* Use bforget(), because we may have changed the disk geometry */
if (*(unsigned short *) (0x1fe + data) != cpu_to_le16(MSDOS_LABEL_MAGIC)) {
bforget(bh);
}
p = (struct partition *) (0x1be + data);
-#ifdef CONFIG_IDE
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_HD)
if (!tested_for_xlate++) { /* Do this only once per disk */
/*
* Look for various forms of IDE disk geometry translation
(void) ide_xlate_1024(dev, 2, heads, " [PTBL]");
}
}
-#endif /* CONFIG_IDE */
+#endif /* (CONFIG_BLK_DEV_IDE) || (CONFIG_BLK_DEV_HD) */
/* Look for partitions in two passes:
First find the primary partitions, and the DOS-type extended partitions.
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
/*
* For backward compatibility? Maybe this should be moved
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
/*
* For backward compatibility? Maybe this should be moved
* into arch/i386 instead?
return error;
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
/*
* For backward compatibility? Maybe this should be moved
return error;
}
-#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__)
+#if !defined(__alpha__) && !defined(__sparc__) && !defined(__ia64__) && !defined(__s390__)
/*
* For backward compatibility? Maybe this should be moved
-/* $Id: elf.h,v 1.20 1998/09/14 09:11:10 davem Exp $ */
+/* $Id: elf.h,v 1.21 2000/04/14 09:59:04 davem Exp $ */
#ifndef __ASMSPARC_ELF_H
#define __ASMSPARC_ELF_H
/*
- * $Id: io.h,v 1.26 2000/03/30 01:43:26 davem Exp $
+ * $Id: io.h,v 1.27 2000/04/13 04:45:59 davem Exp $
*/
#ifndef __SPARC_IO_H
#define __SPARC_IO_H
* This is why we have no bus number argument to ioremap().
*/
extern void *ioremap(unsigned long offset, unsigned long size);
+#define ioremap_nocache(X,Y) ioremap((X),(Y))
extern void iounmap(void *addr);
/* P3: talk davem into dropping "name" argument in favor of res->name */
-/* $Id: namei.h,v 1.15 2000/04/08 02:15:14 davem Exp $
+/* $Id: namei.h,v 1.16 2000/04/13 00:55:54 davem Exp $
* linux/include/asm-sparc/namei.h
*
* Routines to handle famous /usr/gnemul/s*.
-/* $Id: delay.h,v 1.7 1997/11/07 18:24:31 mj Exp $
+/* $Id: delay.h,v 1.8 2000/04/13 04:45:59 davem Exp $
* delay.h: Linux delay routines on the V9.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
#define __SPARC64_DELAY_H
#ifdef __SMP__
+#include <linux/sched.h>
#include <asm/smp.h>
#endif
-/* $Id: elf.h,v 1.23 1999/12/15 14:19:06 davem Exp $ */
+/* $Id: elf.h,v 1.24 2000/04/14 09:59:04 davem Exp $ */
#ifndef __ASM_SPARC64_ELF_H
#define __ASM_SPARC64_ELF_H
-/* $Id: io.h,v 1.34 2000/03/30 01:40:54 davem Exp $ */
+/* $Id: io.h,v 1.35 2000/04/13 04:45:59 davem Exp $ */
#ifndef __SPARC64_IO_H
#define __SPARC64_IO_H
* using physically addressed loads and stores, so this does nothing.
*/
#define ioremap(__offset, __size) ((void *)(__offset))
+#define ioremap_nocache(X,Y) ioremap((X),(Y))
#define iounmap(__addr) do { } while(0)
/* Similarly for SBUS. */
-/* $Id: namei.h,v 1.16 2000/04/08 02:15:17 davem Exp $
+/* $Id: namei.h,v 1.17 2000/04/13 00:55:54 davem Exp $
* linux/include/asm-sparc64/namei.h
*
* Routines to handle famous /usr/gnemul/s*.
-/* $Id: page.h,v 1.33 2000/03/22 02:48:04 davem Exp $ */
+/* $Id: page.h,v 1.35 2000/04/13 04:45:59 davem Exp $ */
#ifndef _SPARC64_PAGE_H
#define _SPARC64_PAGE_H
#define BUG() __builtin_trap()
#define PAGE_BUG(page) BUG()
-extern void clear_page(void *page);
-extern void copy_page(void *to, void *from);
+extern void _clear_page(void *page);
+extern void _copy_page(void *to, void *from);
+#define clear_page(X) _clear_page((void *)(X))
+#define copy_page(X,Y) _copy_page((void *)(X), (void *)(Y))
extern void clear_user_page(void *page, unsigned long vaddr);
extern void copy_user_page(void *to, void *from, unsigned long vaddr);
#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long) (x) + PAGE_OFFSET))
-#define MAP_NR(addr) (__pa(addr) >> PAGE_SHIFT)
+#define MAP_NR(addr) ((__pa(addr)-phys_base) >> PAGE_SHIFT)
#define virt_to_phys __pa
#define phys_to_virt __va
*/
struct sparc_phys_banks {
- unsigned long base_addr;
- unsigned long num_bytes;
+ unsigned long base_addr;
+ unsigned long num_bytes;
};
#define SPARC_PHYS_BANKS 32
ret = (struct page *)(__page_address(ret) + off);
pgd_cache_size--;
} else {
- ret = (struct page *) __get_free_page(GFP_KERNEL);
- if(ret) {
- struct page *page = mem_map + MAP_NR(ret);
-
- memset(ret, 0, PAGE_SIZE);
+ struct page *page = alloc_page(GFP_KERNEL);
+
+ if (page) {
+ ret = (struct page *)page_address(page);
+ clear_page(ret);
(unsigned long)page->pprev_hash = 2;
(unsigned long *)page->next_hash = pgd_quicklist;
pgd_quicklist = (unsigned long *)page;
-/* $Id: pgtable.h,v 1.124 2000/03/27 10:38:56 davem Exp $
+/* $Id: pgtable.h,v 1.125 2000/04/12 08:10:26 davem Exp $
* pgtable.h: SpitFire page table operations.
*
* Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
#define BAD_PAGE __bad_page()
-/* First physical page can be anywhere, the following is needed so that
- * va-->pa and vice versa conversions work properly without performance
- * hit for all __pa()/__va() operations.
- */
extern unsigned long phys_base;
-#define ZERO_PAGE(vaddr) (mem_map + (phys_base>>PAGE_SHIFT))
+
+#define ZERO_PAGE(vaddr) (mem_map)
/* Warning: These take pointers to page structs now... */
#define mk_pte(page, pgprot) \
- __pte(((page - mem_map) << PAGE_SHIFT) | pgprot_val(pgprot))
+ __pte((((page - mem_map) << PAGE_SHIFT)+phys_base) | pgprot_val(pgprot))
#define page_pte_prot(page, prot) mk_pte(page, prot)
#define page_pte(page) page_pte_prot(page, __pgprot(0))
(pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
#define pgd_set(pgdp, pmdp) \
(pgd_val(*(pgdp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
-#define pte_pagenr(pte) ((unsigned long) ((pte_val(pte)&~PAGE_OFFSET)>>PAGE_SHIFT))
+#define pte_pagenr(pte) (((unsigned long) ((pte_val(pte)&~PAGE_OFFSET)-phys_base)>>PAGE_SHIFT))
#define pmd_page(pmd) ((unsigned long) __va((pmd_val(pmd)<<11UL)))
#define pgd_page(pgd) ((unsigned long) __va((pgd_val(pgd)<<11UL)))
#define pte_none(pte) (!pte_val(pte))
-/* $Id: sab82532.h,v 1.5 1999/05/12 11:21:22 davem Exp $
+/* $Id: sab82532.h,v 1.6 2000/04/13 07:22:35 ecd Exp $
* sab82532.h: Register Definitions for the Siemens SAB82532 DUSCC
*
* Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be)
int recv_fifo_size;
int custom_divisor;
int baud;
+ unsigned int cec_timeout;
+ unsigned int tec_timeout;
int x_char;
int close_delay;
unsigned short closing_wait;
#ifndef _LINUX_ASM_VGA_H_
#define _LINUX_ASM_VGA_H_
+#include <asm/types.h>
+
#define VT_BUF_HAVE_RW
static inline void scr_writew(u16 val, u16 *addr)
#define ATM_ATMOPT_CLP 1 /* set CLP bit */
-typedef struct { unsigned short bits; } atm_vcc_flags_t;
+typedef struct { unsigned int bits; } atm_vcc_flags_t;
struct atm_vcc {
struct sk_buff_head recvq; /* receive queue */
struct k_atm_aal_stats *stats; /* pointer to AAL stats group */
wait_queue_head_t sleep; /* if socket is busy */
- wait_queue_head_t wsleep; /* if waiting for write buffer space */
struct sock *sk; /* socket backpointer */
struct atm_vcc *prev,*next;
/* SVC part --- may move later ------------------------------------- */
#define SMART_AUTOSAVE 0xd2
#define SMART_SAVE 0xd3
#define SMART_IMMEDIATE_OFFLINE 0xd4
+#define SMART_READ_LOG_SECTOR 0xd5
+#define SMART_WRITE_LOG_SECTOR 0xd6
#define SMART_ENABLE 0xd8
#define SMART_DISABLE 0xd9
#define SMART_STATUS 0xda
+/*
+ * linux/include/linux/hdsmart.h
+ *
+ * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org>
+ * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * (for example /usr/src/linux/COPYING); if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
#ifndef _LINUX_HDSMART_H
#define _LINUX_HDSMART_H
-/*
- * This file contains some defines for the AT-hd-controller.
- * Various sources.
- */
+/* smart_attribute is the vendor specific in SFF-8035 spec */
+struct ata_smart_attribute {
+ unsigned char id;
+ unsigned short status_flag;
+ unsigned char normalized;
+ unsigned char worse_normal;
+ unsigned char raw[6];
+ unsigned char reserv;
+} __attribute__ ((packed));
+
+/* smart_values is format of the read drive Atrribute command */
+struct ata_smart_values {
+ unsigned short revnumber;
+ struct ata_smart_attribute vendor_attributes [30];
+ unsigned char offline_data_collection_status;
+ unsigned char self_test_exec_status;
+ unsigned short total_time_to_complete_off_line;
+ unsigned char vendor_specific_366;
+ unsigned char offline_data_collection_capability;
+ unsigned short smart_capability;
+ unsigned char errorlog_capability;
+ unsigned char vendor_specific_371;
+ unsigned char short_test_completion_time;
+ unsigned char extend_test_completion_time;
+ unsigned char reserved_374_385 [12];
+ unsigned char vendor_specific_386_509 [125];
+ unsigned char chksum;
+} __attribute__ ((packed));
+
+/* Smart Threshold data structures */
+/* Vendor attribute of SMART Threshold */
+struct ata_smart_threshold_entry {
+ unsigned char id;
+ unsigned char normalized_threshold;
+ unsigned char reserved[10];
+} __attribute__ ((packed));
+
+/* Format of Read SMART THreshold Command */
+struct ata_smart_thresholds {
+ unsigned short revnumber;
+ struct ata_smart_threshold_entry thres_entries[30];
+ unsigned char reserved[149];
+ unsigned char chksum;
+} __attribute__ ((packed));
+
+struct ata_smart_errorlog_command_struct {
+ unsigned char devicecontrolreg;
+ unsigned char featuresreg;
+ unsigned char sector_count;
+ unsigned char sector_number;
+ unsigned char cylinder_low;
+ unsigned char cylinder_high;
+ unsigned char drive_head;
+ unsigned char commandreg;
+ unsigned int timestamp;
+} __attribute__ ((packed));
-#define NR_ATTRIBUTES 30
-
-typedef struct threshold_s {
- unsigned char id;
- unsigned char threshold;
- unsigned char reserved[10];
-} __attribute__ ((packed)) threshold_t;
-
-typedef struct thresholds_s {
- unsigned short revision;
- threshold_t thresholds[NR_ATTRIBUTES];
- unsigned char reserved[18];
- unsigned char vendor[131];
- unsigned char checksum;
-} __attribute__ ((packed)) thresholds_t;
-
-typedef struct value_s {
- unsigned char id;
- unsigned short status;
- unsigned char value;
- unsigned char vendor[8];
-} __attribute__ ((packed)) value_t;
-
-typedef struct values_s {
- unsigned short revision;
- value_t values[NR_ATTRIBUTES];
- unsigned char offline_status;
- unsigned char vendor1;
- unsigned short offline_timeout;
- unsigned char vendor2;
- unsigned char offline_capability;
- unsigned short smart_capability;
- unsigned char reserved[16];
- unsigned char vendor[125];
- unsigned char checksum;
-} __attribute__ ((packed)) values_t;
+struct ata_smart_errorlog_error_struct {
+ unsigned char error_condition;
+ unsigned char extended_error[14];
+ unsigned char state;
+ unsigned short timestamp;
+} __attribute__ ((packed));
+
+struct ata_smart_errorlog_struct {
+ struct ata_smart_errorlog_command_struct commands[6];
+ struct ata_smart_errorlog_error_struct error_struct;
+} __attribute__ ((packed));
+
+struct ata_smart_errorlog {
+ unsigned char revnumber;
+ unsigned char error_log_pointer;
+ struct ata_smart_errorlog_struct errorlog_struct[5];
+ unsigned short ata_error_count;
+ unsigned short non_fatal_count;
+ unsigned short drive_timeout_count;
+ unsigned char reserved[53];
+} __attribute__ ((packed));
+
+struct ata_smart_selftestlog_struct {
+ unsigned char selftestnumber;
+ unsigned char selfteststatus;
+ unsigned short timestamp;
+ unsigned char selftestfailurecheckpoint;
+ unsigned int lbafirstfailure;
+ unsigned char vendorspecific[15];
+} __attribute__ ((packed));
+
+struct ata_smart_selftestlog {
+ unsigned short revnumber;
+ struct ata_smart_selftestlog_struct selftest_struct[21];
+ unsigned char vendorspecific[2];
+ unsigned char mostrecenttest;
+ unsigned char resevered[2];
+ unsigned char chksum;
+} __attribute__ ((packed));
#if !defined(__KERNEL__) || defined(_IDE_DISK_C)
-
-#define NR_OFFLINE_TEXTS 5
-struct {
- unsigned char value;
- char *text;
-} offline_status_text[NR_OFFLINE_TEXTS] = {
- { 0x00, "NeverStarted" },
- { 0x02, "Completed" },
- { 0x04, "Suspended" },
- { 0x05, "Aborted" },
- { 0x06, "Failed" }
-};
+/* smartctl version number */
+#define VERSION_MAJOR 1
+#define VERSION_MINOR 2
+
+/* Number of ata device to scan */
+int numdevices;
+
+/* how often SMART is checks in seconds */
+int checktime = 1800;
+
+typedef struct atadevices_s {
+ int fd;
+ char devicename[14];
+ int selftest;
+ struct hd_driveid drive;
+ struct ata_smart_values smartval;
+ struct ata_smart_thresholds smartthres;
+} atadevices_t;
+
#endif /* !defined(__KERNEL__) || defined(_IDE_DISK_C) */
#endif /* _LINUX_HDSMART_H */
struct proc_dir_entry *proc; /* /proc/ide/ directory entry */
void *settings; /* /proc/ide/ drive settings */
char driver_req[10]; /* requests specific driver */
-#if 1
- struct thresholds_s *smart_thresholds;
- struct values_s *smart_values;
-#else
- thresholds_t smart_thresholds;
- values_t smart_values;
-#endif
int last_lun; /* last logical unit */
int forced_lun; /* if hdxlun was given at boot */
} ide_drive_t;
ide_resetproc_t *resetproc; /* routine to reset controller after a disk reset */
ide_dmaproc_t *dmaproc; /* dma read/write/abort routine */
unsigned int *dmatable_cpu; /* dma physical region descriptor table (cpu view) */
- u32 dmatable_dma; /* dma physical region descriptor table (dma view) */
+ dma_addr_t dmatable_dma; /* dma physical region descriptor table (dma view) */
struct scatterlist *sg_table; /* Scatter-gather list used to build the above */
int sg_nents; /* Current number of entries in it */
int sg_dma_direction; /* dma transfer direction */
typedef int (ide_open_proc)(struct inode *, struct file *, ide_drive_t *);
typedef void (ide_release_proc)(struct inode *, struct file *, ide_drive_t *);
typedef int (ide_check_media_change_proc)(ide_drive_t *);
+typedef void (ide_revalidate_proc)(ide_drive_t *);
typedef void (ide_pre_reset_proc)(ide_drive_t *);
typedef unsigned long (ide_capacity_proc)(ide_drive_t *);
typedef ide_startstop_t (ide_special_proc)(ide_drive_t *);
ide_open_proc *open;
ide_release_proc *release;
ide_check_media_change_proc *media_change;
+ ide_revalidate_proc *revalidate;
ide_pre_reset_proc *pre_reset;
ide_capacity_proc *capacity;
ide_special_proc *special;
int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
void ide_delay_50ms (void);
+int system_bus_clock(void);
int ide_driveid_update (ide_drive_t *drive);
int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature);
((unsigned char *)&addr)[2], \
((unsigned char *)&addr)[3]
+#define HIPQUAD(addr) \
+ ((unsigned char *)&addr)[3], \
+ ((unsigned char *)&addr)[2], \
+ ((unsigned char *)&addr)[1], \
+ ((unsigned char *)&addr)[0]
+
#endif /* __KERNEL__ */
#define SI_LOAD_SHIFT 16
#define VM_SEQ_READ 0x00008000 /* App will access data sequentially */
#define VM_RAND_READ 0x00010000 /* App will not benefit from clustered reads */
+#define VM_DONTCOPY 0x00020000 /* Do not copy this vma on fork */
+
#define VM_STACK_FLAGS 0x00000177
#define VM_READHINTMASK (VM_SEQ_READ | VM_RAND_READ)
struct iphdr *iph, size_t len,
enum ip_conntrack_info ctinfo);
- /* Called when a new connection for this protocol found; returns
- * TRUE if it's OK. If so, packet() called next. */
- int (*new)(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len);
+ /* Called when a new connection for this protocol found;
+ * returns timeout. If so, packet() called next. */
+ unsigned long (*new)(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len);
/* Module (if any) which this is connected to. */
struct module *me;
#ifndef _IPT_STATE_H
#define _IPT_STATE_H
-#define _IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)+1))
-#define IPT_STATE_BIT(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? _IPT_STATE_BIT((ctinfo)-IP_CT_IS_REPLY) : _IPT_STATE_BIT(ctinfo))
+#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
#define IPT_STATE_INVALID (1 << 0)
struct ipt_state_info
#define PCI_VENDOR_ID_ARTOP 0x1191
#define PCI_DEVICE_ID_ARTOP_ATP8400 0x0004
#define PCI_DEVICE_ID_ARTOP_ATP850UF 0x0005
+#define PCI_DEVICE_ID_ARTOP_ATP860 0x0006
+#define PCI_DEVICE_ID_ARTOP_ATP860R 0x0007
#define PCI_VENDOR_ID_ZEITNET 0x1193
#define PCI_DEVICE_ID_ZEITNET_1221 0x0001
#define timer_synchronize(t) while (timer_is_running(t)) barrier()
extern int del_timer_sync(struct timer_list * timer);
#else
-#define timer_exit(t) do { } while (0)
-#define timer_set_running(t) do { } while (0)
+#define timer_exit(t) (void)(t)
+#define timer_set_running(t) (void)(t)
#define timer_is_running(t) (0)
-#define timer_synchronize(t) barrier()
+#define timer_synchronize(t) do { (void)(t); barrier(); } while(0)
#define del_timer_sync(t) del_timer(t)
#endif
/*
* These are the public elements of the Linux kernel X.25 implementation.
+ *
+ * History
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#ifndef X25_KERNEL_H
/*
* DTE/DCE subscription options.
+ *
+ * As this is missing lots of options, user should expect major
+ * changes of this structure in 2.5.x which might break compatibilty.
+ * The somewhat ugly dimension 200-sizeof() is needed to maintain
+ * backward compatibility.
*/
struct x25_subscrip_struct {
- char device[200];
+ char device[200-sizeof(unsigned long)];
+ unsigned long global_facil_mask; /* 0 to disable negotiation */
unsigned int extended;
};
+/* values for above global_facil_mask */
+
+#define X25_MASK_REVERSE 0x01
+#define X25_MASK_THROUGHPUT 0x02
+#define X25_MASK_PACKET_SIZE 0x04
+#define X25_MASK_WINDOW_SIZE 0x08
+
+
+
/*
* Routing table control structure.
*/
struct msghdr *, int,
struct scm_cookie *);
extern int sock_no_recvmsg(struct socket *,
- struct msghdr *, int,
+ struct msghdr *, int, int,
struct scm_cookie *);
extern int sock_no_mmap(struct file *file,
struct socket *sock,
/*
* Declarations of X.25 Packet Layer type objects.
*
- * Jonathan Naylor 17/11/96
+ * History
+ * nov/17/96 Jonathan Naylor Initial version.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#ifndef _X25_H
struct sk_buff_head queue;
unsigned long t20;
struct timer_list t20timer;
+ unsigned long global_facil_mask;
};
typedef struct {
struct x25_causediag causediag;
struct x25_facilities facilities;
struct x25_calluserdata calluserdata;
+ unsigned long vc_facil_mask; /* inc_call facilities mask */
} x25_cb;
/* af_x25.c */
extern void x25_terminate_link(struct x25_neigh *);
/* x25_facilities.c */
-extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *);
-extern int x25_create_facilities(unsigned char *, struct x25_facilities *);
+extern int x25_parse_facilities(struct sk_buff *, struct x25_facilities *, unsigned long *);
+extern int x25_create_facilities(unsigned char *, struct x25_facilities *, unsigned long);
extern int x25_negotiate_facilities(struct sk_buff *, struct sock *, struct x25_facilities *);
extern void x25_limit_facilities(struct x25_facilities *, struct x25_neigh *);
static int shm_statfs(struct super_block *sb, struct statfs *buf)
{
- buf->f_type = 0;
+ buf->f_type = SHM_FS_MAGIC;
buf->f_bsize = PAGE_SIZE;
buf->f_blocks = shm_ctlall;
buf->f_bavail = buf->f_bfree = shm_ctlall - shm_tot;
struct file *file;
retval = -ENOMEM;
+ if(mpnt->vm_flags & VM_DONTCOPY)
+ continue;
tmp = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
if (!tmp)
goto fail_nomem;
? -EFAULT : 0;
}
-#if !defined(__ia64__)
+#if !defined(__ia64__) && !defined(__s390__)
/*
* Back compatibility for getrlimit. Needed for some apps.
static ctl_table vm_table[] = {
{VM_FREEPG, "freepages",
&freepages, sizeof(freepages_t), 0644, NULL, &proc_dointvec},
- {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0600, NULL,
+ {VM_BDFLUSH, "bdflush", &bdf_prm, 9*sizeof(int), 0644, NULL,
&proc_dointvec_minmax, &sysctl_intvec, NULL,
&bdflush_min, &bdflush_max},
{VM_OVERCOMMIT_MEMORY, "overcommit_memory", &sysctl_overcommit_memory,
{VM_PAGERDAEMON, "kswapd",
&pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
{VM_PGT_CACHE, "pagetable_cache",
- &pgt_cache_water, 2*sizeof(int), 0600, NULL, &proc_dointvec},
+ &pgt_cache_water, 2*sizeof(int), 0644, NULL, &proc_dointvec},
{VM_PAGE_CLUSTER, "page-cluster",
- &page_cluster, sizeof(int), 0600, NULL, &proc_dointvec},
+ &page_cluster, sizeof(int), 0644, NULL, &proc_dointvec},
{0}
};
if(entry)
{
#if TR_SR_DEBUG
-printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0],
+printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0],
trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]);
#endif
if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8)
DPRINTK("clip_arp_rcv\n");
vcc = ATM_SKB(skb)->vcc;
if (!vcc || !atm_charge(vcc,skb->truesize)) {
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return 0;
}
DPRINTK("pushing to %p\n",vcc);
atm_return(vcc,skb->truesize);
skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs;
/* clip_vcc->entry == NULL if we don't have an IP address yet */
- skb->rx_dev = NULL;
if (!skb->dev) {
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return;
}
ATM_SKB(skb)->vcc = vcc;
static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb)
{
struct clip_vcc *clip_vcc = CLIP_VCC(vcc);
+ struct net_device *dev = skb->dev;
int old;
+ unsigned long flags;
DPRINTK("clip_pop(vcc %p)\n",vcc);
clip_vcc->old_pop(vcc,skb);
/* skb->dev == NULL in outbound ARP packets */
- if (!skb->dev) return;
- spin_lock(&PRIV(skb->dev)->xoff_lock);
+ if (!dev) return;
+ spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags);
if (atm_may_send(vcc,0)) {
old = xchg(&clip_vcc->xoff,0);
- if (old) netif_wake_queue(skb->dev);
+ if (old) netif_wake_queue(dev);
}
- spin_unlock(&PRIV(skb->dev)->xoff_lock);
+ spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags);
}
struct atmarp_entry *entry;
struct atm_vcc *vcc;
int old;
+ unsigned long flags;
DPRINTK("clip_start_xmit (skb %p)\n",skb);
if (!skb->dst) {
return 0;
}
if (old) return 0;
- spin_lock(&clip_priv->xoff_lock);
+ spin_lock_irqsave(&clip_priv->xoff_lock,flags);
netif_stop_queue(dev); /* XOFF -> throttle immediately */
barrier();
if (!entry->vccs->xoff)
good enough, because nothing should really be asleep because
of the brief netif_stop_queue. If this isn't true or if it
changes, use netif_wake_queue instead. */
- spin_unlock(&clip_priv->xoff_lock);
+ spin_unlock_irqrestore(&clip_priv->xoff_lock,flags);
return 0;
}
vcc->atm_options = vcc->aal_options = 0;
vcc->timestamp.tv_sec = vcc->timestamp.tv_usec = 0;
init_waitqueue_head(&vcc->sleep);
- init_waitqueue_head(&vcc->wsleep);
skb_queue_head_init(&vcc->recvq);
skb_queue_head_init(&vcc->listenq);
sock->sk = sk;
if (!size) return 0;
/* verify_area is done by net/socket.c */
eff = (size+3) & ~3; /* align to word boundary */
- add_wait_queue(&vcc->wsleep,&wait);
+ add_wait_queue(&vcc->sleep,&wait);
set_current_state(TASK_INTERRUPTIBLE);
error = 0;
while (!(skb = vcc->alloc_tx(vcc,eff))) {
}
}
set_current_state(TASK_RUNNING);
- remove_wait_queue(&vcc->wsleep,&wait);
+ remove_wait_queue(&vcc->sleep,&wait);
if (error) return error;
skb->dev = NULL; /* for paths shared with net_device interfaces */
ATM_SKB(skb)->iovcnt = 0;
vcc = ATM_SD(sock);
poll_wait(file,&vcc->sleep,wait);
- poll_wait(file,&vcc->wsleep,wait);
mask = 0;
if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq))
mask |= POLLIN | POLLRDNORM;
/* net/atm/common.h - ATM sockets (common part for PVC and SVC) */
-/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */
+/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */
#ifndef NET_ATM_COMMON_H
int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci);
void atm_release_vcc_sk(struct sock *sk,int free_sk);
int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos);
-/* -- now in atmdev.h:
-void atm_async_release_vcc(struct atm_vcc *vcc,int reply);
-*/
void atm_shutdown_dev(struct atm_dev *dev);
int atm_proc_init(void);
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
-rwlock_t lane_bridge_hook_lock = RW_LOCK_UNLOCKED;
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
unsigned char *addr) = NULL;
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL;
#if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE)
-EXPORT_SYMBOL(lane_bridge_hook_lock);
EXPORT_SYMBOL(br_fdb_get_hook);
EXPORT_SYMBOL(br_fdb_put_hook);
#endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */
#if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <linux/if_bridge.h>
#include "../bridge/br_private.h"
-unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
+static unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00};
#endif
/* Modular too */
mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3],
mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]);
- read_lock(&lane_bridge_hook_lock);
- if (br_fdb_get_hook == NULL || dev->br_port == NULL) {
- read_unlock(&lane_bridge_hook_lock);
+ if (br_fdb_get_hook == NULL || dev->br_port == NULL)
break;
- }
f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr);
if (f != NULL &&
skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
if (skb2 == NULL) {
br_fdb_put_hook(f);
- read_unlock(&lane_bridge_hook_lock);
break;
}
skb2->len = sizeof(struct atmlec_msg);
wake_up(&priv->lecd->sleep);
}
if (f != NULL) br_fdb_put_hook(f);
- read_unlock(&lane_bridge_hook_lock);
#endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
}
break;
lec_arp_check_empties(priv, vcc, skb);
}
skb->dev = dev;
- skb->rx_dev = NULL;
skb->data += 2; /* skip lec_id */
#ifdef CONFIG_TR
if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev);
if (entry->recv_vcc) {
entry->recv_vcc->push = entry->old_recv_push;
#if 0
- set_bit(ATM_VF_RELEASED,&entry->vcc->flags);
- clear_bit(ATM_VF_READY,&entry->vcc->flags);
+ set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags);
+ clear_bit(ATM_VF_READY,&entry->recv_vcc->flags);
entry->recv_vcc->push(entry->recv_vcc, NULL);
#endif
atm_async_release_vcc(entry->recv_vcc, -EPIPE);
#if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
#include <linux/if_bridge.h>
-extern rwlock_t lane_bridge_hook_lock;
struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br,
unsigned char *addr);
void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent);
static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc);
static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
- uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
+ uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type);
static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry);
static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc);
static void mpc_cache_check( unsigned long checking_time );
static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x5e},
- {0x00, 0x03} /* For MPOA control PDUs */
+ 0xaa, 0xaa, 0x03,
+ {0x00, 0x00, 0x5e},
+ {0x00, 0x03} /* For MPOA control PDUs */
};
static struct llc_snap_hdr llc_snap_mpoa_data = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x00},
- {0x08, 0x00} /* This is for IP PDUs only */
+ 0xaa, 0xaa, 0x03,
+ {0x00, 0x00, 0x00},
+ {0x08, 0x00} /* This is for IP PDUs only */
};
static struct llc_snap_hdr llc_snap_mpoa_data_tagged = {
- 0xaa, 0xaa, 0x03,
- {0x00, 0x00, 0x00},
- {0x88, 0x4c} /* This is for tagged data PDUs */
+ 0xaa, 0xaa, 0x03,
+ {0x00, 0x00, 0x00},
+ {0x88, 0x4c} /* This is for tagged data PDUs */
};
static struct notifier_block mpoa_notifier = {
- mpoa_event_listener,
- NULL,
- 0
+ mpoa_event_listener,
+ NULL,
+ 0
};
#ifdef CONFIG_PROC_FS
static struct mpoa_client *find_mpc_by_itfnum(int itf)
{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->dev_num == itf)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
+ struct mpoa_client *mpc;
+
+ mpc = mpcs; /* our global linked list */
+ while (mpc != NULL) {
+ if (mpc->dev_num == itf)
+ return mpc;
+ mpc = mpc->next;
+ }
+
+ return NULL; /* not found */
}
static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc)
{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->mpoad_vcc == vcc)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
+ struct mpoa_client *mpc;
+
+ mpc = mpcs; /* our global linked list */
+ while (mpc != NULL) {
+ if (mpc->mpoad_vcc == vcc)
+ return mpc;
+ mpc = mpc->next;
+ }
+
+ return NULL; /* not found */
}
static struct mpoa_client *find_mpc_by_lec(struct net_device *dev)
{
- struct mpoa_client *mpc;
-
- mpc = mpcs; /* our global linked list */
- while (mpc != NULL) {
- if (mpc->dev == dev)
- return mpc;
- mpc = mpc->next;
- }
-
- return NULL; /* not found */
+ struct mpoa_client *mpc;
+
+ mpc = mpcs; /* our global linked list */
+ while (mpc != NULL) {
+ if (mpc->dev == dev)
+ return mpc;
+ mpc = mpc->next;
+ }
+
+ return NULL; /* not found */
}
/*
*/
struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos)
{
- struct atm_mpoa_qos *entry;
+ struct atm_mpoa_qos *entry;
- entry = atm_mpoa_search_qos(dst_ip);
- if (entry != NULL) {
- entry->qos = *qos;
- return entry;
- }
+ entry = atm_mpoa_search_qos(dst_ip);
+ if (entry != NULL) {
+ entry->qos = *qos;
+ return entry;
+ }
- entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
- if (entry == NULL) {
- printk("mpoa: atm_mpoa_add_qos: out of memory\n");
- return entry;
- }
+ entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL);
+ if (entry == NULL) {
+ printk("mpoa: atm_mpoa_add_qos: out of memory\n");
+ return entry;
+ }
- entry->ipaddr = dst_ip;
- entry->qos = *qos;
+ entry->ipaddr = dst_ip;
+ entry->qos = *qos;
- entry->next = qos_head;
- qos_head = entry;
+ entry->next = qos_head;
+ qos_head = entry;
- return entry;
+ return entry;
}
struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip)
{
- struct atm_mpoa_qos *qos;
+ struct atm_mpoa_qos *qos;
- qos = qos_head;
- while( qos != NULL ){
- if(qos->ipaddr == dst_ip) {
- break;
+ qos = qos_head;
+ while( qos != NULL ){
+ if(qos->ipaddr == dst_ip) {
+ break;
}
- qos = qos->next;
- }
+ qos = qos->next;
+ }
- return qos;
+ return qos;
}
/*
int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry)
{
- struct atm_mpoa_qos *curr;
-
- if (entry == NULL) return 0;
- if (entry == qos_head) {
- qos_head = qos_head->next;
- kfree(entry);
- return 1;
- }
-
- curr = qos_head;
- while (curr != NULL) {
- if (curr->next == entry) {
- curr->next = entry->next;
- kfree(entry);
- return 1;
- }
- curr = curr->next;
- }
-
- return 0;
+ struct atm_mpoa_qos *curr;
+
+ if (entry == NULL) return 0;
+ if (entry == qos_head) {
+ qos_head = qos_head->next;
+ kfree(entry);
+ return 1;
+ }
+
+ curr = qos_head;
+ while (curr != NULL) {
+ if (curr->next == entry) {
+ curr->next = entry->next;
+ kfree(entry);
+ return 1;
+ }
+ curr = curr->next;
+ }
+
+ return 0;
}
void atm_mpoa_disp_qos(char *page, int *len)
ipaddr[sizeof(ipaddr)-1] = '\0';
while (qos != NULL) {
ip = (unsigned char *)&qos->ipaddr;
- sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
- *len += sprintf(page + *len, "%-16s\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
- ipaddr,
+ sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip));
+ *len += sprintf(page + *len, "%%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n",
+ NIPQUAD(ipaddr),
qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu,
qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu);
qos = qos->next;
static struct net_device *find_lec_by_itfnum(int itf)
{
- extern struct atm_lane_ops atm_lane_ops; /* in common.c */
-
- if (atm_lane_ops.get_lecs == NULL)
- return NULL;
+ extern struct atm_lane_ops atm_lane_ops; /* in common.c */
+
+ if (atm_lane_ops.get_lecs == NULL)
+ return NULL;
- return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
+ return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */
}
static struct mpoa_client *alloc_mpc(void)
{
- struct mpoa_client *mpc;
-
- mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
- if (mpc == NULL)
- return NULL;
- memset(mpc, 0, sizeof(struct mpoa_client));
-#if 0 /* compiler seems to barf on this */
- mpc->ingress_lock = RW_LOCK_UNLOCKED;
- mpc->egress_lock = RW_LOCK_UNLOCKED;
-#endif
- mpc->next = mpcs;
- atm_mpoa_init_cache(mpc);
+ struct mpoa_client *mpc;
+
+ mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL);
+ if (mpc == NULL)
+ return NULL;
+ memset(mpc, 0, sizeof(struct mpoa_client));
+ mpc->ingress_lock = RW_LOCK_UNLOCKED;
+ mpc->egress_lock = RW_LOCK_UNLOCKED;
+ mpc->next = mpcs;
+ atm_mpoa_init_cache(mpc);
mpc->parameters.mpc_p1 = MPC_P1;
mpc->parameters.mpc_p2 = MPC_P2;
mpc->parameters.mpc_p5 = MPC_P5;
mpc->parameters.mpc_p6 = MPC_P6;
- mpcs = mpc;
+ mpcs = mpc;
- return mpc;
+ return mpc;
}
/*
*/
static void start_mpc(struct mpoa_client *mpc, struct net_device *dev)
{
-
- dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name);
- if (dev->hard_start_xmit == NULL) {
- printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
- dev->name);
- return;
- }
- mpc->old_hard_start_xmit = dev->hard_start_xmit;
- dev->hard_start_xmit = mpc_send_packet;
-
- return;
+
+ dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name);
+ if (dev->hard_start_xmit == NULL) {
+ printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n",
+ dev->name);
+ return;
+ }
+ mpc->old_hard_start_xmit = dev->hard_start_xmit;
+ dev->hard_start_xmit = mpc_send_packet;
+
+ return;
}
static void stop_mpc(struct mpoa_client *mpc)
{
-
- dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name);
-
- /* Lets not nullify lec device's dev->hard_start_xmit */
- if (mpc->dev->hard_start_xmit != mpc_send_packet) {
- dprintk(" mpc already stopped, not fatal\n");
- return;
- }
- dprintk("\n");
- mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
- mpc->old_hard_start_xmit = NULL;
+
+ dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name);
+
+ /* Lets not nullify lec device's dev->hard_start_xmit */
+ if (mpc->dev->hard_start_xmit != mpc_send_packet) {
+ dprintk(" mpc already stopped, not fatal\n");
+ return;
+ }
+ dprintk("\n");
+ mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit;
+ mpc->old_hard_start_xmit = NULL;
/* close_shortcuts(mpc); ??? FIXME */
-
- return;
+
+ return;
}
static const char * __attribute__ ((unused)) mpoa_device_type_string(char type)
{
- switch(type) {
- case NON_MPOA:
- return "non-MPOA device";
- break;
- case MPS:
- return "MPS";
- break;
- case MPC:
- return "MPC";
- break;
- case MPS_AND_MPC:
- return "both MPS and MPC";
- break;
- default:
- return "unspecified (non-MPOA) device";
- break;
- }
-
- return ""; /* not reached */
+ switch(type) {
+ case NON_MPOA:
+ return "non-MPOA device";
+ break;
+ case MPS:
+ return "MPS";
+ break;
+ case MPC:
+ return "MPC";
+ break;
+ case MPS_AND_MPC:
+ return "both MPS and MPC";
+ break;
+ default:
+ return "unspecified (non-MPOA) device";
+ break;
+ }
+
+ return ""; /* not reached */
}
/*
*
*/
static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr,
- uint8_t *tlvs, uint32_t sizeoftlvs)
+ uint8_t *tlvs, uint32_t sizeoftlvs)
{
- uint32_t type;
- uint8_t length, mpoa_device_type, number_of_mps_macs;
- uint8_t *end_of_tlvs;
- struct mpoa_client *mpc;
-
- mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
- dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
- dprintk("total length of all TLVs %d\n", sizeoftlvs);
+ uint32_t type;
+ uint8_t length, mpoa_device_type, number_of_mps_macs;
+ uint8_t *end_of_tlvs;
+ struct mpoa_client *mpc;
+
+ mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */
+ dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name);
+ dprintk("total length of all TLVs %d\n", sizeoftlvs);
mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */
- if (mpc == NULL) {
- printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
- return;
- }
- end_of_tlvs = tlvs + sizeoftlvs;
- while (end_of_tlvs - tlvs >= 5) {
- type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
- length = tlvs[4];
- tlvs += 5;
- dprintk(" type 0x%x length %02x\n", type, length);
- if (tlvs + length > end_of_tlvs) {
- printk("TLV value extends past its buffer, aborting parse\n");
- return;
- }
-
- if (type == 0) {
- printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
- return;
+ if (mpc == NULL) {
+ printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name);
+ return;
+ }
+ end_of_tlvs = tlvs + sizeoftlvs;
+ while (end_of_tlvs - tlvs >= 5) {
+ type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3];
+ length = tlvs[4];
+ tlvs += 5;
+ dprintk(" type 0x%x length %02x\n", type, length);
+ if (tlvs + length > end_of_tlvs) {
+ printk("TLV value extends past its buffer, aborting parse\n");
+ return;
+ }
+
+ if (type == 0) {
+ printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name);
+ return;
}
- if (type != TLV_MPOA_DEVICE_TYPE) {
- tlvs += length;
- continue; /* skip other TLVs */
- }
- mpoa_device_type = *tlvs++;
- number_of_mps_macs = *tlvs++;
- dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
- if (mpoa_device_type == MPS_AND_MPC &&
- length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
- printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
- dev->name);
- continue;
- }
- if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
- && length < 22 + number_of_mps_macs*ETH_ALEN) {
- printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
- dev->name);
- continue;
- }
- if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
- dprintk("ignoring non-MPS device\n");
- if (mpoa_device_type == MPC) tlvs += 20;
- continue; /* we are only interested in MPSs */
- }
- if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
- printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
- continue; /* someone should read the spec */
- }
- dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
-
- /* ok, now we can go and tell our daemon the control address of MPS */
- send_set_mps_ctrl_addr(tlvs, mpc);
-
- tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
- if (tlvs == NULL) return;
- }
- if (end_of_tlvs - tlvs != 0)
- printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n",
- dev->name, end_of_tlvs - tlvs);
- return;
+ if (type != TLV_MPOA_DEVICE_TYPE) {
+ tlvs += length;
+ continue; /* skip other TLVs */
+ }
+ mpoa_device_type = *tlvs++;
+ number_of_mps_macs = *tlvs++;
+ dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type));
+ if (mpoa_device_type == MPS_AND_MPC &&
+ length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */
+ printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
+ dev->name);
+ continue;
+ }
+ if ((mpoa_device_type == MPS || mpoa_device_type == MPC)
+ && length < 22 + number_of_mps_macs*ETH_ALEN) {
+ printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n",
+ dev->name);
+ continue;
+ }
+ if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) {
+ dprintk("ignoring non-MPS device\n");
+ if (mpoa_device_type == MPC) tlvs += 20;
+ continue; /* we are only interested in MPSs */
+ }
+ if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) {
+ printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name);
+ continue; /* someone should read the spec */
+ }
+ dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs);
+
+ /* ok, now we can go and tell our daemon the control address of MPS */
+ send_set_mps_ctrl_addr(tlvs, mpc);
+
+ tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type);
+ if (tlvs == NULL) return;
+ }
+ if (end_of_tlvs - tlvs != 0)
+ printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n",
+ dev->name, end_of_tlvs - tlvs);
+ return;
}
/*
* For a freshly allocated MPOA client mpc->mps_macs == 0.
*/
static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac,
- uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
+ uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type)
{
- int num_macs;
- num_macs = (mps_macs > 1) ? mps_macs : 1;
-
- if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
- if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
- mpc->number_of_mps_macs = 0;
- mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
- if (mpc->mps_macs == NULL) {
- printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
- return NULL;
- }
- }
- memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
- tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
- if (mps_macs > 0)
- memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
- tlvs += mps_macs*ETH_ALEN;
- mpc->number_of_mps_macs = num_macs;
-
- return tlvs;
+ int num_macs;
+ num_macs = (mps_macs > 1) ? mps_macs : 1;
+
+ if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */
+ if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs);
+ mpc->number_of_mps_macs = 0;
+ mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL);
+ if (mpc->mps_macs == NULL) {
+ printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name);
+ return NULL;
+ }
+ }
+ memcpy(mpc->mps_macs, router_mac, ETH_ALEN);
+ tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20;
+ if (mps_macs > 0)
+ memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN);
+ tlvs += mps_macs*ETH_ALEN;
+ mpc->number_of_mps_macs = num_macs;
+
+ return tlvs;
}
-/* FIXME: tarvitsee työtä */
static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc)
{
- in_cache_entry *entry;
- struct iphdr *iph;
- char *buff;
- uint32_t ipaddr = 0;
-
- static struct {
- struct llc_snap_hdr hdr;
- uint32_t tag;
- } tagged_llc_snap_hdr = {
- {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
- 0
- };
-
- buff = skb->data + mpc->dev->hard_header_len;
- iph = (struct iphdr *)buff;
+ in_cache_entry *entry;
+ struct iphdr *iph;
+ char *buff;
+ uint32_t ipaddr = 0;
+
+ static struct {
+ struct llc_snap_hdr hdr;
+ uint32_t tag;
+ } tagged_llc_snap_hdr = {
+ {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}},
+ 0
+ };
+
+ buff = skb->data + mpc->dev->hard_header_len;
+ iph = (struct iphdr *)buff;
ipaddr = iph->daddr;
- ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);
-
- entry = mpc->in_ops->search(ipaddr, mpc);
- if (entry == NULL) {
- mpc->in_ops->new_entry(ipaddr, mpc);
- return 1;
- }
- if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */
- ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);
- return 1;
- }
-
- ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);
- /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
- if (iph->ttl <= 1) {
- ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);
- return 1;
- }
- iph->ttl--;
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- if (entry->ctrl_info.tag != 0) {
- ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
- tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
- skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
- skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */
- memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
- } else {
- skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
- skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */
- memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
- }
-
- atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
+ ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr);
+
+ entry = mpc->in_ops->get(ipaddr, mpc);
+ if (entry == NULL) {
+ entry = mpc->in_ops->add_entry(ipaddr, mpc);
+ if (entry != NULL) mpc->in_ops->put(entry);
+ return 1;
+ }
+ if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */
+ ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name);
+ mpc->in_ops->put(entry);
+ return 1;
+ }
+
+ ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name);
+ /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */
+ if (iph->ttl <= 1) {
+ ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl);
+ mpc->in_ops->put(entry);
+ return 1;
+ }
+ iph->ttl--;
+ iph->check = 0;
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+ if (entry->ctrl_info.tag != 0) {
+ ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag);
+ tagged_llc_snap_hdr.tag = entry->ctrl_info.tag;
+ skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
+ skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */
+ memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr));
+ } else {
+ skb_pull(skb, ETH_HLEN); /* get rid of Eth header */
+ skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */
+ memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
+ }
+
+ atomic_add(skb->truesize, &entry->shortcut->tx_inuse);
ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */
ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
- entry->shortcut->send(entry->shortcut, skb);
+ entry->shortcut->send(entry->shortcut, skb);
entry->packets_fwded++;
+ mpc->in_ops->put(entry);
- return 0;
+ return 0;
}
/*
*/
static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- int retval;
- struct mpoa_client *mpc;
- struct ethhdr *eth;
- int i = 0;
-
- mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
- if(mpc == NULL) {
- printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
- goto non_ip;
- }
-
- eth = (struct ethhdr *)skb->data;
- if (eth->h_proto != htons(ETH_P_IP))
- goto non_ip; /* Multi-Protocol Over ATM :-) */
-
- while (i < mpc->number_of_mps_macs) {
- if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
- if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
- return 0; /* success! */
- i++;
- }
+ int retval;
+ struct mpoa_client *mpc;
+ struct ethhdr *eth;
+ int i = 0;
+
+ mpc = find_mpc_by_lec(dev); /* this should NEVER fail */
+ if(mpc == NULL) {
+ printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name);
+ goto non_ip;
+ }
+
+ eth = (struct ethhdr *)skb->data;
+ if (eth->h_proto != htons(ETH_P_IP))
+ goto non_ip; /* Multi-Protocol Over ATM :-) */
+
+ while (i < mpc->number_of_mps_macs) {
+ if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0)
+ if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */
+ return 0; /* success! */
+ i++;
+ }
non_ip:
- retval = mpc->old_hard_start_xmit(skb,dev);
-
- return retval;
+ retval = mpc->old_hard_start_xmit(skb,dev);
+
+ return retval;
}
int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg)
{
- int bytes_left;
- struct mpoa_client *mpc;
- struct atmmpc_ioc ioc_data;
- in_cache_entry *in_entry;
- uint32_t ipaddr;
+ int bytes_left;
+ struct mpoa_client *mpc;
+ struct atmmpc_ioc ioc_data;
+ in_cache_entry *in_entry;
+ uint32_t ipaddr;
unsigned char *ip;
- bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc));
- if (bytes_left != 0) {
- printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left);
- return -EFAULT;
- }
- ipaddr = ioc_data.ipaddr;
- if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
- return -EINVAL;
-
- mpc = find_mpc_by_itfnum(ioc_data.dev_num);
- if (mpc == NULL)
- return -EINVAL;
-
- if (ioc_data.type == MPC_SOCKET_INGRESS) {
- in_entry = mpc->in_ops->search(ipaddr, mpc);
- if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
- printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
- mpc->dev->name);
- return -EINVAL;
- }
+ bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc));
+ if (bytes_left != 0) {
+ printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left);
+ return -EFAULT;
+ }
+ ipaddr = ioc_data.ipaddr;
+ if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF)
+ return -EINVAL;
+
+ mpc = find_mpc_by_itfnum(ioc_data.dev_num);
+ if (mpc == NULL)
+ return -EINVAL;
+
+ if (ioc_data.type == MPC_SOCKET_INGRESS) {
+ in_entry = mpc->in_ops->get(ipaddr, mpc);
+ if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) {
+ printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n",
+ mpc->dev->name);
+ if (in_entry != NULL) mpc->in_ops->put(in_entry);
+ return -EINVAL;
+ }
ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip;
- printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
- mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
- in_entry->shortcut = vcc;
- } else {
- printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
- }
-
- vcc->proto_data = mpc->dev;
- vcc->push = mpc_push;
-
- return 0;
+ printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n",
+ mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ in_entry->shortcut = vcc;
+ mpc->in_ops->put(in_entry);
+ } else {
+ printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name);
+ }
+
+ vcc->proto_data = mpc->dev;
+ vcc->push = mpc_push;
+
+ return 0;
}
/*
*/
static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev)
{
- struct mpoa_client *mpc;
- in_cache_entry *in_entry;
- eg_cache_entry *eg_entry;
-
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL) {
- printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
- return;
- }
-
- dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
- in_entry = mpc->in_ops->search_by_vcc(vcc, mpc);
- if (in_entry) {
- unsigned char *ip __attribute__ ((unused)) =
+ struct mpoa_client *mpc;
+ in_cache_entry *in_entry;
+ eg_cache_entry *eg_entry;
+
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL) {
+ printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name);
+ return;
+ }
+
+ dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name);
+ in_entry = mpc->in_ops->get_by_vcc(vcc, mpc);
+ if (in_entry) {
+ unsigned char *ip __attribute__ ((unused)) =
(unsigned char *)&in_entry->ctrl_info.in_dst_ip;
- dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
- mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
- in_entry->shortcut = NULL;
- }
- eg_entry = mpc->eg_ops->search_by_vcc(vcc, mpc);
- if (eg_entry) {
- dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
- eg_entry->shortcut = NULL;
- }
-
- if (in_entry == NULL && eg_entry == NULL)
- dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name);
-
- return;
+ dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n",
+ mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ in_entry->shortcut = NULL;
+ mpc->in_ops->put(in_entry);
+ }
+ eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc);
+ if (eg_entry) {
+ dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name);
+ eg_entry->shortcut = NULL;
+ mpc->eg_ops->put(eg_entry);
+ }
+
+ if (in_entry == NULL && eg_entry == NULL)
+ dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name);
+
+ return;
}
static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb)
{
- struct net_device *dev = (struct net_device *)vcc->proto_data;
- struct sk_buff *new_skb;
- eg_cache_entry *eg;
- struct mpoa_client *mpc;
+ struct net_device *dev = (struct net_device *)vcc->proto_data;
+ struct sk_buff *new_skb;
+ eg_cache_entry *eg;
+ struct mpoa_client *mpc;
uint32_t tag;
- char *tmp;
-
- ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
- if (skb == NULL) {
- dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
- mpc_vcc_close(vcc, dev);
- return;
- }
-
- skb->dev = dev;
- if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
- dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
- skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */
- wake_up(&vcc->sleep);
- return;
- }
-
- /* data coming over the shortcut */
- atm_return(vcc, skb->truesize);
+ char *tmp;
+
+ ddprintk("mpoa: (%s) mpc_push:\n", dev->name);
+ if (skb == NULL) {
+ dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name);
+ mpc_vcc_close(vcc, dev);
+ return;
+ }
+
+ skb->dev = dev;
+ if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
+ dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
+ skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */
+ wake_up(&vcc->sleep);
+ return;
+ }
+
+ /* data coming over the shortcut */
+ atm_return(vcc, skb->truesize);
mpc = find_mpc_by_lec(dev);
- if (mpc == NULL) {
- printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
- return;
- }
+ if (mpc == NULL) {
+ printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name);
+ return;
+ }
- if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
- ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
+ if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */
+ ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name);
- } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
- printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
- printk(" mpc_push: non-tagged data unsupported, purging\n");
- kfree_skb(skb);
- return;
- } else {
- printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
- kfree_skb(skb);
- return;
- }
-
- tmp = skb->data + sizeof(struct llc_snap_hdr);
- tag = *(uint32_t *)tmp;
-
- eg = mpc->eg_ops->search_by_tag(tag, mpc);
- if (eg == NULL) {
- printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
- dev->name,tag);
- purge_egress_shortcut(vcc, NULL);
- kfree_skb(skb);
- return;
- }
-
- /*
- * See if ingress MPC is using shortcut we opened as a return channel.
- * This means we have a bi-directional vcc opened by us.
- */
- if (eg->shortcut == NULL) {
- eg->shortcut = vcc;
- printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
- }
-
- skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
- new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
- kfree_skb(skb);
- if (new_skb == NULL) return;
- skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */
- memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
- new_skb->protocol = eth_type_trans(new_skb, dev);
- new_skb->nh.raw = new_skb->data;
+ } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */
+ printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name);
+ printk(" mpc_push: non-tagged data unsupported, purging\n");
+ dev_kfree_skb_any(skb);
+ return;
+ } else {
+ printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ tmp = skb->data + sizeof(struct llc_snap_hdr);
+ tag = *(uint32_t *)tmp;
+
+ eg = mpc->eg_ops->get_by_tag(tag, mpc);
+ if (eg == NULL) {
+ printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n",
+ dev->name,tag);
+ purge_egress_shortcut(vcc, NULL);
+ dev_kfree_skb_any(skb);
+ return;
+ }
+
+ /*
+ * See if ingress MPC is using shortcut we opened as a return channel.
+ * This means we have a bi-directional vcc opened by us.
+ */
+ if (eg->shortcut == NULL) {
+ eg->shortcut = vcc;
+ printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name);
+ }
+
+ skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */
+ new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */
+ dev_kfree_skb_any(skb);
+ if (new_skb == NULL){
+ mpc->eg_ops->put(eg);
+ return;
+ }
+ skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */
+ memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length);
+ new_skb->protocol = eth_type_trans(new_skb, dev);
+ new_skb->nh.raw = new_skb->data;
eg->latest_ip_addr = new_skb->nh.iph->saddr;
- eg->packets_rcvd++;
-
- netif_rx(new_skb);
+ eg->packets_rcvd++;
+ mpc->eg_ops->put(eg);
+
+ netif_rx(new_skb);
- return;
+ return;
}
static struct atmdev_ops mpc_ops = { /* only send is required */
- close: mpoad_close,
- send: msg_from_mpoad
+ close: mpoad_close,
+ send: msg_from_mpoad
};
static struct atm_dev mpc_dev = {
- &mpc_ops, /* device operations */
- NULL, /* PHY operations */
- "mpc", /* device type name */
- 42, /* device index (dummy) */
- NULL, /* VCC table */
- NULL, /* last VCC */
- NULL, /* per-device data */
- NULL, /* private PHY data */
- { 0 }, /* device flags */
- NULL, /* local ATM address */
- { 0 } /* no ESI */
- /* rest of the members will be 0 */
+ &mpc_ops, /* device operations */
+ NULL, /* PHY operations */
+ "mpc", /* device type name */
+ 42, /* device index (dummy) */
+ NULL, /* VCC table */
+ NULL, /* last VCC */
+ NULL, /* per-device data */
+ NULL, /* private PHY data */
+ { 0 }, /* device flags */
+ NULL, /* local ATM address */
+ { 0 } /* no ESI */
+ /* rest of the members will be 0 */
};
int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg)
{
- struct mpoa_client *mpc;
- struct lec_priv *priv;
-
- if (mpcs == NULL) {
- init_timer(&mpc_timer);
- mpc_timer_refresh();
-
- /* This lets us now how our LECs are doing */
- register_netdevice_notifier(&mpoa_notifier);
- }
-
- mpc = find_mpc_by_itfnum(arg);
- if (mpc == NULL) {
- dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
- mpc = alloc_mpc();
- mpc->dev_num = arg;
- mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
- }
- if (mpc->mpoad_vcc) {
- printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
- return -EADDRINUSE;
- }
-
- if (mpc->dev) { /* check if the lec is LANE2 capable */
- priv = (struct lec_priv *)mpc->dev->priv;
- if (priv->lane_version < 2)
- mpc->dev = NULL;
+ struct mpoa_client *mpc;
+ struct lec_priv *priv;
+
+ if (mpcs == NULL) {
+ init_timer(&mpc_timer);
+ mpc_timer_refresh();
+
+ /* This lets us now how our LECs are doing */
+ register_netdevice_notifier(&mpoa_notifier);
+ }
+
+ mpc = find_mpc_by_itfnum(arg);
+ if (mpc == NULL) {
+ dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg);
+ mpc = alloc_mpc();
+ mpc->dev_num = arg;
+ mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */
+ }
+ if (mpc->mpoad_vcc) {
+ printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg);
+ return -EADDRINUSE;
+ }
+
+ if (mpc->dev) { /* check if the lec is LANE2 capable */
+ priv = (struct lec_priv *)mpc->dev->priv;
+ if (priv->lane_version < 2)
+ mpc->dev = NULL;
else
- priv->lane2_ops->associate_indicator = lane2_assoc_ind;
- }
+ priv->lane2_ops->associate_indicator = lane2_assoc_ind;
+ }
- mpc->mpoad_vcc = vcc;
- bind_vcc(vcc, &mpc_dev);
+ mpc->mpoad_vcc = vcc;
+ bind_vcc(vcc, &mpc_dev);
set_bit(ATM_VF_META,&vcc->flags);
set_bit(ATM_VF_READY,&vcc->flags);
- if (mpc->dev) {
- char empty[ATM_ESA_LEN];
- memset(empty, 0, ATM_ESA_LEN);
-
- start_mpc(mpc, mpc->dev);
- /* set address if mpcd e.g. gets killed and restarted.
- * If we do not do it now we have to wait for the next LE_ARP
- */
- if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
- send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
- }
-
- MOD_INC_USE_COUNT;
- return arg;
+ if (mpc->dev) {
+ char empty[ATM_ESA_LEN];
+ memset(empty, 0, ATM_ESA_LEN);
+
+ start_mpc(mpc, mpc->dev);
+ /* set address if mpcd e.g. gets killed and restarted.
+ * If we do not do it now we have to wait for the next LE_ARP
+ */
+ if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 )
+ send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc);
+ }
+
+ MOD_INC_USE_COUNT;
+ return arg;
}
static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc)
{
- struct k_message mesg;
+ struct k_message mesg;
- memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
-
- mesg.type = SET_MPS_CTRL_ADDR;
- memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
- msg_to_mpoad(&mesg, mpc);
+ memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN);
+
+ mesg.type = SET_MPS_CTRL_ADDR;
+ memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN);
+ msg_to_mpoad(&mesg, mpc);
- return;
+ return;
}
static void mpoad_close(struct atm_vcc *vcc)
{
- unsigned long flags;
- struct mpoa_client *mpc;
- struct sk_buff *skb;
-
- mpc = find_mpc_by_vcc(vcc);
- if (mpc == NULL) {
- printk("mpoa: mpoad_close: did not find MPC\n");
- return;
- }
- if (!mpc->mpoad_vcc) {
- printk("mpoa: mpoad_close: close for non-present mpoad\n");
- return;
- }
-
- mpc->mpoad_vcc = NULL;
- if (mpc->dev) {
- struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
- priv->lane2_ops->associate_indicator = NULL;
- stop_mpc(mpc);
- }
-
- /* clear the caches */
- write_lock_irqsave(&mpc->ingress_lock, flags);
- while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
- write_unlock_irqrestore(&mpc->ingress_lock, flags);
-
- write_lock_irqsave(&mpc->egress_lock, flags);
- while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
- write_unlock_irqrestore(&mpc->egress_lock, flags);
+ struct mpoa_client *mpc;
+ struct sk_buff *skb;
+
+ mpc = find_mpc_by_vcc(vcc);
+ if (mpc == NULL) {
+ printk("mpoa: mpoad_close: did not find MPC\n");
+ return;
+ }
+ if (!mpc->mpoad_vcc) {
+ printk("mpoa: mpoad_close: close for non-present mpoad\n");
+ return;
+ }
+
+ mpc->mpoad_vcc = NULL;
+ if (mpc->dev) {
+ struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv;
+ priv->lane2_ops->associate_indicator = NULL;
+ stop_mpc(mpc);
+ }
+
+ mpc->in_ops->destroy_cache(mpc);
+ mpc->eg_ops->destroy_cache(mpc);
while ( (skb = skb_dequeue(&vcc->recvq)) ){
- atm_return(vcc, skb->truesize);
- kfree_skb(skb);
- }
-
- printk("mpoa: (%s) going down\n",
- (mpc->dev) ? mpc->dev->name : "<unknown>");
- MOD_DEC_USE_COUNT;
-
- return;
+ atm_return(vcc, skb->truesize);
+ kfree_skb(skb);
+ }
+
+ printk("mpoa: (%s) going down\n",
+ (mpc->dev) ? mpc->dev->name : "<unknown>");
+ MOD_DEC_USE_COUNT;
+
+ return;
}
/*
*/
static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb)
{
-
- struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
- struct k_message *mesg = (struct k_message*)skb->data;
- atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
-
- if (mpc == NULL) {
- printk("mpoa: msg_from_mpoad: no mpc found\n");
- return 0;
- }
- dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
- switch(mesg->type) {
- case MPOA_RES_REPLY_RCVD:
- dprintk(" mpoa_res_reply_rcvd\n");
- MPOA_res_reply_rcvd(mesg, mpc);
- break;
- case MPOA_TRIGGER_RCVD:
- dprintk(" mpoa_trigger_rcvd\n");
- MPOA_trigger_rcvd(mesg, mpc);
- break;
- case INGRESS_PURGE_RCVD:
- dprintk(" nhrp_purge_rcvd\n");
- ingress_purge_rcvd(mesg, mpc);
- break;
- case EGRESS_PURGE_RCVD:
- dprintk(" egress_purge_reply_rcvd\n");
- egress_purge_rcvd(mesg, mpc);
- break;
- case MPS_DEATH:
- dprintk(" mps_death\n");
- mps_death(mesg, mpc);
- break;
- case CACHE_IMPOS_RCVD:
- dprintk(" cache_impos_rcvd\n");
- MPOA_cache_impos_rcvd(mesg, mpc);
- break;
- case SET_MPC_CTRL_ADDR:
- dprintk(" set_mpc_ctrl_addr\n");
- set_mpc_ctrl_addr_rcvd(mesg, mpc);
- break;
+
+ struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
+ struct k_message *mesg = (struct k_message*)skb->data;
+ atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse);
+
+ if (mpc == NULL) {
+ printk("mpoa: msg_from_mpoad: no mpc found\n");
+ return 0;
+ }
+ dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>");
+ switch(mesg->type) {
+ case MPOA_RES_REPLY_RCVD:
+ dprintk(" mpoa_res_reply_rcvd\n");
+ MPOA_res_reply_rcvd(mesg, mpc);
+ break;
+ case MPOA_TRIGGER_RCVD:
+ dprintk(" mpoa_trigger_rcvd\n");
+ MPOA_trigger_rcvd(mesg, mpc);
+ break;
+ case INGRESS_PURGE_RCVD:
+ dprintk(" nhrp_purge_rcvd\n");
+ ingress_purge_rcvd(mesg, mpc);
+ break;
+ case EGRESS_PURGE_RCVD:
+ dprintk(" egress_purge_reply_rcvd\n");
+ egress_purge_rcvd(mesg, mpc);
+ break;
+ case MPS_DEATH:
+ dprintk(" mps_death\n");
+ mps_death(mesg, mpc);
+ break;
+ case CACHE_IMPOS_RCVD:
+ dprintk(" cache_impos_rcvd\n");
+ MPOA_cache_impos_rcvd(mesg, mpc);
+ break;
+ case SET_MPC_CTRL_ADDR:
+ dprintk(" set_mpc_ctrl_addr\n");
+ set_mpc_ctrl_addr_rcvd(mesg, mpc);
+ break;
case SET_MPS_MAC_ADDR:
- dprintk(" set_mps_mac_addr\n");
+ dprintk(" set_mps_mac_addr\n");
set_mps_mac_addr_rcvd(mesg, mpc);
break;
case CLEAN_UP_AND_EXIT:
- dprintk(" clean_up_and_exit\n");
- clean_up(mesg, mpc, DIE);
- break;
- case RELOAD:
- dprintk(" reload\n");
- clean_up(mesg, mpc, RELOAD);
- break;
- case SET_MPC_PARAMS:
- dprintk(" set_mpc_params\n");
- mpc->parameters = mesg->content.params;
- break;
- default:
- dprintk(" unknown message %d\n", mesg->type);
- break;
- }
- kfree_skb(skb);
-
- return 0;
+ dprintk(" clean_up_and_exit\n");
+ clean_up(mesg, mpc, DIE);
+ break;
+ case RELOAD:
+ dprintk(" reload\n");
+ clean_up(mesg, mpc, RELOAD);
+ break;
+ case SET_MPC_PARAMS:
+ dprintk(" set_mpc_params\n");
+ mpc->parameters = mesg->content.params;
+ break;
+ default:
+ dprintk(" unknown message %d\n", mesg->type);
+ break;
+ }
+ kfree_skb(skb);
+
+ return 0;
}
+/* Remember that this function may not do things that sleep */
int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
{
- struct sk_buff *skb;
-
- if (mpc == NULL || !mpc->mpoad_vcc) {
- printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
- return -ENXIO;
- }
-
- skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
- if (skb == NULL)
- return -ENOMEM;
- skb_put(skb, sizeof(struct k_message));
- memcpy(skb->data, mesg, sizeof(struct k_message));
- atm_force_charge(mpc->mpoad_vcc, skb->truesize);
- skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
- wake_up(&mpc->mpoad_vcc->sleep);
-
- return 0;
+ struct sk_buff *skb;
+
+ if (mpc == NULL || !mpc->mpoad_vcc) {
+ printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
+ return -ENXIO;
+ }
+
+ skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
+ if (skb == NULL)
+ return -ENOMEM;
+ skb_put(skb, sizeof(struct k_message));
+ memcpy(skb->data, mesg, sizeof(struct k_message));
+ atm_force_charge(mpc->mpoad_vcc, skb->truesize);
+ skb_queue_tail(&mpc->mpoad_vcc->recvq, skb);
+ wake_up(&mpc->mpoad_vcc->sleep);
+
+ return 0;
}
static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr)
{
- struct net_device *dev;
- struct mpoa_client *mpc;
- struct lec_priv *priv;
-
- dev = (struct net_device *)dev_ptr;
- if (dev->name == NULL || strncmp(dev->name, "lec", 3))
- return NOTIFY_DONE; /* we are only interested in lec:s */
-
- switch (event) {
- case NETDEV_REGISTER: /* a new lec device was allocated */
- priv = (struct lec_priv *)dev->priv;
- if (priv->lane_version < 2)
- break;
- priv->lane2_ops->associate_indicator = lane2_assoc_ind;
- mpc = find_mpc_by_itfnum(priv->itfnum);
- if (mpc == NULL) {
- dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
- dev->name);
- mpc = alloc_mpc();
- if (mpc == NULL) {
- printk("mpoa: mpoa_event_listener: no new mpc");
- break;
- }
- }
- mpc->dev_num = priv->itfnum;
- mpc->dev = dev;
- dprintk("mpoa: (%s) was initialized\n", dev->name);
- break;
- case NETDEV_UNREGISTER:
- /* the lec device was deallocated */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- dprintk("mpoa: device (%s) was deallocated\n", dev->name);
- stop_mpc(mpc);
- mpc->dev = NULL;
- break;
- case NETDEV_UP:
- /* the dev was ifconfig'ed up */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- if (mpc->mpoad_vcc != NULL) {
- start_mpc(mpc, dev);
- }
- break;
- case NETDEV_DOWN:
- /* the dev was ifconfig'ed down */
- /* this means dev->start == 0 and
- * the flow of packets from the
- * upper layer stops
- */
- mpc = find_mpc_by_lec(dev);
- if (mpc == NULL)
- break;
- if (mpc->mpoad_vcc != NULL) {
- stop_mpc(mpc);
- }
- break;
- case NETDEV_REBOOT:
- case NETDEV_CHANGE:
- case NETDEV_CHANGEMTU:
- case NETDEV_CHANGEADDR:
- case NETDEV_GOING_DOWN:
- break;
- default:
- break;
- }
-
- return NOTIFY_DONE;
+ struct net_device *dev;
+ struct mpoa_client *mpc;
+ struct lec_priv *priv;
+
+ dev = (struct net_device *)dev_ptr;
+ if (dev->name == NULL || strncmp(dev->name, "lec", 3))
+ return NOTIFY_DONE; /* we are only interested in lec:s */
+
+ switch (event) {
+ case NETDEV_REGISTER: /* a new lec device was allocated */
+ priv = (struct lec_priv *)dev->priv;
+ if (priv->lane_version < 2)
+ break;
+ priv->lane2_ops->associate_indicator = lane2_assoc_ind;
+ mpc = find_mpc_by_itfnum(priv->itfnum);
+ if (mpc == NULL) {
+ dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n",
+ dev->name);
+ mpc = alloc_mpc();
+ if (mpc == NULL) {
+ printk("mpoa: mpoa_event_listener: no new mpc");
+ break;
+ }
+ }
+ mpc->dev_num = priv->itfnum;
+ mpc->dev = dev;
+ dprintk("mpoa: (%s) was initialized\n", dev->name);
+ break;
+ case NETDEV_UNREGISTER:
+ /* the lec device was deallocated */
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL)
+ break;
+ dprintk("mpoa: device (%s) was deallocated\n", dev->name);
+ stop_mpc(mpc);
+ mpc->dev = NULL;
+ break;
+ case NETDEV_UP:
+ /* the dev was ifconfig'ed up */
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL)
+ break;
+ if (mpc->mpoad_vcc != NULL) {
+ start_mpc(mpc, dev);
+ }
+ break;
+ case NETDEV_DOWN:
+ /* the dev was ifconfig'ed down */
+ /* this means that the flow of packets from the
+ * upper layer stops
+ */
+ mpc = find_mpc_by_lec(dev);
+ if (mpc == NULL)
+ break;
+ if (mpc->mpoad_vcc != NULL) {
+ stop_mpc(mpc);
+ }
+ break;
+ case NETDEV_REBOOT:
+ case NETDEV_CHANGE:
+ case NETDEV_CHANGEMTU:
+ case NETDEV_CHANGEADDR:
+ case NETDEV_GOING_DOWN:
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
}
/*
*/
-static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client)
+static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- in_cache_entry *entry;
+ uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ in_cache_entry *entry;
- entry = client->in_ops->search(dst_ip, client);
- if( entry == NULL ){
- entry = client->in_ops->new_entry(dst_ip, client);
- entry->entry_state = INGRESS_RESOLVING;
+ entry = mpc->in_ops->get(dst_ip, mpc);
+ if(entry == NULL){
+ entry = mpc->in_ops->add_entry(dst_ip, mpc);
+ entry->entry_state = INGRESS_RESOLVING;
msg->type = SND_MPOA_RES_RQST;
- msg->content.in_info = entry->ctrl_info;
- msg_to_mpoad(msg,client);
+ msg->content.in_info = entry->ctrl_info;
+ msg_to_mpoad(msg, mpc);
do_gettimeofday(&(entry->reply_wait));
+ mpc->in_ops->put(entry);
return;
- }
-
- if( entry->entry_state == INGRESS_INVALID ){
- entry->entry_state = INGRESS_RESOLVING;
+ }
+
+ if(entry->entry_state == INGRESS_INVALID){
+ entry->entry_state = INGRESS_RESOLVING;
msg->type = SND_MPOA_RES_RQST;
- msg->content.in_info = entry->ctrl_info;
- msg_to_mpoad(msg,client);
+ msg->content.in_info = entry->ctrl_info;
+ msg_to_mpoad(msg, mpc);
do_gettimeofday(&(entry->reply_wait));
- return;
- }
-
- printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
- (client->dev) ? client->dev->name : "<unknown>");
+ mpc->in_ops->put(entry);
+ return;
+ }
+
+ printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n",
+ (mpc->dev) ? mpc->dev->name : "<unknown>");
+ mpc->in_ops->put(entry);
return;
}
* Things get complicated because we have to check if there's an egress
* shortcut with suitable traffic parameters we could use.
*/
-static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry){
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
+static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry)
+{
+ uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip);
- eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client);
+ eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client);
+
if(eg_entry && eg_entry->shortcut){
- if(eg_entry->shortcut->qos.txtp.traffic_class &
+ if(eg_entry->shortcut->qos.txtp.traffic_class &
msg->qos.txtp.traffic_class &
(qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){
- if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
- entry->shortcut = eg_entry->shortcut;
+ if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR)
+ entry->shortcut = eg_entry->shortcut;
else if(eg_entry->shortcut->qos.txtp.max_pcr > 0)
- entry->shortcut = eg_entry->shortcut;
+ entry->shortcut = eg_entry->shortcut;
}
if(entry->shortcut){
- dprintk("mpoa: (%s) using egress SVC to reach %d.%d.%d.%d\n",client->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip));
+ client->eg_ops->put(eg_entry);
return;
}
}
+ if (eg_entry != NULL)
+ client->eg_ops->put(eg_entry);
+
/* No luck in the egress cache we must open an ingress SVC */
msg->type = OPEN_INGRESS_SVC;
if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class))
{
- msg->qos = qos->qos;
+ msg->qos = qos->qos;
printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name);
}
else memset(&msg->qos,0,sizeof(struct atm_qos));
return;
}
-static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *client)
+static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
unsigned char *ip;
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- in_cache_entry *entry = client->in_ops->search(dst_ip, client);
+ uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc);
ip = (unsigned char *)&dst_ip;
- dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %d.%d.%d.%d\n", client->dev->name, ip[0], ip[1], ip[2], ip[3]);
- ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", client->dev->name, entry);
- if(entry == NULL){
- printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", client->dev->name);
- return;
- }
- ddprintk(" entry_state = %d ", entry->entry_state);
-
- if (entry->entry_state == INGRESS_RESOLVED) {
- printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", client->dev->name);
- return;
- }
-
- entry->ctrl_info = msg->content.in_info;
- do_gettimeofday(&(entry->tv));
- do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
- entry->refresh_time = 0;
- ddprintk("entry->shortcut = %p\n", entry->shortcut);
+ dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip));
+ ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry);
+ if(entry == NULL){
+ printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name);
+ return;
+ }
+ ddprintk(" entry_state = %d ", entry->entry_state);
+
+ if (entry->entry_state == INGRESS_RESOLVED) {
+ printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name);
+ mpc->in_ops->put(entry);
+ return;
+ }
+
+ entry->ctrl_info = msg->content.in_info;
+ do_gettimeofday(&(entry->tv));
+ do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */
+ entry->refresh_time = 0;
+ ddprintk("entry->shortcut = %p\n", entry->shortcut);
if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){
- entry->entry_state = INGRESS_RESOLVED;
+ entry->entry_state = INGRESS_RESOLVED;
+ mpc->in_ops->put(entry);
return; /* Shortcut already open... */
}
if (entry->shortcut != NULL) {
printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n",
- client->dev->name);
+ mpc->dev->name);
+ mpc->in_ops->put(entry);
return;
}
- check_qos_and_open_shortcut(msg, client, entry);
+ check_qos_and_open_shortcut(msg, mpc, entry);
entry->entry_state = INGRESS_RESOLVED;
+ mpc->in_ops->put(entry);
return;
static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- uint32_t dst_ip = msg->content.in_info.in_dst_ip;
- uint32_t mask = msg->ip_mask;
+ uint32_t dst_ip = msg->content.in_info.in_dst_ip;
+ uint32_t mask = msg->ip_mask;
unsigned char *ip = (unsigned char *)&dst_ip;
+ in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
- in_cache_entry *entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask);
- if( entry == NULL ){
- printk("mpoa: (%s) ingress_purge_rcvd: recieved a purge for an entry that doesn't exist, ", mpc->dev->name);
- printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
- return;
- }
- while(entry != NULL){
- dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
- mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
- mpc->in_ops->cache_remove(entry, mpc);
- entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask);
+ if(entry == NULL){
+ printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name);
+ printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+ return;
}
- return;
+
+ do {
+ dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" ,
+ mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
+ write_lock_bh(&mpc->ingress_lock);
+ mpc->in_ops->remove_entry(entry, mpc);
+ write_unlock_bh(&mpc->ingress_lock);
+ mpc->in_ops->put(entry);
+ entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask);
+ } while (entry != NULL);
+
+ return;
}
static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc)
{
- unsigned long flags;
- uint32_t cache_id = msg->content.eg_info.cache_id;
- eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(cache_id, mpc);
-
- if( entry == NULL ){
- printk("mpoa: (%s) egress_purge_rcvd: received a purge reply for an entry that doesn't exist\n", mpc->dev->name);
- return;
- }
-
- write_lock_irqsave(&mpc->egress_lock, flags);
- mpc->eg_ops->cache_remove(entry, mpc);
- write_unlock_irqrestore(&mpc->egress_lock, flags);
-
- return;
+ uint32_t cache_id = msg->content.eg_info.cache_id;
+ eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc);
+
+ if (entry == NULL) {
+ dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name);
+ return;
+ }
+
+ write_lock_irq(&mpc->egress_lock);
+ mpc->eg_ops->remove_entry(entry, mpc);
+ write_unlock_irq(&mpc->egress_lock);
+
+ mpc->eg_ops->put(entry);
+
+ return;
}
static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
{
- struct k_message *purge_msg;
- struct sk_buff *skb;
-
- dprintk("mpoa: purge_egress_shortcut: entering\n");
- if (vcc == NULL) {
- printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
- return;
- }
-
- skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
- if (skb == NULL) {
- printk("mpoa: purge_egress_shortcut: out of memory\n");
- return;
- }
-
- skb_put(skb, sizeof(struct k_message));
- memset(skb->data, 0, sizeof(struct k_message));
- purge_msg = (struct k_message *)skb->data;
- purge_msg->type = DATA_PLANE_PURGE;
- if (entry != NULL)
- purge_msg->content.eg_info = entry->ctrl_info;
-
- atm_force_charge(vcc, skb->truesize);
- skb_queue_tail(&vcc->recvq, skb);
- wake_up(&vcc->sleep);
- dprintk("mpoa: purge_egress_shortcut: exiting:\n");
-
- return;
+ struct k_message *purge_msg;
+ struct sk_buff *skb;
+
+ dprintk("mpoa: purge_egress_shortcut: entering\n");
+ if (vcc == NULL) {
+ printk("mpoa: purge_egress_shortcut: vcc == NULL\n");
+ return;
+ }
+
+ skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC);
+ if (skb == NULL) {
+ printk("mpoa: purge_egress_shortcut: out of memory\n");
+ return;
+ }
+
+ skb_put(skb, sizeof(struct k_message));
+ memset(skb->data, 0, sizeof(struct k_message));
+ purge_msg = (struct k_message *)skb->data;
+ purge_msg->type = DATA_PLANE_PURGE;
+ if (entry != NULL)
+ purge_msg->content.eg_info = entry->ctrl_info;
+
+ atm_force_charge(vcc, skb->truesize);
+ skb_queue_tail(&vcc->recvq, skb);
+ wake_up(&vcc->sleep);
+ dprintk("mpoa: purge_egress_shortcut: exiting:\n");
+
+ return;
}
/*
*/
static void mps_death( struct k_message * msg, struct mpoa_client * mpc )
{
+ eg_cache_entry *entry;
- unsigned long flags;
- eg_cache_entry *entry;
-
- dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
+ dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name);
- if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
- printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
- return;
- }
-
- entry = mpc->eg_cache;
- while (entry != NULL) {
- purge_egress_shortcut(entry->shortcut, entry);
- entry = entry->next;
- }
+ if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){
+ printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name);
+ return;
+ }
- write_lock_irqsave(&mpc->ingress_lock, flags);
- while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
- write_unlock_irqrestore(&mpc->ingress_lock, flags);
+ /* FIXME: This knows too much of the cache structure */
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while (entry != NULL) {
+ purge_egress_shortcut(entry->shortcut, entry);
+ entry = entry->next;
+ }
+ read_unlock_irq(&mpc->egress_lock);
- write_lock_irqsave(&mpc->egress_lock, flags);
- while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
- write_unlock_irqrestore(&mpc->egress_lock, flags);
+ mpc->in_ops->destroy_cache(mpc);
+ mpc->eg_ops->destroy_cache(mpc);
- return;
+ return;
}
-static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc){
-
- uint16_t holding_time;
- unsigned long flags;
- eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(msg->content.eg_info.cache_id, mpc);
-
- holding_time = msg->content.eg_info.holding_time;
- dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
- mpc->dev->name, entry, holding_time);
- if(entry == NULL && holding_time) {
- mpc->eg_ops->new_entry(msg, mpc);
- return;
- }
- if(holding_time){
- mpc->eg_ops->update(entry, holding_time);
- return;
- }
-
- write_lock_irqsave(&mpc->egress_lock, flags);
- mpc->eg_ops->cache_remove(entry, mpc);
- write_unlock_irqrestore(&mpc->egress_lock, flags);
-
-
- return;
+static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc)
+{
+ uint16_t holding_time;
+ eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc);
+
+ holding_time = msg->content.eg_info.holding_time;
+ dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n",
+ mpc->dev->name, entry, holding_time);
+ if(entry == NULL && holding_time) {
+ entry = mpc->eg_ops->add_entry(msg, mpc);
+ mpc->eg_ops->put(entry);
+ return;
+ }
+ if(holding_time){
+ mpc->eg_ops->update(entry, holding_time);
+ return;
+ }
+
+ write_lock_irq(&mpc->egress_lock);
+ mpc->eg_ops->remove_entry(entry, mpc);
+ write_unlock_irq(&mpc->egress_lock);
+
+ mpc->eg_ops->put(entry);
+
+ return;
}
static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc)
{
- struct lec_priv *priv;
- int i, retval ;
-
- uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
-
- tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */
- tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */
- tlv[5] = 0x02; /* MPOA client */
- tlv[6] = 0x00; /* number of MPS MAC addresses */
-
- memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
- memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
-
- dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
- (mpc->dev) ? mpc->dev->name : "<unknown>");
- for (i = 7; i < sizeof(tlv); i++)
- dprintk("%02x ", tlv[i]);
- dprintk("\n");
-
- if (mpc->dev) {
- priv = (struct lec_priv *)mpc->dev->priv;
- retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
- if (retval == 0)
- printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
- retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
- if (retval < 0)
- printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
- }
-
- return;
+ struct lec_priv *priv;
+ int i, retval ;
+
+ uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN];
+
+ tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */
+ tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */
+ tlv[5] = 0x02; /* MPOA client */
+ tlv[6] = 0x00; /* number of MPS MAC addresses */
+
+ memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */
+ memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN);
+
+ dprintk("mpoa: (%s) setting MPC ctrl ATM address to ",
+ (mpc->dev) ? mpc->dev->name : "<unknown>");
+ for (i = 7; i < sizeof(tlv); i++)
+ dprintk("%02x ", tlv[i]);
+ dprintk("\n");
+
+ if (mpc->dev) {
+ priv = (struct lec_priv *)mpc->dev->priv;
+ retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv));
+ if (retval == 0)
+ printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name);
+ retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL);
+ if (retval < 0)
+ printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name);
+ }
+
+ return;
}
-static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client){
+static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client)
+{
- if(client->number_of_mps_macs)
- kfree(client->mps_macs);
- client->number_of_mps_macs = 0;
+ if(client->number_of_mps_macs)
+ kfree(client->mps_macs);
+ client->number_of_mps_macs = 0;
client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL);
- if (client->mps_macs == NULL) {
- printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
- return;
- }
+ if (client->mps_macs == NULL) {
+ printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n");
+ return;
+ }
client->number_of_mps_macs = 1;
memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN);
/*
* purge egress cache and tell daemon to 'action' (DIE, RELOAD)
*/
-static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action){
+static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action)
+{
- unsigned long flags;
- eg_cache_entry *entry;
+ eg_cache_entry *entry;
msg->type = SND_EGRESS_PURGE;
- read_lock_irqsave(&mpc->egress_lock, flags);
- entry = mpc->eg_cache;
- while(entry != NULL){
- msg->content.eg_info = entry->ctrl_info;
- dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
+ /* FIXME: This knows too much of the cache structure */
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while (entry != NULL){
+ msg->content.eg_info = entry->ctrl_info;
+ dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id);
msg_to_mpoad(msg, mpc);
entry = entry->next;
}
- read_unlock_irqrestore(&mpc->egress_lock, flags);
+ read_unlock_irq(&mpc->egress_lock);
msg->type = action;
msg_to_mpoad(msg, mpc);
static void mpc_timer_refresh()
{
- mpc_timer.expires = jiffies + (MPC_P2 * HZ);
- mpc_timer.data = mpc_timer.expires;
- mpc_timer.function = mpc_cache_check;
- add_timer(&mpc_timer);
-
- return;
+ mpc_timer.expires = jiffies + (MPC_P2 * HZ);
+ mpc_timer.data = mpc_timer.expires;
+ mpc_timer.function = mpc_cache_check;
+ add_timer(&mpc_timer);
+
+ return;
}
static void mpc_cache_check( unsigned long checking_time )
{
- struct mpoa_client *mpc = mpcs;
- static unsigned long previous_resolving_check_time = 0;
- static unsigned long previous_refresh_time = 0;
-
- while( mpc != NULL ){
- mpc->in_ops->clear_count(mpc);
+ struct mpoa_client *mpc = mpcs;
+ static unsigned long previous_resolving_check_time = 0;
+ static unsigned long previous_refresh_time = 0;
+
+ while( mpc != NULL ){
+ mpc->in_ops->clear_count(mpc);
mpc->eg_ops->clear_expired(mpc);
- if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
- mpc->in_ops->check_resolving(mpc);
- previous_resolving_check_time = checking_time;
- }
- if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
- mpc->in_ops->refresh(mpc);
- previous_refresh_time = checking_time;
- }
- mpc = mpc->next;
- }
- mpc_timer_refresh();
-
- return;
+ if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){
+ mpc->in_ops->check_resolving(mpc);
+ previous_resolving_check_time = checking_time;
+ }
+ if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){
+ mpc->in_ops->refresh(mpc);
+ previous_refresh_time = checking_time;
+ }
+ mpc = mpc->next;
+ }
+ mpc_timer_refresh();
+
+ return;
}
void atm_mpoa_init_ops(struct atm_mpoa_ops *ops)
{
- ops->mpoad_attach = atm_mpoa_mpoad_attach;
- ops->vcc_attach = atm_mpoa_vcc_attach;
+ ops->mpoad_attach = atm_mpoa_mpoad_attach;
+ ops->vcc_attach = atm_mpoa_vcc_attach;
#ifdef CONFIG_PROC_FS
if(mpc_proc_init() != 0)
- printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
+ printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n");
else
- printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
+ printk(KERN_INFO "mpoa: /proc/mpoa initialized\n");
#endif
- printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
+ printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n");
- return;
+ return;
}
#ifdef MODULE
int init_module(void)
{
- extern struct atm_mpoa_ops atm_mpoa_ops;
+ extern struct atm_mpoa_ops atm_mpoa_ops;
atm_mpoa_init_ops(&atm_mpoa_ops);
- return 0;
+ return 0;
}
void cleanup_module(void)
{
- extern struct atm_mpoa_ops atm_mpoa_ops;
- struct mpoa_client *mpc, *tmp;
- struct atm_mpoa_qos *qos, *nextqos;
- struct lec_priv *priv;
-
- if (MOD_IN_USE) {
- printk("mpc.c: module in use\n");
- return;
- }
+ extern struct atm_mpoa_ops atm_mpoa_ops;
+ struct mpoa_client *mpc, *tmp;
+ struct atm_mpoa_qos *qos, *nextqos;
+ struct lec_priv *priv;
+
+ if (MOD_IN_USE) {
+ printk("mpc.c: module in use\n");
+ return;
+ }
#ifdef CONFIG_PROC_FS
mpc_proc_clean();
#endif
- del_timer(&mpc_timer);
- unregister_netdevice_notifier(&mpoa_notifier);
- atm_mpoa_ops.mpoad_attach = NULL;
- atm_mpoa_ops.vcc_attach = NULL;
-
- mpc = mpcs;
- mpcs = NULL;
- while (mpc != NULL) {
- tmp = mpc->next;
- if (mpc->dev != NULL) {
- stop_mpc(mpc);
- priv = (struct lec_priv *)mpc->dev->priv;
- if (priv->lane2_ops != NULL)
- priv->lane2_ops->associate_indicator = NULL;
- }
- ddprintk("mpoa: cleanup_module: about to clear caches\n");
- while(mpc->in_ops->cache_remove(mpc->in_cache, mpc));
- while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc));
- ddprintk("mpoa: cleanup_module: caches cleared\n");
- kfree(mpc->mps_macs);
- memset(mpc, 0, sizeof(struct mpoa_client));
- ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
- kfree(mpc);
- ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
- mpc = tmp;
- }
-
- qos = qos_head;
- qos_head = NULL;
- while (qos != NULL) {
- nextqos = qos->next;
- dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
- kfree(qos);
- qos = nextqos;
- }
-
- return;
+ del_timer(&mpc_timer);
+ unregister_netdevice_notifier(&mpoa_notifier);
+ atm_mpoa_ops.mpoad_attach = NULL;
+ atm_mpoa_ops.vcc_attach = NULL;
+
+ mpc = mpcs;
+ mpcs = NULL;
+ while (mpc != NULL) {
+ tmp = mpc->next;
+ if (mpc->dev != NULL) {
+ stop_mpc(mpc);
+ priv = (struct lec_priv *)mpc->dev->priv;
+ if (priv->lane2_ops != NULL)
+ priv->lane2_ops->associate_indicator = NULL;
+ }
+ ddprintk("mpoa: cleanup_module: about to clear caches\n");
+ mpc->in_ops->destroy_cache(mpc);
+ mpc->eg_ops->destroy_cache(mpc);
+ ddprintk("mpoa: cleanup_module: caches cleared\n");
+ kfree(mpc->mps_macs);
+ memset(mpc, 0, sizeof(struct mpoa_client));
+ ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc);
+ kfree(mpc);
+ ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp);
+ mpc = tmp;
+ }
+
+ qos = qos_head;
+ qos_head = NULL;
+ while (qos != NULL) {
+ nextqos = qos->next;
+ dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos);
+ kfree(qos);
+ qos = nextqos;
+ }
+
+ return;
}
#endif /* MODULE */
#define ddprintk(format,args...)
#endif
-static in_cache_entry *in_cache_search(uint32_t dst_ip,
- struct mpoa_client *client)
+static in_cache_entry *in_cache_get(uint32_t dst_ip,
+ struct mpoa_client *client)
{
- unsigned long flags;
- in_cache_entry *entry;
-
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- if( entry->ctrl_info.in_dst_ip == dst_ip ){
- read_unlock_irqrestore(&client->ingress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
-
- return NULL;
+ in_cache_entry *entry;
+
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ if( entry->ctrl_info.in_dst_ip == dst_ip ){
+ atomic_inc(&entry->use);
+ read_unlock_bh(&client->ingress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
+
+ return NULL;
}
-static in_cache_entry *in_cache_search_with_mask(uint32_t dst_ip,
- struct mpoa_client *client,
- uint32_t mask){
- unsigned long flags;
- in_cache_entry *entry;
-
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){
- read_unlock_irqrestore(&client->ingress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
-
- return NULL;
-
+static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip,
+ struct mpoa_client *client,
+ uint32_t mask)
+{
+ in_cache_entry *entry;
+
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){
+ atomic_inc(&entry->use);
+ read_unlock_bh(&client->ingress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
+
+ return NULL;
+
}
-static in_cache_entry *in_cache_search_by_vcc(struct atm_vcc *vcc,
- struct mpoa_client *client )
+static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc,
+ struct mpoa_client *client )
{
- unsigned long flags;
- in_cache_entry *entry;
-
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- if(entry->shortcut == vcc) {
- read_unlock_irqrestore(&client->ingress_lock, flags);
- return entry;
- }
+ in_cache_entry *entry;
+
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ if(entry->shortcut == vcc) {
+ atomic_inc(&entry->use);
+ read_unlock_bh(&client->ingress_lock);
+ return entry;
+ }
entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
+ }
+ read_unlock_bh(&client->ingress_lock);
- return NULL;
+ return NULL;
}
-static in_cache_entry *new_in_cache_entry(uint32_t dst_ip,
+static in_cache_entry *in_cache_add_entry(uint32_t dst_ip,
struct mpoa_client *client)
{
- unsigned long flags;
- unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
- in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
-
- if (entry == NULL) {
- printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
- return NULL;
- }
-
- dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
- memset(entry,0,sizeof(in_cache_entry));
-
- dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
- write_lock_irqsave(&client->ingress_lock, flags);
- entry->next = client->in_cache;
- entry->prev = NULL;
- if (client->in_cache != NULL)
- client->in_cache->prev = entry;
- client->in_cache = entry;
- write_unlock_irqrestore(&client->ingress_lock, flags);
- dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
-
- memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
- entry->ctrl_info.in_dst_ip = dst_ip;
- do_gettimeofday(&(entry->tv));
- entry->retry_time = client->parameters.mpc_p4;
- entry->count = 1;
- entry->entry_state = INGRESS_INVALID;
- entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
+ unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip;
+ in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL);
+
+ if (entry == NULL) {
+ printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n");
+ return NULL;
+ }
+
+ dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]);
+ memset(entry,0,sizeof(in_cache_entry));
+
+ atomic_set(&entry->use, 1);
+ dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n");
+ write_lock_bh(&client->ingress_lock);
+ entry->next = client->in_cache;
+ entry->prev = NULL;
+ if (client->in_cache != NULL)
+ client->in_cache->prev = entry;
+ client->in_cache = entry;
+
+ memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
+ entry->ctrl_info.in_dst_ip = dst_ip;
+ do_gettimeofday(&(entry->tv));
+ entry->retry_time = client->parameters.mpc_p4;
+ entry->count = 1;
+ entry->entry_state = INGRESS_INVALID;
+ entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT;
+ atomic_inc(&entry->use);
+
+ write_unlock_bh(&client->ingress_lock);
+ dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n");
return entry;
}
-static int cache_hit( in_cache_entry * entry, struct mpoa_client *mpc)
+static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc)
{
- struct atm_mpoa_qos *qos;
- struct k_message msg;
+ struct atm_mpoa_qos *qos;
+ struct k_message msg;
- entry->count++;
+ entry->count++;
if(entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL)
- return OPEN;
+ return OPEN;
if(entry->entry_state == INGRESS_REFRESHING){
- if(entry->count > mpc->parameters.mpc_p1){
- msg.type = SND_MPOA_RES_RQST;
+ if(entry->count > mpc->parameters.mpc_p1){
+ msg.type = SND_MPOA_RES_RQST;
msg.content.in_info = entry->ctrl_info;
memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN);
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL) msg.qos = qos->qos;
+ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+ if (qos != NULL) msg.qos = qos->qos;
msg_to_mpoad(&msg, mpc);
do_gettimeofday(&(entry->reply_wait));
entry->entry_state = INGRESS_RESOLVING;
}
if(entry->shortcut != NULL)
- return OPEN;
+ return OPEN;
return CLOSED;
}
- if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
- return OPEN;
+ if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL)
+ return OPEN;
- if( entry->count > mpc->parameters.mpc_p1 &&
- entry->entry_state == INGRESS_INVALID){
- unsigned char *ip __attribute__ ((unused)) =
+ if( entry->count > mpc->parameters.mpc_p1 &&
+ entry->entry_state == INGRESS_INVALID){
+ unsigned char *ip __attribute__ ((unused)) =
(unsigned char *)&entry->ctrl_info.in_dst_ip;
dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]);
- entry->entry_state = INGRESS_RESOLVING;
- msg.type = SND_MPOA_RES_RQST;
- memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
- msg.content.in_info = entry->ctrl_info;
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL) msg.qos = qos->qos;
- msg_to_mpoad( &msg, mpc);
- do_gettimeofday(&(entry->reply_wait));
- }
-
- return CLOSED;
+ entry->entry_state = INGRESS_RESOLVING;
+ msg.type = SND_MPOA_RES_RQST;
+ memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN );
+ msg.content.in_info = entry->ctrl_info;
+ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+ if (qos != NULL) msg.qos = qos->qos;
+ msg_to_mpoad( &msg, mpc);
+ do_gettimeofday(&(entry->reply_wait));
+ }
+
+ return CLOSED;
}
-/*
- * If there are no more references to vcc in egress cache,
- * we are ready to close it.
- */
-static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
+static void in_cache_put(in_cache_entry *entry)
{
- if (vcc == NULL)
- return;
-
- dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc:\n");
- if (mpc->eg_ops->search_by_vcc(vcc, mpc) != NULL)
- return; /* entry still in use */
-
- atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */
- dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc, closed one:\n");
+ if (atomic_dec_and_test(&entry->use)) {
+ memset(entry, 0, sizeof(in_cache_entry));
+ kfree(entry);
+ }
return;
}
/*
* This should be called with write lock on
*/
-static int in_cache_remove( in_cache_entry *entry,
- struct mpoa_client *client )
+static void in_cache_remove_entry(in_cache_entry *entry,
+ struct mpoa_client *client)
{
struct atm_vcc *vcc;
- struct k_message msg;
- unsigned char *ip;
-
- if(entry == NULL)
- return 0;
+ struct k_message msg;
+ unsigned char *ip;
vcc = entry->shortcut;
- ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
- dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
-
- if (entry->prev != NULL)
- entry->prev->next = entry->next;
- else
- client->in_cache = entry->next;
- if (entry->next != NULL)
- entry->next->prev = entry->prev;
- memset(entry, 0, sizeof(in_cache_entry));
- kfree(entry);
+ ip = (unsigned char *)&entry->ctrl_info.in_dst_ip;
+ dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]);
+
+ if (entry->prev != NULL)
+ entry->prev->next = entry->next;
+ else
+ client->in_cache = entry->next;
+ if (entry->next != NULL)
+ entry->next->prev = entry->prev;
+ client->in_ops->put(entry);
if(client->in_cache == NULL && client->eg_cache == NULL){
- msg.type = STOP_KEEP_ALIVE_SM;
+ msg.type = STOP_KEEP_ALIVE_SM;
msg_to_mpoad(&msg,client);
}
- close_unused_egress_vcc(vcc, client);
- return 1;
-}
+ /* Check if the egress side still uses this VCC */
+ if (vcc != NULL) {
+ eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, client);
+ if (eg_entry != NULL) {
+ client->eg_ops->put(eg_entry);
+ return;
+ }
+ atm_async_release_vcc(vcc, -EPIPE);
+ }
+ return;
+}
-/* Call this every MPC-p2 seconds... Not exactly correct solution,
- but an easy one... */
+/* Call this every MPC-p2 seconds... Not exactly correct solution,
+ but an easy one... */
static void clear_count_and_expired(struct mpoa_client *client)
{
- unsigned char *ip;
- unsigned long flags;
- in_cache_entry *entry, *next_entry;
- struct timeval now;
+ unsigned char *ip;
+ in_cache_entry *entry, *next_entry;
+ struct timeval now;
do_gettimeofday(&now);
-
- write_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while(entry != NULL){
- entry->count=0;
- next_entry = entry->next;
- if((now.tv_sec - entry->tv.tv_sec)
- > entry->ctrl_info.holding_time){
- ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
- dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
- in_cache_remove(entry, client);
- }
- entry = next_entry;
- }
- write_unlock_irqrestore(&client->ingress_lock, flags);
-
- return;
-}
-/* Call this every MPC-p4 seconds. */
+ write_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while(entry != NULL){
+ entry->count=0;
+ next_entry = entry->next;
+ if((now.tv_sec - entry->tv.tv_sec)
+ > entry->ctrl_info.holding_time){
+ ip = (unsigned char*)&entry->ctrl_info.in_dst_ip;
+ dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+ client->in_ops->remove_entry(entry, client);
+ }
+ entry = next_entry;
+ }
+ write_unlock_bh(&client->ingress_lock);
+
+ return;
+}
-static void check_resolving_entries( struct mpoa_client * client )
+/* Call this every MPC-p4 seconds. */
+static void check_resolving_entries(struct mpoa_client *client)
{
- struct atm_mpoa_qos *qos;
- unsigned long flags;
- in_cache_entry *entry;
- struct timeval now;
- struct k_message msg;
+ struct atm_mpoa_qos *qos;
+ in_cache_entry *entry;
+ struct timeval now;
+ struct k_message msg;
do_gettimeofday( &now );
- read_lock_irqsave(&client->ingress_lock, flags);
- entry = client->in_cache;
- while( entry != NULL ){
- if(entry->entry_state == INGRESS_RESOLVING){
- if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
- entry = entry->next; /* Entry in hold down */
- continue;
- }
- if( (now.tv_sec - entry->reply_wait.tv_sec) >
- entry->retry_time ){
- entry->retry_time = MPC_C1*( entry->retry_time );
- if(entry->retry_time > client->parameters.mpc_p5){
- /* Retry time maximum exceeded, put entry in hold down. */
- do_gettimeofday(&(entry->hold_down));
- entry->retry_time = client->parameters.mpc_p4;
- entry = entry->next;
- continue;
- }
+ read_lock_bh(&client->ingress_lock);
+ entry = client->in_cache;
+ while( entry != NULL ){
+ if(entry->entry_state == INGRESS_RESOLVING){
+ if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){
+ entry = entry->next; /* Entry in hold down */
+ continue;
+ }
+ if( (now.tv_sec - entry->reply_wait.tv_sec) >
+ entry->retry_time ){
+ entry->retry_time = MPC_C1*( entry->retry_time );
+ if(entry->retry_time > client->parameters.mpc_p5){
+ /* Retry time maximum exceeded, put entry in hold down. */
+ do_gettimeofday(&(entry->hold_down));
+ entry->retry_time = client->parameters.mpc_p4;
+ entry = entry->next;
+ continue;
+ }
/* Ask daemon to send a resolution request. */
- memset(&(entry->hold_down),0,sizeof(struct timeval));
- msg.type = SND_MPOA_RES_RTRY;
- memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
- msg.content.in_info = entry->ctrl_info;
- qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
- if (qos != NULL) msg.qos = qos->qos;
- msg_to_mpoad(&msg, client);
- do_gettimeofday(&(entry->reply_wait));
- }
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
+ memset(&(entry->hold_down),0,sizeof(struct timeval));
+ msg.type = SND_MPOA_RES_RTRY;
+ memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN);
+ msg.content.in_info = entry->ctrl_info;
+ qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip);
+ if (qos != NULL) msg.qos = qos->qos;
+ msg_to_mpoad(&msg, client);
+ do_gettimeofday(&(entry->reply_wait));
+ }
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
}
/* Call this every MPC-p5 seconds. */
-
-static void refresh_entries( struct mpoa_client * client )
+static void refresh_entries(struct mpoa_client *client)
{
- unsigned long flags;
- struct timeval now;
- struct in_cache_entry *entry = client->in_cache;
-
- ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
+ struct timeval now;
+ struct in_cache_entry *entry = client->in_cache;
+
+ ddprintk("mpoa: mpoa_caches.c: refresh_entries\n");
do_gettimeofday(&now);
- read_lock_irqsave(&client->ingress_lock, flags);
- while( entry != NULL ){
- if( entry->entry_state == INGRESS_RESOLVED ){
- if(!(entry->refresh_time))
- entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
+ read_lock_bh(&client->ingress_lock);
+ while( entry != NULL ){
+ if( entry->entry_state == INGRESS_RESOLVED ){
+ if(!(entry->refresh_time))
+ entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3;
if( (now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time ){
- dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
+ dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n");
entry->entry_state = INGRESS_REFRESHING;
-
+
}
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->ingress_lock, flags);
+ }
+ entry = entry->next;
+ }
+ read_unlock_bh(&client->ingress_lock);
}
-static eg_cache_entry *eg_cache_search_by_cache_id(uint32_t cache_id,
- struct mpoa_client *client)
+static void in_destroy_cache(struct mpoa_client *mpc)
{
- eg_cache_entry *entry;
- unsigned long flags;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while(entry != NULL){
- if( entry->ctrl_info.cache_id == cache_id){
- read_unlock_irqrestore(&client->egress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
-
- return NULL;
+ write_lock_irq(&mpc->ingress_lock);
+ while(mpc->in_cache != NULL)
+ mpc->in_ops->remove_entry(mpc->in_cache, mpc);
+ write_unlock_irq(&mpc->ingress_lock);
+
+ return;
}
-static eg_cache_entry *eg_cache_search_by_tag(uint32_t tag,
- struct mpoa_client *client)
+static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc)
{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while(entry != NULL){
- if( entry->ctrl_info.tag == tag){
- read_unlock_irqrestore(&client->egress_lock, flags);
- return entry;
- }
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
-
- return NULL;
+ eg_cache_entry *entry;
+
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while(entry != NULL){
+ if(entry->ctrl_info.cache_id == cache_id){
+ atomic_inc(&entry->use);
+ read_unlock_irq(&mpc->egress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_irq(&mpc->egress_lock);
+
+ return NULL;
}
-static eg_cache_entry *eg_cache_search_by_vcc(struct atm_vcc *vcc,
- struct mpoa_client *client )
+/* This can be called from any context since it saves CPU flags */
+static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc)
{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while( entry != NULL ){
- if( entry->shortcut == vcc ) {
- read_unlock_irqrestore(&client->egress_lock, flags);
- return entry;
+ unsigned long flags;
+ eg_cache_entry *entry;
+
+ read_lock_irqsave(&mpc->egress_lock, flags);
+ entry = mpc->eg_cache;
+ while (entry != NULL){
+ if (entry->ctrl_info.tag == tag) {
+ atomic_inc(&entry->use);
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
+ return entry;
}
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
+ entry = entry->next;
+ }
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
- return NULL;
+ return NULL;
}
-static eg_cache_entry *eg_cache_search_by_src_ip(uint32_t ipaddr,
- struct mpoa_client *client)
+/* This can be called from any context since it saves CPU flags */
+static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
{
- unsigned long flags;
- eg_cache_entry *entry;
-
- read_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while( entry != NULL ){
- if(entry->latest_ip_addr == ipaddr) {
- break;
+ unsigned long flags;
+ eg_cache_entry *entry;
+
+ read_lock_irqsave(&mpc->egress_lock, flags);
+ entry = mpc->eg_cache;
+ while (entry != NULL){
+ if (entry->shortcut == vcc) {
+ atomic_inc(&entry->use);
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
+ return entry;
}
- entry = entry->next;
- }
- read_unlock_irqrestore(&client->egress_lock, flags);
+ entry = entry->next;
+ }
+ read_unlock_irqrestore(&mpc->egress_lock, flags);
- return entry;
+ return NULL;
}
-/*
- * If there are no more references to vcc in ingress cache,
- * we are ready to close it.
- */
-static void close_unused_ingress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc)
+static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc)
{
- if (vcc == NULL)
- return;
+ eg_cache_entry *entry;
+
+ read_lock_irq(&mpc->egress_lock);
+ entry = mpc->eg_cache;
+ while(entry != NULL){
+ if(entry->latest_ip_addr == ipaddr) {
+ atomic_inc(&entry->use);
+ read_unlock_irq(&mpc->egress_lock);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ read_unlock_irq(&mpc->egress_lock);
- dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:\n");
- if (mpc->in_ops->search_by_vcc(vcc, mpc) != NULL)
- return; /* entry still in use */
+ return NULL;
+}
- atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */
- dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:, closed one\n");
+static void eg_cache_put(eg_cache_entry *entry)
+{
+ if (atomic_dec_and_test(&entry->use)) {
+ memset(entry, 0, sizeof(eg_cache_entry));
+ kfree(entry);
+ }
return;
}
+
/*
* This should be called with write lock on
*/
-static int eg_cache_remove(eg_cache_entry *entry,
- struct mpoa_client *client)
+static void eg_cache_remove_entry(eg_cache_entry *entry,
+ struct mpoa_client *client)
{
struct atm_vcc *vcc;
- struct k_message msg;
- if(entry == NULL)
- return 0;
+ struct k_message msg;
vcc = entry->shortcut;
- dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
- if (entry->prev != NULL)
- entry->prev->next = entry->next;
- else
- client->eg_cache = entry->next;
- if (entry->next != NULL)
- entry->next->prev = entry->prev;
- memset(entry, 0, sizeof(eg_cache_entry));
- kfree(entry);
+ dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n");
+ if (entry->prev != NULL)
+ entry->prev->next = entry->next;
+ else
+ client->eg_cache = entry->next;
+ if (entry->next != NULL)
+ entry->next->prev = entry->prev;
+ client->eg_ops->put(entry);
if(client->in_cache == NULL && client->eg_cache == NULL){
- msg.type = STOP_KEEP_ALIVE_SM;
+ msg.type = STOP_KEEP_ALIVE_SM;
msg_to_mpoad(&msg,client);
}
- close_unused_ingress_vcc(vcc, client);
+ /* Check if the ingress side still uses this VCC */
+ if (vcc != NULL) {
+ in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client);
+ if (in_entry != NULL) {
+ client->in_ops->put(in_entry);
+ return;
+ }
+ atm_async_release_vcc(vcc, -EPIPE);
+ }
- return 1;
-}
+ return;
+}
-static eg_cache_entry *new_eg_cache_entry(struct k_message *msg, struct mpoa_client *client)
+static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client)
{
- unsigned long flags;
- unsigned char *ip;
- eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
+ unsigned char *ip;
+ eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL);
- if (entry == NULL) {
- printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
- return NULL;
+ if (entry == NULL) {
+ printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n");
+ return NULL;
}
- ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
- dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %d.%d.%d.%d, this should be our IP\n", ip[0], ip[1], ip[2], ip[3]);
- memset(entry, 0, sizeof(eg_cache_entry));
-
- dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
- write_lock_irqsave(&client->egress_lock, flags);
- entry->next = client->eg_cache;
- entry->prev = NULL;
- if (client->eg_cache != NULL)
- client->eg_cache->prev = entry;
- client->eg_cache = entry;
- write_unlock_irqrestore(&client->egress_lock, flags);
- dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
-
- memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
- entry->ctrl_info = msg->content.eg_info;
- do_gettimeofday(&(entry->tv));
- entry->entry_state = EGRESS_RESOLVED;
- dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
- ip = (unsigned char *)&entry->ctrl_info.mps_ip;
- dprintk("mpoa: mpoa_caches.c: mps_ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
- return entry;
+ ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip;
+ dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip));
+ memset(entry, 0, sizeof(eg_cache_entry));
+
+ atomic_set(&entry->use, 1);
+ dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n");
+ write_lock_irq(&client->egress_lock);
+ entry->next = client->eg_cache;
+ entry->prev = NULL;
+ if (client->eg_cache != NULL)
+ client->eg_cache->prev = entry;
+ client->eg_cache = entry;
+
+ memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN);
+ entry->ctrl_info = msg->content.eg_info;
+ do_gettimeofday(&(entry->tv));
+ entry->entry_state = EGRESS_RESOLVED;
+ dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id));
+ ip = (unsigned char *)&entry->ctrl_info.mps_ip;
+ dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip));
+ atomic_inc(&entry->use);
+
+ write_unlock_irq(&client->egress_lock);
+ dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n");
+
+ return entry;
}
static void update_eg_cache_entry(eg_cache_entry * entry, uint16_t holding_time)
{
- do_gettimeofday(&(entry->tv));
- entry->entry_state = EGRESS_RESOLVED;
- entry->ctrl_info.holding_time = holding_time;
+ do_gettimeofday(&(entry->tv));
+ entry->entry_state = EGRESS_RESOLVED;
+ entry->ctrl_info.holding_time = holding_time;
- return;
+ return;
}
-static void clear_expired(struct mpoa_client *client){
- eg_cache_entry *entry, *next_entry;
- unsigned long flags;
- struct timeval now;
+static void clear_expired(struct mpoa_client *client)
+{
+ eg_cache_entry *entry, *next_entry;
+ struct timeval now;
struct k_message msg;
- do_gettimeofday(&now);
+ do_gettimeofday(&now);
- write_lock_irqsave(&client->egress_lock, flags);
- entry = client->eg_cache;
- while(entry != NULL){
- next_entry = entry->next;
- if((now.tv_sec - entry->tv.tv_sec)
- > entry->ctrl_info.holding_time){
- msg.type = SND_EGRESS_PURGE;
+ write_lock_irq(&client->egress_lock);
+ entry = client->eg_cache;
+ while(entry != NULL){
+ next_entry = entry->next;
+ if((now.tv_sec - entry->tv.tv_sec)
+ > entry->ctrl_info.holding_time){
+ msg.type = SND_EGRESS_PURGE;
msg.content.eg_info = entry->ctrl_info;
- dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
+ dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id));
msg_to_mpoad(&msg, client);
- eg_cache_remove(entry, client);
- }
- entry = next_entry;
- }
- write_unlock_irqrestore(&client->egress_lock, flags);
+ client->eg_ops->remove_entry(entry, client);
+ }
+ entry = next_entry;
+ }
+ write_unlock_irq(&client->egress_lock);
+
+ return;
+}
+
+static void eg_destroy_cache(struct mpoa_client *mpc)
+{
+ write_lock_irq(&mpc->egress_lock);
+ while(mpc->eg_cache != NULL)
+ mpc->eg_ops->remove_entry(mpc->eg_cache, mpc);
+ write_unlock_irq(&mpc->egress_lock);
- return;
+ return;
}
static struct in_cache_ops ingress_ops = {
- new_in_cache_entry, /* new_entry */
- in_cache_search, /* search */
- in_cache_search_with_mask, /* search_with_mask */
- in_cache_search_by_vcc, /* search_by_vcc */
- cache_hit, /* cache_hit */
- in_cache_remove, /* cache_remove */
- clear_count_and_expired, /* clear_count */
- check_resolving_entries, /* check_resolving */
- refresh_entries, /* refresh */
+ in_cache_add_entry, /* add_entry */
+ in_cache_get, /* get */
+ in_cache_get_with_mask, /* get_with_mask */
+ in_cache_get_by_vcc, /* get_by_vcc */
+ in_cache_put, /* put */
+ in_cache_remove_entry, /* remove_entry */
+ cache_hit, /* cache_hit */
+ clear_count_and_expired, /* clear_count */
+ check_resolving_entries, /* check_resolving */
+ refresh_entries, /* refresh */
+ in_destroy_cache /* destroy_cache */
};
static struct eg_cache_ops egress_ops = {
- new_eg_cache_entry, /* new_entry */
- eg_cache_search_by_cache_id, /* search_by_cache_id */
- eg_cache_search_by_tag, /* search_by_tag */
- eg_cache_search_by_vcc, /* search_by_vcc */
- eg_cache_search_by_src_ip, /* search_by_src_ip */
- eg_cache_remove, /* cache_remove */
- update_eg_cache_entry, /* update */
- clear_expired /* clear_expired */
+ eg_cache_add_entry, /* add_entry */
+ eg_cache_get_by_cache_id, /* get_by_cache_id */
+ eg_cache_get_by_tag, /* get_by_tag */
+ eg_cache_get_by_vcc, /* get_by_vcc */
+ eg_cache_get_by_src_ip, /* get_by_src_ip */
+ eg_cache_put, /* put */
+ eg_cache_remove_entry, /* remove_entry */
+ update_eg_cache_entry, /* update */
+ clear_expired, /* clear_expired */
+ eg_destroy_cache /* destroy_cache */
};
void atm_mpoa_init_cache(struct mpoa_client *mpc)
{
- mpc->in_ops = &ingress_ops;
- mpc->eg_ops = &egress_ops;
+ mpc->in_ops = &ingress_ops;
+ mpc->eg_ops = &egress_ops;
- return;
+ return;
}
struct atm_vcc *shortcut;
uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN];
struct in_ctrl_info ctrl_info;
+ atomic_t use;
} in_cache_entry;
struct in_cache_ops{
- in_cache_entry *(*new_entry)(uint32_t dst_ip,
- struct mpoa_client *client);
- in_cache_entry *(*search)(uint32_t dst_ip, struct mpoa_client *client);
- in_cache_entry *(*search_with_mask)(uint32_t dst_ip,
- struct mpoa_client *client,
- uint32_t mask);
- in_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc,
- struct mpoa_client *client);
- int (*cache_hit)(in_cache_entry *entry,
- struct mpoa_client *client);
- int (*cache_remove)(in_cache_entry *delEntry,
- struct mpoa_client *client );
- void (*clear_count)(struct mpoa_client *client);
- void (*check_resolving)(struct mpoa_client *client);
- void (*refresh)(struct mpoa_client *client);
+ in_cache_entry *(*add_entry)(uint32_t dst_ip,
+ struct mpoa_client *client);
+ in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client);
+ in_cache_entry *(*get_with_mask)(uint32_t dst_ip,
+ struct mpoa_client *client,
+ uint32_t mask);
+ in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc,
+ struct mpoa_client *client);
+ void (*put)(in_cache_entry *entry);
+ void (*remove_entry)(in_cache_entry *delEntry,
+ struct mpoa_client *client );
+ int (*cache_hit)(in_cache_entry *entry,
+ struct mpoa_client *client);
+ void (*clear_count)(struct mpoa_client *client);
+ void (*check_resolving)(struct mpoa_client *client);
+ void (*refresh)(struct mpoa_client *client);
+ void (*destroy_cache)(struct mpoa_client *mpc);
};
typedef struct eg_cache_entry{
uint16_t entry_state;
uint32_t latest_ip_addr; /* The src IP address of the last packet */
struct eg_ctrl_info ctrl_info;
+ atomic_t use;
} eg_cache_entry;
struct eg_cache_ops{
- eg_cache_entry *(*new_entry)(struct k_message *msg, struct mpoa_client *client);
- eg_cache_entry *(*search_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
- eg_cache_entry *(*search_by_tag)(uint32_t cache_id, struct mpoa_client *client);
- eg_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
- eg_cache_entry *(*search_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
- int (*cache_remove)(eg_cache_entry *entry, struct mpoa_client *client);
- void (*update)(eg_cache_entry *entry, uint16_t holding_time);
- void (*clear_expired)(struct mpoa_client *client);
+ eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client);
+ eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client);
+ void (*put)(eg_cache_entry *entry);
+ void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client);
+ void (*update)(eg_cache_entry *entry, uint16_t holding_time);
+ void (*clear_expired)(struct mpoa_client *client);
+ void (*destroy_cache)(struct mpoa_client *mpc);
};
DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize);
atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse);
dev_kfree_skb_any(skb);
- wake_up(&vcc->wsleep);
+ wake_up(&vcc->sleep);
}
* Authors:
* Lennert Buytenhek <buytenh@gnu.org>
*
- * $Id: br.c,v 1.41 2000/03/24 01:33:36 davem Exp $
+ * $Id: br.c,v 1.42 2000/04/14 10:10:34 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
br_handle_frame_hook = br_handle_frame;
br_ioctl_hook = br_ioctl_deviceless_stub;
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- write_lock(&lane_bridge_hook_lock);
br_fdb_get_hook = br_fdb_get;
br_fdb_put_hook = br_fdb_put;
- write_unlock(&lane_bridge_hook_lock);
#endif
register_netdevice_notifier(&br_device_notifier);
br_call_ioctl_atomic(__br_clear_ioctl_hook);
net_call_rx_atomic(__br_clear_frame_hook);
#if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
- write_lock(&lane_bridge_hook_lock);
br_fdb_get_hook = NULL;
br_fdb_put_hook = NULL;
- write_unlock(&lane_bridge_hook_lock);
#endif
}
dst_port = ntohs(tcp->dest);
}
- printk("PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu"
+ printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
- ip->protocol,
- (ntohl(ip->saddr)>>24)&0xFF,
- (ntohl(ip->saddr)>>16)&0xFF,
- (ntohl(ip->saddr)>>8)&0xFF,
- (ntohl(ip->saddr))&0xFF,
- src_port,
- (ntohl(ip->daddr)>>24)&0xFF,
- (ntohl(ip->daddr)>>16)&0xFF,
- (ntohl(ip->daddr)>>8)&0xFF,
- (ntohl(ip->daddr))&0xFF,
+ ip->protocol, NIPQUAD(ip->saddr),
+ src_port, NIPQUAD(ip->daddr),
dst_port,
ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
ntohs(ip->frag_off), ip->ttl);
* Authors: Alan Cox <iiitac@pyr.swan.ac.uk>
* Florian La Roche <rzsfl@rz.uni-sb.de>
*
- * Version: $Id: skbuff.c,v 1.71 2000/03/29 11:58:33 davem Exp $
+ * Version: $Id: skbuff.c,v 1.72 2000/04/13 00:55:54 davem Exp $
*
* Fixes:
* Alan Cox : Fixed the worst of the load balancer bugs.
* handler for protocols to use and generic option handler.
*
*
- * Version: $Id: sock.c,v 1.92 2000/04/08 07:21:15 davem Exp $
+ * Version: $Id: sock.c,v 1.93 2000/04/13 03:13:29 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
return -EOPNOTSUPP;
}
-int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int flags,
+int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int len, int flags,
struct scm_cookie *scm)
{
return -EOPNOTSUPP;
#endif
}
-int __init econet_proto_init(struct net_proto *pro)
+int __init econet_proto_init(void)
{
extern void econet_sysctl_register(void);
sock_register(&econet_family_ops);
char hbuffer[HBUFFERLEN];
int i,j,k;
const char hexbuf[] = "0123456789ABCDEF";
- char abuf[16];
size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n");
#endif
size = sprintf(buffer+len,
- "%-17s0x%-10x0x%-10x%s",
- in_ntoa2(*(u32*)n->primary_key, abuf),
+ "%u.%u.%u.%u0x%-10x0x%-10x%s",
+ NIPQUAD(*(u32*)n->primary_key),
hatype,
arp_state_to_flags(n),
hbuffer);
int hatype = dev ? dev->type : 0;
size = sprintf(buffer+len,
- "%-17s0x%-10x0x%-10x%s",
- in_ntoa2(*(u32*)n->key, abuf),
+ "%u.%u.%u.%u0x%-10x0x%-10x%s",
+ NIPQUAD(*(u32*)n->key),
hatype,
ATF_PUBL|ATF_PERM,
"00:00:00:00:00:00");
u32 daddr = key->dst;
u32 saddr = key->src;
-FRprintk("Lookup: %08x <- %08x ", key->dst, key->src);
+FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ",
+ NIPQUAD(key->dst), NIPQUAD(key->src));
read_lock(&fib_rules_lock);
for (r = fib_rules; r; r=r->r_next) {
if (((saddr^r->r_src) & r->r_srcmask) ||
case ICMP_FRAG_NEEDED:
if (ipv4_config.no_pmtu_disc) {
if (net_ratelimit())
- printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n",
+ printk(KERN_INFO "ICMP: %u.%u.%u.%u: fragmentation needed and DF set.\n",
NIPQUAD(iph->daddr));
} else {
unsigned short new_mtu;
break;
case ICMP_SR_FAILED:
if (net_ratelimit())
- printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr));
+ printk(KERN_INFO "ICMP: %u.%u.%u.%u: Source Route Failed.\n", NIPQUAD(iph->daddr));
break;
default:
break;
if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
{
if (net_ratelimit())
- printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n",
+ printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP error to a broadcast.\n",
NIPQUAD(skb->nh.iph->saddr));
return;
}
break;
}
if (!ifa && net_ratelimit()) {
- char b1[16], b2[16];
- printk(KERN_INFO "Wrong address mask %s from %s/%s\n",
- in_ntoa2(mask, b1), in_ntoa2(rt->rt_src, b2), dev->name);
+ printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from %s/%u.%u.%u.%u\n",
+ NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src));
}
}
read_unlock(&in_dev->lock);
*
* The IP fragmentation functionality.
*
- * Version: $Id: ip_fragment.c,v 1.47 2000/02/09 21:11:33 davem Exp $
+ * Version: $Id: ip_fragment.c,v 1.48 2000/04/13 01:05:33 davem Exp $
*
* Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG>
* Alan Cox <Alan.Cox@linux.org>
*/
skb->security = qp->fragments->skb->security;
+#ifdef CONFIG_NETFILTER
+ /* Connection association is same as fragment (if any). */
+ skb->nfct = qp->fragments->skb->nfct;
+ nf_conntrack_get(skb->nfct);
#ifdef CONFIG_NETFILTER_DEBUG
skb->nf_debug = qp->fragments->skb->nf_debug;
+#endif
#endif
/* Done with all fragments. Fixup the new IP header. */
*/
out_oversize:
if (net_ratelimit())
- printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n",
+ printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n",
NIPQUAD(iph->saddr));
/* the skb isn't in a fragment, so fall through to free it */
out_freeskb:
*
* The Internet Protocol (IP) module.
*
- * Version: $Id: ip_input.c,v 1.46 2000/02/22 23:54:26 davem Exp $
+ * Version: $Id: ip_input.c,v 1.47 2000/04/13 01:11:59 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
read_lock(&ip_ra_lock);
for (ra = ip_ra_chain; ra; ra = ra->next) {
struct sock *sk = ra->sk;
- if (sk && sk->num == protocol) {
+
+ /* If socket is bound to an interface, only report
+ * the packet if it came from that interface.
+ */
+ if (sk && sk->num == protocol
+ && ((sk->bound_dev_if == 0)
+ || (sk->bound_dev_if == skb->dev->ifindex))) {
if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) {
skb = ip_defrag(skb);
if (skb == NULL) {
if (in_dev) {
if (!IN_DEV_SOURCE_ROUTE(in_dev)) {
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n",
+ printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n",
NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
in_dev_put(in_dev);
goto drop;
/*
- * $Id: ipconfig.c,v 1.27 2000/02/21 15:51:41 davem Exp $
+ * $Id: ipconfig.c,v 1.29 2000/04/13 01:16:17 davem Exp $
*
* Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
* information to configure own IP address and routes.
#define CONFIG_IP_PNP_DYNAMIC
-static int ic_proto_enabled __initdata = 0 /* Protocols enabled */
+int ic_proto_enabled __initdata = 0 /* Protocols enabled */
#ifdef CONFIG_IP_PNP_BOOTP
| IC_BOOTP
#endif
strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name);
set_sockaddr(sin, ic_myaddr, 0);
if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Unable to set interface address (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
set_sockaddr(sin, ic_netmask, 0);
if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Unable to set interface netmask (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0);
if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) {
- printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
return 0;
set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0);
rm.rt_flags = RTF_UP | RTF_GATEWAY;
if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) {
- printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err);
+ printk(KERN_ERR "IP-Config: Cannot add default route (%u.%u.%u.%u).\n",
+ NIPQUAD(err));
return -1;
}
}
else if (IN_CLASSC(ntohl(ic_myaddr)))
ic_netmask = htonl(IN_CLASSC_NET);
else {
- printk(KERN_ERR "IP-Config: Unable to guess netmask for address %08x\n", ic_myaddr);
+ printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n",
+ NIPQUAD(ic_myaddr));
return -1;
}
- printk("IP-Config: Guessing netmask %s\n", in_ntoa(ic_netmask));
+ printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask));
}
return 0;
if (!ic_got_reply)
return -1;
- printk("IP-Config: Got %s answer from %s, ",
+ printk("IP-Config: Got %s answer from %u.%u.%u.%u, ",
(ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP",
- in_ntoa(ic_servaddr));
- printk("my address is %s\n", in_ntoa(ic_myaddr));
+ NIPQUAD(ic_servaddr));
+ printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr));
return 0;
}
size_t hash, repl_hash;
struct ip_conntrack_expect *expected;
enum ip_conntrack_info ctinfo;
+ unsigned long extra_jiffies;
int i;
if (!invert_tuple(&repl_tuple, tuple, protocol)) {
repl_hash = hash_conntrack(&repl_tuple);
memset(conntrack, 0, sizeof(struct ip_conntrack));
- atomic_set(&conntrack->ct_general.use, 1);
+ atomic_set(&conntrack->ct_general.use, 2);
conntrack->ct_general.destroy = destroy_conntrack;
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
- for(i=0; i < IP_CT_NUMBER; i++)
+ for (i=0; i < IP_CT_NUMBER; i++)
conntrack->infos[i].master = &conntrack->ct_general;
- if (!protocol->new(conntrack, skb->nh.iph, skb->len)) {
+ extra_jiffies = protocol->new(conntrack, skb->nh.iph, skb->len);
+ if (!extra_jiffies) {
kmem_cache_free(ip_conntrack_cachep, conntrack);
return 1;
}
+ conntrack->timeout.data = (unsigned long)conntrack;
+ conntrack->timeout.function = death_by_timeout;
+ conntrack->timeout.expires = jiffies + extra_jiffies;
+ add_timer(&conntrack->timeout);
/* Sew in at head of hash list. */
WRITE_LOCK(&ip_conntrack_lock);
}
static void
-resolve_normal_ct(struct sk_buff *skb)
+resolve_normal_ct(struct sk_buff *skb, int create)
{
struct ip_conntrack_tuple tuple;
struct ip_conntrack_tuple_hash *h;
do {
/* look for tuple match */
h = ip_conntrack_find_get(&tuple, NULL);
- if (!h && init_conntrack(&tuple, proto, skb))
+ if (!h && (!create || init_conntrack(&tuple, proto, skb)))
return;
} while (!h);
}
/* Return conntrack and conntrack_info a given skb */
-struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+static struct ip_conntrack *
+__ip_conntrack_get(struct sk_buff *skb,
+ enum ip_conntrack_info *ctinfo,
+ int create)
{
if (!skb->nfct) {
/* It may be an icmp error... */
if (!icmp_error_track(skb))
- resolve_normal_ct(skb);
+ resolve_normal_ct(skb, create);
}
if (skb->nfct) {
return NULL;
}
+struct ip_conntrack *
+ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+ return __ip_conntrack_get(skb, ctinfo, 0);
+}
+
/* Netfilter hook itself. */
unsigned int ip_conntrack_in(unsigned int hooknum,
struct sk_buff **pskb,
return NF_STOLEN;
}
- ct = ip_conntrack_get(*pskb, &ctinfo);
- if (!ct)
+ ct = __ip_conntrack_get(*pskb, &ctinfo, 1);
+ if (!ct) {
/* Not valid part of a connection */
return NF_ACCEPT;
+ }
proto = find_proto((*pskb)->nh.iph->protocol);
- /* If this is new, this is first time timer will be set */
ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo);
if (ret == -1) {
MOD_DEC_USE_COUNT;
}
-/* Refresh conntrack for this many jiffies: if noone calls this,
- conntrack will vanish with current skb. */
+/* Refresh conntrack for this many jiffies. */
void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
{
+ IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+
WRITE_LOCK(&ip_conntrack_lock);
- /* If this hasn't had a timer before, it's still being set up */
- if (ct->timeout.data == 0) {
- ct->timeout.data = (unsigned long)ct;
- ct->timeout.function = death_by_timeout;
+ /* Need del_timer for race avoidance (may already be dying). */
+ if (del_timer(&ct->timeout)) {
ct->timeout.expires = jiffies + extra_jiffies;
- atomic_inc(&ct->ct_general.use);
add_timer(&ct->timeout);
- } else {
- /* Need del_timer for race avoidance (may already be dying). */
- if (del_timer(&ct->timeout)) {
- ct->timeout.expires = jiffies + extra_jiffies;
- add_timer(&ct->timeout);
- }
}
WRITE_UNLOCK(&ip_conntrack_lock);
}
}
/* Called when a new connection for this protocol found. */
-static int new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
+static unsigned long
+new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
{
- return 1;
+ return GENERIC_TIMEOUT;
}
struct ip_conntrack_protocol ip_conntrack_generic_protocol
}
/* Called when a new connection for this protocol found. */
-static int icmp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
+static unsigned long icmp_new(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len)
{
static u_int8_t valid_new[]
= { [ICMP_ECHO] = 1,
DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
return 0;
}
- return 1;
+ return ICMP_TIMEOUT;
}
struct ip_conntrack_protocol ip_conntrack_protocol_icmp
conntrack->proto.tcp_state = newconntrack;
WRITE_UNLOCK(&tcp_lock);
- /* Refresh: need write lock to write to conntrack. */
ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
return NF_ACCEPT;
}
/* Called when a new connection for this protocol found. */
-static int tcp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
+static unsigned long tcp_new(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len)
{
enum tcp_conntrack newconntrack;
struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
if (newconntrack == TCP_CONNTRACK_MAX) {
DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
return 0;
- } else {
- conntrack->proto.tcp_state = newconntrack;
- ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
}
- return 1;
+
+ conntrack->proto.tcp_state = newconntrack;
+ return tcp_timeouts[conntrack->proto.tcp_state];
}
struct ip_conntrack_protocol ip_conntrack_protocol_tcp
}
/* Called when a new connection for this protocol found. */
-static int udp_new(struct ip_conntrack *conntrack,
- struct iphdr *iph, size_t len)
+static unsigned long udp_new(struct ip_conntrack *conntrack,
+ struct iphdr *iph, size_t len)
{
- return 1;
+ return UDP_TIMEOUT;
}
struct ip_conntrack_protocol ip_conntrack_protocol_udp
interface. We degfragment them at LOCAL_OUT, however,
so we have to refragment them here. */
if ((*pskb)->len > rt->u.dst.pmtu) {
- DEBUGP("ip_conntrack: refragm %p (size %u) to %u (okfn %p)\n",
- *pskb, (*pskb)->len, rt->u.dst.pmtu, okfn);
/* No hook can be after us, so this should be OK. */
ip_fragment(*pskb, okfn);
return NF_STOLEN;
return NF_ACCEPT;
}
+static unsigned int ip_conntrack_local(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
+ if (net_ratelimit())
+ printk("ipt_hook: happy cracking.\n");
+ return NF_ACCEPT;
+ }
+ return ip_conntrack_in(hooknum, pskb, in, out, okfn);
+}
+
/* Connection tracking may drop packets, but never alters them, so
make it the first hook. */
static struct nf_hook_ops ip_conntrack_in_ops
= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
NF_IP_PRI_CONNTRACK };
static struct nf_hook_ops ip_conntrack_local_out_ops
-= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_LOCAL_OUT,
+= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
NF_IP_PRI_CONNTRACK };
/* Refragmenter; last chance. */
static struct nf_hook_ops ip_conntrack_out_ops
const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ return NF_ACCEPT;
+
/* We can hit fragment here; forwarded packets get
defragmented by connection tracking coming in, then
fragmented (grr) by the forward code.
return ip_nat_fn(hooknum, pskb, in, out, okfn);
}
+static unsigned int
+ip_nat_local_fn(unsigned int hooknum,
+ struct sk_buff **pskb,
+ const struct net_device *in,
+ const struct net_device *out,
+ int (*okfn)(struct sk_buff *))
+{
+ /* root is playing with raw sockets. */
+ if ((*pskb)->len < sizeof(struct iphdr)
+ || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+ return NF_ACCEPT;
+
+ return ip_nat_fn(hooknum, pskb, in, out, okfn);
+}
+
/* We must be after connection tracking and before packet filtering. */
/* Before packet filtering, change destination */
= { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC};
/* Before packet filtering, change destination */
static struct nf_hook_ops ip_nat_local_out_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
+= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
/* Protocol registration. */
int ip_nat_protocol_register(struct ip_nat_protocol *proto)
"Peer pid : %d\n"
"Peer died : %d\n"
"Peer copy mode : %d\n"
- "Peer copy range : %d\n"
+ "Peer copy range : %Zu\n"
"Queue length : %d\n"
"Queue max. length : %d\n"
"Queue flushing : %d\n"
#define IP_NF_ASSERT(x) \
do { \
if (!(x)) \
- printk("IPT_ASSERT: %s:%s:%u\n", \
+ printk("IP_NF_ASSERT: %s:%s:%u\n", \
__FUNCTION__, __FILE__, __LINE__); \
} while(0)
#else
target = find_target_lock(t->u.name, &ret, &ipt_mutex);
if (!target) {
duprintf("check_entry: `%s' not found\n", t->u.name);
- up(&ipt_mutex);
return ret;
}
if (target->me)
{
int ret;
+ MOD_INC_USE_COUNT;
ret = down_interruptible(&ipt_mutex);
if (ret != 0)
return ret;
- if (list_named_insert(&ipt_target, target)) {
- MOD_INC_USE_COUNT;
- ret = 0;
- } else {
+ if (!list_named_insert(&ipt_target, target)) {
duprintf("ipt_register_target: `%s' already in list!\n",
target->name);
ret = -EINVAL;
+ MOD_DEC_USE_COUNT;
}
up(&ipt_mutex);
return ret;
{
int ret;
+ MOD_INC_USE_COUNT;
ret = down_interruptible(&ipt_mutex);
- if (ret != 0)
+ if (ret != 0) {
+ MOD_DEC_USE_COUNT;
return ret;
-
+ }
if (list_named_insert(&ipt_match, match)) {
- MOD_INC_USE_COUNT;
ret = 0;
} else {
duprintf("ipt_register_match: `%s' already in list!\n",
match->name);
+ MOD_DEC_USE_COUNT;
ret = -EINVAL;
}
up(&ipt_mutex);
static struct ipt_table_info bootstrap
= { 0, 0, { 0 }, { 0 }, { }, { } };
+ MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ipt_table_info)
+ SMP_ALIGN(table->table->size) * smp_num_cpus);
if (!newinfo) {
ret = -ENOMEM;
+ MOD_DEC_USE_COUNT;
return ret;
}
memcpy(newinfo->entries, table->table->entries, table->table->size);
table->table->underflow);
if (ret != 0) {
vfree(newinfo);
+ MOD_DEC_USE_COUNT;
return ret;
}
ret = down_interruptible(&ipt_mutex);
if (ret != 0) {
vfree(newinfo);
+ MOD_DEC_USE_COUNT;
return ret;
}
table->lock = RW_LOCK_UNLOCKED;
list_prepend(&ipt_tables, table);
- MOD_INC_USE_COUNT;
unlock:
up(&ipt_mutex);
free_unlock:
vfree(newinfo);
+ MOD_DEC_USE_COUNT;
goto unlock;
}
printk("%d ",f->ipfw.fw_redirpt);
}
- printk("%s PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu"
+ printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu"
" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu",
- ifname, ip->protocol,
- (ntohl(ip->saddr)>>24)&0xFF,
- (ntohl(ip->saddr)>>16)&0xFF,
- (ntohl(ip->saddr)>>8)&0xFF,
- (ntohl(ip->saddr))&0xFF,
- src_port,
- (ntohl(ip->daddr)>>24)&0xFF,
- (ntohl(ip->daddr)>>16)&0xFF,
- (ntohl(ip->daddr)>>8)&0xFF,
- (ntohl(ip->daddr))&0xFF,
+ ifname, ip->protocol, NIPQUAD(ip->saddr),
+ src_port, NIPQUAD(ip->daddr),
dst_port,
ntohs(ip->tot_len), ip->tos, ntohs(ip->id),
ntohs(ip->frag_off), ip->ttl);
#define dprintf4(a1,a2,a3,a4)
#endif
-#define print_ip(a) printk("%d.%d.%d.%d",(ntohl(a)>>24)&0xFF,\
- (ntohl(a)>>16)&0xFF,\
- (ntohl(a)>>8)&0xFF,\
- (ntohl(a))&0xFF);
+#define print_ip(a) printk("%u.%u.%u.%u", NIPQUAD(a));
#ifdef DEBUG_IP_FIREWALL
#define dprint_ip(a) print_ip(a)
* TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ",
- (ntohl(iph->saddr)>>24)&0xFF,
- (ntohl(iph->saddr)>>16)&0xFF,
- (ntohl(iph->saddr)>>8)&0xFF,
- (ntohl(iph->saddr))&0xFF,
- (ntohl(iph->daddr)>>24)&0xFF,
- (ntohl(iph->daddr)>>16)&0xFF,
- (ntohl(iph->daddr)>>8)&0xFF,
- (ntohl(iph->daddr))&0xFF);
+ NIPQUAD(iph->saddr), NIPQUAD(iph->daddr));
/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
break;
case ICMP_REDIRECT:
/* Max length: 24 "GATEWAY=255.255.255.255 " */
- printk("GATEWAY=%u.%u.%u.%u ",
- (ntohl(icmph->un.gateway)>>24)&0xFF,
- (ntohl(icmph->un.gateway)>>16)&0xFF,
- (ntohl(icmph->un.gateway)>>8)&0xFF,
- (ntohl(icmph->un.gateway))&0xFF);
+ printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway));
/* Fall through */
case ICMP_DEST_UNREACH:
case ICMP_SOURCE_QUENCH:
#if RT_CACHE_DEBUG >= 2
if (rt->u.rt_next) {
struct rtable * trt;
- printk("rt_cache @%02x: %08x", hash, rt->rt_dst);
+ printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst));
for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next)
- printk(" . %08x", trt->rt_dst);
+ printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
printk("\n");
}
#endif
reject_redirect:
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_INFO "Redirect from %X/%s to %X ignored."
- "Path = %X -> %X, tos %02x\n",
- ntohl(old_gw), dev->name, ntohl(new_gw),
- ntohl(saddr), ntohl(daddr), tos);
+ printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n"
+ " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n",
+ NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
+ NIPQUAD(saddr), NIPQUAD(daddr), tos);
#endif
in_dev_put(in_dev);
}
if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
#if RT_CACHE_DEBUG >= 1
- printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos);
+ printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n",
+ NIPQUAD(rt->rt_dst), rt->key.tos);
#endif
rt_del(hash, rt);
return NULL;
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) &&
rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit())
- printk(KERN_WARNING "host %08x/if%d ignores redirects for %08x to %08x.\n",
- rt->rt_src, rt->rt_iif, rt->rt_dst, rt->rt_gateway);
+ printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for "
+ "%u.%u.%u.%u to %u.%u.%u.%u.\n",
+ NIPQUAD(rt->rt_src), rt->rt_iif,
+ NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
#endif
}
out:
static int ip_rt_bug(struct sk_buff *skb)
{
- printk(KERN_DEBUG "ip_rt_bug: %08x -> %08x, %s\n", skb->nh.iph->saddr,
- skb->nh.iph->daddr, skb->dev ? skb->dev->name : "?");
+ printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n",
+ NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr),
+ skb->dev ? skb->dev->name : "?");
kfree_skb(skb);
return 0;
}
martian_destination:
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
- printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name);
+ printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
#endif
e_inval:
err = -EINVAL;
#ifdef CONFIG_IP_ROUTE_VERBOSE
if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
/*
- * RFC1812 recommenadtion, if source is martian,
+ * RFC1812 recommendation, if source is martian,
* the only hint is MAC header.
*/
- printk(KERN_WARNING "martian source %08x for %08x, dev %s\n", saddr, daddr, dev->name);
+ printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n",
+ NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
if (dev->hard_header_len) {
int i;
unsigned char *p = skb->mac.raw;
- printk(KERN_WARNING "ll header:");
- for (i=0; i<dev->hard_header_len; i++, p++)
- printk(" %02x", *p);
+ printk(KERN_WARNING "ll header: ");
+ for (i=0; i<dev->hard_header_len; i++, p++) {
+ printk("%02x", *p);
+ if(i<(dev->hard_header_len-1))
+ printk(":");
+ }
printk("\n");
}
}
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.167 2000/04/08 07:21:18 davem Exp $
+ * Version: $Id: tcp.c,v 1.168 2000/04/13 01:13:06 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
answ = 0;
else if (sk->urginline || !tp->urg_data ||
before(tp->urg_seq,tp->copied_seq) ||
- !before(tp->urg_seq,tp->rcv_nxt))
+ !before(tp->urg_seq,tp->rcv_nxt)) {
answ = tp->rcv_nxt - tp->copied_seq;
- else
+
+ /* Subtract 1, if FIN is in queue. */
+ if (answ && !skb_queue_empty(&sk->receive_queue))
+ answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin;
+ } else
answ = tp->urg_seq - tp->copied_seq;
release_sock(sk);
break;
peer->v4daddr == saddr) {
if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) {
- NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %08x/%u\n", peer->tcp_ts, req->ts_recent, saddr, ntohs(skb->h.th->source)));
+ NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %u.%u.%u.%u/%u\n", \
+ peer->tcp_ts, req->ts_recent, NIPQUAD(saddr), ntohs(skb->h.th->source)));
NET_INC_STATS_BH(PAWSPassiveRejected);
dst_release(dst);
goto drop_and_free;
* to destinations, already remembered
* to the moment of synflood.
*/
- NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP: drop open request from %08x/%u\n", saddr, ntohs(skb->h.th->source)));
+ NETDEBUG(if (net_ratelimit()) \
+ printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \
+ NIPQUAD(saddr), ntohs(skb->h.th->source)));
TCP_INC_STATS_BH(TcpAttemptFails);
dst_release(dst);
goto drop_and_free;
opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL);
if (opt == NULL) {
- DPRINTK("gred_dump:failed to malloc for %d\n",
+ DPRINTK("gred_dump:failed to malloc for %Zd\n",
sizeof(struct tc_gred_qopt)*MAX_DPs);
goto rtattr_failure;
}
char hostname[32];
int status;
- dprintk("RPC: rpc_getport_external(%s, %d, %d, %d)\n",
- in_ntoa(sin->sin_addr.s_addr), prog, vers, prot);
+ dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n",
+ NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot);
strcpy(hostname, in_ntoa(sin->sin_addr.s_addr));
if (!(pmap_clnt = pmap_create(hostname, sin, prot)))
if (ntohs(sin.sin_port) >= 1024) {
if (net_ratelimit())
printk(KERN_WARNING
- "%s: connect from unprivileged port: %s:%d",
+ "%s: connect from unprivileged port: %u.%u.%u.%u:%d",
serv->sv_name,
- in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
goto failed;
}
- dprintk("%s: connect from %s:%04x\n", serv->sv_name,
- in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port));
+ dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name,
+ NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port));
if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0)))
goto failed;
int error;
int type;
- dprintk("svc: svc_create_socket(%s, %d, %08x:%d)\n",
+ dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n",
serv->sv_program->pg_name, protocol,
- ntohl(sin->sin_addr.s_addr),
+ NIPQUAD(sin->sin_addr.s_addr),
ntohs(sin->sin_port));
if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
* X.25 002 Jonathan Naylor Centralised disconnect handling.
* New timer architecture.
* 2000-11-03 Henner Eisen MSG_EOR handling more POSIX compliant.
+ * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of
+ * facilities negotiation and increased
+ * the throughput upper limit.
*/
#include <linux/config.h>
make->protinfo.x25->source_addr = source_addr;
make->protinfo.x25->neighbour = neigh;
make->protinfo.x25->facilities = facilities;
+ make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask;
x25_write_internal(make, X25_CALL_ACCEPTED);
return -EINVAL;
if (facilities.winsize_in < 1 || facilities.winsize_in > 127)
return -EINVAL;
- if (facilities.throughput < 0x03 || facilities.throughput > 0x2C)
+ if (facilities.throughput < 0x03 || facilities.throughput > 0xDD)
return -EINVAL;
if (facilities.reverse != 0 && facilities.reverse != 1)
return -EINVAL;
*
* History
* X.25 001 Split from x25_subr.c
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
* Parse a set of facilities into the facilities structure. Unrecognised
* facilities are written to the debug log file.
*/
-int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities)
+int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, unsigned long *vc_fac_mask)
{
unsigned int len;
unsigned char *p = skb->data;
len = *p++;
+ *vc_fac_mask = 0;
while (len > 0) {
switch (*p & X25_FAC_CLASS_MASK) {
switch (*p) {
case X25_FAC_REVERSE:
facilities->reverse = (p[1] & 0x01);
+ *vc_fac_mask |= X25_MASK_REVERSE;
break;
case X25_FAC_THROUGHPUT:
facilities->throughput = p[1];
+ *vc_fac_mask |= X25_MASK_THROUGHPUT;
break;
default:
printk(KERN_DEBUG "X.25: unknown facility %02X, value %02X\n", p[0], p[1]);
case X25_FAC_PACKET_SIZE:
facilities->pacsize_in = p[1];
facilities->pacsize_out = p[2];
+ *vc_fac_mask |= X25_MASK_PACKET_SIZE;
break;
case X25_FAC_WINDOW_SIZE:
facilities->winsize_in = p[1];
facilities->winsize_out = p[2];
+ *vc_fac_mask |= X25_MASK_WINDOW_SIZE;
break;
default:
printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]);
/*
* Create a set of facilities.
*/
-int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities)
+int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities, unsigned long facil_mask)
{
unsigned char *p = buffer + 1;
int len;
- if (facilities->reverse != 0) {
+ if (facil_mask == 0) {
+ buffer [0] = 0; /* length of the facilities field in call_req or call_accept packets */
+ len = 1; /* 1 byte for the length field */
+ return len;
+ }
+
+ if ((facilities->reverse != 0) && (facil_mask & X25_MASK_REVERSE)) {
*p++ = X25_FAC_REVERSE;
*p++ = (facilities->reverse) ? 0x01 : 0x00;
}
- if (facilities->throughput != 0) {
+ if ((facilities->throughput != 0) && (facil_mask & X25_MASK_THROUGHPUT)) {
*p++ = X25_FAC_THROUGHPUT;
*p++ = facilities->throughput;
}
- if (facilities->pacsize_in != 0 || facilities->pacsize_out != 0) {
+ if ((facilities->pacsize_in != 0 || facilities->pacsize_out != 0) && (facil_mask & X25_MASK_PACKET_SIZE)) {
*p++ = X25_FAC_PACKET_SIZE;
*p++ = (facilities->pacsize_in == 0) ? facilities->pacsize_out : facilities->pacsize_in;
*p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in : facilities->pacsize_out;
}
- if (facilities->winsize_in != 0 || facilities->winsize_out != 0) {
+ if ((facilities->winsize_in != 0 || facilities->winsize_out != 0) && (facil_mask & X25_MASK_WINDOW_SIZE)) {
*p++ = X25_FAC_WINDOW_SIZE;
*p++ = (facilities->winsize_in == 0) ? facilities->winsize_out : facilities->winsize_in;
*p++ = (facilities->winsize_out == 0) ? facilities->winsize_in : facilities->winsize_out;
*new = *ours;
- len = x25_parse_facilities(skb, &theirs);
+ len = x25_parse_facilities(skb, &theirs, &sk->protinfo.x25->vc_facil_mask);
/*
* They want reverse charging, we won't accept it.
* 2 of the License, or (at your option) any later version.
*
* History
- * X.25 001 Jonathan Naylor Started coding.
- * X.25 002 Jonathan Naylor Centralised disconnection code.
- * New timer architecture.
+ * X.25 001 Jonathan Naylor Started coding.
+ * X.25 002 Jonathan Naylor Centralised disconnection code.
+ * New timer architecture.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
*/
skb_pull(skb, X25_STD_MIN_LEN);
skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr));
- skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities));
+ skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities, &sk->protinfo.x25->vc_facil_mask));
/*
* Copy any Call User Data.
*/
* 2 of the License, or (at your option) any later version.
*
* History
- * X.25 001 Jonathan Naylor Started coding.
- * X.25 002 Jonathan Naylor New timer architecture.
+ * X.25 001 Jonathan Naylor Started coding.
+ * X.25 002 Jonathan Naylor New timer architecture.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
x25_neigh->dev = dev;
x25_neigh->state = X25_LINK_STATE_0;
x25_neigh->extended = 0;
+ x25_neigh->global_facil_mask = (X25_MASK_REVERSE | X25_MASK_THROUGHPUT | X25_MASK_PACKET_SIZE | X25_MASK_WINDOW_SIZE); /* enables negotiation */
x25_neigh->t20 = sysctl_x25_restart_request_timeout;
save_flags(flags); cli();
switch (cmd) {
case SIOCX25GSUBSCRIP:
+ if (copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct)))
+ return -EFAULT;
if ((dev = x25_dev_get(x25_subscr.device)) == NULL)
return -EINVAL;
if ((x25_neigh = x25_get_neigh(dev)) == NULL) {
}
dev_put(dev);
x25_subscr.extended = x25_neigh->extended;
+ x25_subscr.global_facil_mask = x25_neigh->global_facil_mask;
if (copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct)))
return -EFAULT;
break;
if (x25_subscr.extended != 0 && x25_subscr.extended != 1)
return -EINVAL;
x25_neigh->extended = x25_subscr.extended;
+ x25_neigh->global_facil_mask = x25_subscr.global_facil_mask;
break;
default:
* 2 of the License, or (at your option) any later version.
*
* History
- * X.25 001 Jonathan Naylor Started coding.
- * X.25 002 Jonathan Naylor Centralised disconnection processing.
+ * X.25 001 Jonathan Naylor Started coding.
+ * X.25 002 Jonathan Naylor Centralised disconnection processing.
+ * mar/20/00 Daniela Squassoni Disabling/enabling of facilities
+ * negotiation.
*/
#include <linux/config.h>
len = x25_addr_aton(addresses, &sk->protinfo.x25->dest_addr, &sk->protinfo.x25->source_addr);
dptr = skb_put(skb, len);
memcpy(dptr, addresses, len);
- len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities);
+ len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->neighbour->global_facil_mask);
dptr = skb_put(skb, len);
memcpy(dptr, facilities, len);
dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);
dptr = skb_put(skb, 2);
*dptr++ = X25_CALL_ACCEPTED;
*dptr++ = 0x00; /* Address lengths */
- len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities);
+ len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->vc_facil_mask);
dptr = skb_put(skb, len);
memcpy(dptr, facilities, len);
dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength);