From cb75bc5a9d9a433f6b5c8015a0f43c1b4d0fad79 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:28:33 -0500 Subject: [PATCH] Import 2.3.27pre6 --- CREDITS | 4 +- MAINTAINERS | 6 +- arch/alpha/mm/extable.c | 7 +- arch/arm/mm/extable.c | 7 +- arch/i386/mm/extable.c | 7 +- arch/i386/mm/init.c | 21 +- arch/m68k/math-emu/fp_emu.h | 8 +- arch/m68k/mm/extable.c | 7 +- arch/mips/mm/extable.c | 7 +- arch/ppc/amiga/config.c | 1 - arch/ppc/kernel/chrp_setup.c | 26 +- arch/ppc/kernel/entry.S | 2 +- arch/ppc/kernel/pmac_setup.c | 1 - arch/ppc/kernel/process.c | 4 +- arch/ppc/kernel/setup.c | 4 +- arch/ppc/mm/extable.c | 7 +- arch/sh/mm/extable.c | 7 +- arch/sparc/mm/extable.c | 7 +- arch/sparc64/kernel/sys_sparc32.c | 5 +- arch/sparc64/mm/extable.c | 7 +- drivers/block/nbd.c | 2 + drivers/char/Config.in | 3 + drivers/char/Makefile | 8 + drivers/char/cs8420.h | 50 + drivers/char/drm/sigio.c | 1 - drivers/char/ibmmpeg2.h | 94 ++ drivers/char/keyboard.c | 1 - drivers/char/mem.c | 6 + drivers/char/n_hdlc.c | 1 - drivers/char/pms.c | 12 +- drivers/char/saa7121.h | 132 ++ drivers/char/saa7146.h | 117 ++ drivers/char/saa7146reg.h | 283 ++++ drivers/char/stradis.c | 2287 +++++++++++++++++++++++++++++ drivers/char/videodev.c | 3 + drivers/i2o/README | 17 +- drivers/i2o/README.ioctl | 48 +- drivers/i2o/i2o_config.c | 242 +-- drivers/i2o/i2o_core.c | 134 +- drivers/i2o/i2o_lan.c | 653 ++++---- drivers/i2o/i2o_lan.h | 8 +- drivers/i2o/i2o_pci.c | 26 +- drivers/i2o/i2o_proc.c | 2016 ++++++++++++++----------- drivers/i2o/i2o_proc.h | 36 - drivers/i2o/i2o_scsi.c | 2 +- drivers/net/3c507.c | 2 +- drivers/net/Makefile | 1236 +++------------- drivers/net/dmfe.c | 1 + drivers/net/es3210.c | 2 +- drivers/net/ncr885e.c | 1 - drivers/net/pcmcia/ray_cs.c | 4 +- drivers/net/sk_mca.c | 1 - drivers/scsi/Makefile | 6 +- drivers/scsi/hosts.c | 6 +- drivers/scsi/inia100.c | 22 +- drivers/scsi/sd.c | 83 +- drivers/scsi/sd_ioctl.c | 119 -- drivers/usb/Makefile | 34 +- drivers/usb/README.serial | 21 +- drivers/usb/usb-serial.c | 880 ++++++++--- fs/buffer.c | 2 +- fs/exec.c | 8 +- fs/proc/kcore.c | 7 +- fs/proc/procfs_syms.c | 2 + fs/udf/misc.c | 4 +- fs/udf/udfdecl.h | 7 +- include/asm-ppc/div64.h | 10 + include/asm-ppc/fcntl.h | 6 +- include/asm-ppc/processor.h | 4 +- include/linux/highmem.h | 4 +- include/linux/i2o.h | 88 +- include/linux/mm.h | 3 +- include/linux/module.h | 1 - include/linux/nbd.h | 15 +- include/linux/pagemap.h | 2 +- include/linux/swap.h | 4 +- kernel/kmod.c | 49 +- kernel/ksyms.c | 1 - kernel/module.c | 43 +- mm/highmem.c | 4 +- mm/mmap.c | 2 +- mm/page_alloc.c | 362 +++-- mm/vmscan.c | 2 +- 83 files changed, 6251 insertions(+), 3124 deletions(-) create mode 100644 drivers/char/cs8420.h create mode 100644 drivers/char/ibmmpeg2.h create mode 100644 drivers/char/saa7121.h create mode 100644 drivers/char/saa7146.h create mode 100644 drivers/char/saa7146reg.h create mode 100644 drivers/char/stradis.c delete mode 100644 drivers/i2o/i2o_proc.h delete mode 100644 drivers/scsi/sd_ioctl.c create mode 100644 include/asm-ppc/div64.h diff --git a/CREDITS b/CREDITS index 851e85409d34..1ba9d2ae5753 100644 --- a/CREDITS +++ b/CREDITS @@ -508,8 +508,8 @@ S: 4850 Moresnet S: Belgium N: Cort Dougan -E: cort@cs.nmt.edu -W: http://www.cs.nmt.edu/~cort/ +E: cort@ppc.kernel.org +W: http://www.ppc.kernel.org/~cort/ D: PowerPC S: Computer Science Department S: New Mexico Tech diff --git a/MAINTAINERS b/MAINTAINERS index 118d5e64dafe..57c707116bd7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -522,10 +522,10 @@ M: eis@baty.hanse.de L: linux-x25@vger.rutgers.edu S: Maintained -LINUX FOR POWERPC (PREP) +LINUX FOR POWERPC P: Cort Dougan -M: cort@cs.nmt.edu -W: http://linuxppc.cs.nmt.edu/ +M: cort@ppc.kernel.org +W: http://www.ppc.kernel.org/ S: Maintained LINUX FOR POWER MACINTOSH diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index ea1387f791d6..12a1f4803fd1 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c @@ -49,18 +49,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp ; mp = mp->next) { if (!mp->ex_table_start) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr - mp->gp); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/arm/mm/extable.c b/arch/arm/mm/extable.c index c98ba5a9e029..e603b6362041 100644 --- a/arch/arm/mm/extable.c +++ b/arch/arm/mm/extable.c @@ -42,18 +42,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/i386/mm/extable.c b/arch/i386/mm/extable.c index 398a62fa1a73..ba34c0395812 100644 --- a/arch/i386/mm/extable.c +++ b/arch/i386/mm/extable.c @@ -42,18 +42,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index 48b4b83ec06f..099696197020 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -422,11 +422,16 @@ void __init paging_init(void) #ifdef CONFIG_HIGHMEM kmap_init(); /* run after fixmap_init */ #endif -#ifdef CONFIG_HIGHMEM - free_area_init(highend_pfn); -#else - free_area_init(max_low_pfn); -#endif + { + unsigned int zones_size[3]; + + zones_size[0] = virt_to_phys((char *)MAX_DMA_ADDRESS) + >> PAGE_SHIFT; + zones_size[1] = max_low_pfn - zones_size[0]; + zones_size[2] = highend_pfn - zones_size[0] - zones_size[1]; + + free_area_init(zones_size); + } return; } @@ -541,7 +546,7 @@ void __init mem_init(void) totalram_pages += totalhigh_pages; #endif printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n", - (unsigned long) nr_free_pages << (PAGE_SHIFT-10), + (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), max_mapnr << (PAGE_SHIFT-10), codepages << (PAGE_SHIFT-10), reservedpages << (PAGE_SHIFT-10), @@ -587,10 +592,10 @@ void si_meminfo(struct sysinfo *val) { val->totalram = totalram_pages; val->sharedram = 0; - val->freeram = nr_free_pages; + val->freeram = nr_free_pages(); val->bufferram = atomic_read(&buffermem_pages); val->totalhigh = totalhigh_pages; - val->freehigh = nr_free_highpages; + val->freehigh = nr_free_highpages(); val->mem_unit = PAGE_SIZE; return; } diff --git a/arch/m68k/math-emu/fp_emu.h b/arch/m68k/math-emu/fp_emu.h index 9344b939b09c..1a4e16802004 100644 --- a/arch/m68k/math-emu/fp_emu.h +++ b/arch/m68k/math-emu/fp_emu.h @@ -38,10 +38,11 @@ #ifndef _FP_EMU_H #define _FP_EMU_H -#ifndef __ASSEMBLY__ - +#include "../kernel/m68k_defs.h" #include +#ifndef __ASSEMBLY__ + #define IS_INF(a) ((a)->exp == 0x7fff) #define IS_ZERO(a) ((a)->mant.m64 == 0) @@ -114,9 +115,6 @@ extern const struct fp_ext fp_Inf; #else /* __ASSEMBLY__ */ -#include "../kernel/m68k_defs.h" -#include - /* * set, reset or clear a bit in the fp status register */ diff --git a/arch/m68k/mm/extable.c b/arch/m68k/mm/extable.c index 7cd5d5c644da..1f8d9e8c3323 100644 --- a/arch/m68k/mm/extable.c +++ b/arch/m68k/mm/extable.c @@ -42,18 +42,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end-1, addr); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/mips/mm/extable.c b/arch/mips/mm/extable.c index 8a0febc38136..a92fdc482e9f 100644 --- a/arch/mips/mm/extable.c +++ b/arch/mips/mm/extable.c @@ -41,18 +41,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/ppc/amiga/config.c b/arch/ppc/amiga/config.c index c66e2359bf82..29b738eec055 100644 --- a/arch/ppc/amiga/config.c +++ b/arch/ppc/amiga/config.c @@ -32,7 +32,6 @@ void (*mach_kbd_reset_setup) (char *, int) __initdata = 0; #include #include -#include #include #include #include diff --git a/arch/ppc/kernel/chrp_setup.c b/arch/ppc/kernel/chrp_setup.c index e70ba4dcab3a..d0825ce8bddf 100644 --- a/arch/ppc/kernel/chrp_setup.c +++ b/arch/ppc/kernel/chrp_setup.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -576,9 +575,10 @@ void __init ppc_md.calibrate_decr = chrp_calibrate_decr; #ifdef CONFIG_VT -#ifdef CONFIG_MAC_KEYBOAD +#ifdef CONFIG_MAC_KEYBOARD if (adb_driver == NULL) { +#endif /* CONFIG_MAC_KEYBOAD */ ppc_md.kbd_setkeycode = pckbd_setkeycode; ppc_md.kbd_getkeycode = pckbd_getkeycode; ppc_md.kbd_translate = pckbd_translate; @@ -588,7 +588,8 @@ void __init #ifdef CONFIG_MAGIC_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; SYSRQ_KEY = 0x54; -#endif +#endif /* CONFIG_MAGIC_SYSRQ */ +#ifdef CONFIG_MAC_KEYBOARD } else { @@ -601,24 +602,13 @@ void __init #ifdef CONFIG_MAGIC_SYSRQ ppc_md.ppc_kbd_sysrq_xlate = mackbd_sysrq_xlate; SYSRQ_KEY = 0x69; -#endif +#endif /* CONFIG_MAGIC_SYSRQ */ } -#else - ppc_md.kbd_setkeycode = pckbd_setkeycode; - ppc_md.kbd_getkeycode = pckbd_getkeycode; - ppc_md.kbd_translate = pckbd_translate; - ppc_md.kbd_unexpected_up = pckbd_unexpected_up; - ppc_md.kbd_leds = pckbd_leds; - ppc_md.kbd_init_hw = pckbd_init_hw; -#ifdef CONFIG_MAGIC_SYSRQ - ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate; - SYSRQ_KEY = 0x54; -#endif +#endif /* CONFIG_MAC_KEYBOARD */ +#endif /* CONFIG_VT */ if ( rtas_data ) ppc_md.progress = chrp_progress; -#endif -#endif - + #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) ppc_ide_md.insw = chrp_ide_insw; ppc_ide_md.outsw = chrp_ide_outsw; diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index 9c940a0373f2..6133f32cafef 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -411,9 +411,9 @@ enter_rtas: addis r7,r7,-KERNELBASE@h lis r8,rtas_entry@ha lwz r8,rtas_entry@l(r8) - addis r5,r8,-KERNELBASE@h mfmsr r9 stw r9,8(r1) + li r0,0 ori r0,r0,MSR_EE|MSR_SE|MSR_BE andc r0,r9,r0 andi. r9,r9,MSR_ME|MSR_RI diff --git a/arch/ppc/kernel/pmac_setup.c b/arch/ppc/kernel/pmac_setup.c index acfe744ec9b9..f494b04c7e84 100644 --- a/arch/ppc/kernel/pmac_setup.c +++ b/arch/ppc/kernel/pmac_setup.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c index a6592f12817e..adeeefe33d25 100644 --- a/arch/ppc/kernel/process.c +++ b/arch/ppc/kernel/process.c @@ -585,8 +585,8 @@ void __init ll_puts(const char *s) */ extern void scheduling_functions_start_here(void); extern void scheduling_functions_end_here(void); -#define first_sched ((unsigned long) scheduling_functions_start_here) -#define last_sched ((unsigned long) scheduling_functions_end_here) +#define first_sched ((unsigned long) scheduling_functions_start_here) +#define last_sched ((unsigned long) scheduling_functions_end_here) unsigned long get_wchan(struct task_struct *p) { diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index ce9a230ac419..2cf9ee71410a 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -389,12 +389,10 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, if ( have_of ) { -#ifdef CONFIG_MACH_SPECIFIC /* prom_init has already been called from __start */ if (boot_infos) relocate_nodes(); finish_device_tree(); -#endif /* CONFIG_MACH_SPECIFIC */ /* * If we were booted via quik, r3 points to the physical * address of the command-line parameters. @@ -450,7 +448,7 @@ identify_machine(unsigned long r3, unsigned long r4, unsigned long r5, int_control.int_cli = __no_use_cli; int_control.int_save_flags = __no_use_save_flags; int_control.int_restore_flags = __no_use_restore_flags; - + switch (_machine) { case _MACH_Pmac: diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c index dc57bf86845b..afcf705e14a6 100644 --- a/arch/ppc/mm/extable.c +++ b/arch/ppc/mm/extable.c @@ -43,18 +43,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/sh/mm/extable.c b/arch/sh/mm/extable.c index 7c677a970bfe..dc77f57fe243 100644 --- a/arch/sh/mm/extable.c +++ b/arch/sh/mm/extable.c @@ -45,18 +45,13 @@ search_exception_table(unsigned long addr) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1, addr); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c index e66e4c72a003..7fe26ad96edd 100644 --- a/arch/sparc/mm/extable.c +++ b/arch/sparc/mm/extable.c @@ -56,18 +56,13 @@ search_exception_table(unsigned long addr, unsigned long *g2) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end-1, addr, g2); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index c25879850a6e..a1e0f26dd9a6 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -2932,7 +2932,6 @@ put_mod_name(char *buf) free_page((unsigned long)buf); } -/* caller must hold modlist_lock at least in read mode */ static __inline__ struct module *find_module(const char *name) { struct module *mod; @@ -3162,7 +3161,7 @@ asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kerne struct module *mod; int err; - read_lock(&modlist_lock); + lock_kernel(); if (name_user == 0) { /* This finds "kernel_module" which is not exported. */ for(mod = module_list; mod->next != NULL; mod = mod->next) @@ -3212,7 +3211,7 @@ asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kerne break; } out: - read_unlock(&modlist_lock); + unlock_kernel(); return err; } diff --git a/arch/sparc64/mm/extable.c b/arch/sparc64/mm/extable.c index a8d4964df0b3..b2df0e169ac0 100644 --- a/arch/sparc64/mm/extable.c +++ b/arch/sparc64/mm/extable.c @@ -56,18 +56,13 @@ search_exception_table(unsigned long addr, unsigned long *g2) #else /* The kernel is the last "module" -- no need to treat it special. */ struct module *mp; - read_lock(&modlist_lock); for (mp = module_list; mp != NULL; mp = mp->next) { if (mp->ex_table_start == NULL) continue; ret = search_one_table(mp->ex_table_start, mp->ex_table_end-1, addr, g2); - if (ret) { - read_unlock(&modlist_lock); - return ret; - } + if (ret) return ret; } - read_unlock(&modlist_lock); #endif return 0; diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index ab18b55b00a0..7c24449ac014 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -105,6 +106,7 @@ static int nbd_xmit(int send, struct socket *sock, char *buf, int size) do { + sock->sk->allocation = GFP_ATOMIC; iov.iov_base = buf; iov.iov_len = size; msg.msg_name = NULL; diff --git a/drivers/char/Config.in b/drivers/char/Config.in index 540217fa227a..52b4bbd17c65 100644 --- a/drivers/char/Config.in +++ b/drivers/char/Config.in @@ -167,6 +167,9 @@ if [ "$CONFIG_VIDEO_DEV" != "n" ]; then dep_tristate ' SGI Vino Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_VINO $CONFIG_VIDEO_DEV fi fi + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)' CONFIG_VIDEO_STRADIS $CONFIG_VIDEO_DEV + fi dep_tristate ' TerraTec ActiveRadio ISA Standalone' CONFIG_RADIO_TERRATEC $CONFIG_VIDEO_DEV if [ "$CONFIG_RADIO_TERRATEC" = "y" ]; then hex ' Terratec i/o port (normally 0x590)' CONFIG_RADIO_TERRATEC_PORT 590 diff --git a/drivers/char/Makefile b/drivers/char/Makefile index f4a6944f28e3..5b29bcafbe91 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -450,6 +450,14 @@ else endif endif +ifeq ($(CONFIG_VIDEO_STRADIS),y) +O_OBJS += vino.o +else + ifeq ($(CONFIG_VIDEO_STRADIS),m) + M_OBJS += stradis.o + endif +endif + ifeq ($(CONFIG_RADIO_AZTECH),y) O_OBJS += radio-aztech.o else diff --git a/drivers/char/cs8420.h b/drivers/char/cs8420.h new file mode 100644 index 000000000000..2b22f3a38de5 --- /dev/null +++ b/drivers/char/cs8420.h @@ -0,0 +1,50 @@ +/* cs8420.h - cs8420 initializations + Copyright (C) 1999 Nathan Laredo (laredo@gnu.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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ +#ifndef __CS8420_H__ +#define __CS8420_H__ + +/* Initialization Sequence */ + +static __u8 init8420[] = { + 1, 0x01, 2, 0x02, 3, 0x00, 4, 0x46, + 5, 0x24, 6, 0x84, 18, 0x18, 19, 0x13, +}; + +#define INIT8420LEN (sizeof(init8420)/2) + +static __u8 mode8420pro[] = { /* professional output mode */ + 32, 0xa1, 33, 0x00, 34, 0x00, 35, 0x00, + 36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00, + 40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00, + 44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00, + 48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00, + 52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00, +}; +#define MODE8420LEN (sizeof(mode8420pro)/2) + +static __u8 mode8420con[] = { /* consumer output mode */ + 32, 0x20, 33, 0x00, 34, 0x00, 35, 0x48, + 36, 0x00, 37, 0x00, 38, 0x00, 39, 0x00, + 40, 0x00, 41, 0x00, 42, 0x00, 43, 0x00, + 44, 0x00, 45, 0x00, 46, 0x00, 47, 0x00, + 48, 0x00, 49, 0x00, 50, 0x00, 51, 0x00, + 52, 0x00, 53, 0x00, 54, 0x00, 55, 0x00, +}; + +#endif diff --git a/drivers/char/drm/sigio.c b/drivers/char/drm/sigio.c index bb75087df234..30df60f66090 100644 --- a/drivers/char/drm/sigio.c +++ b/drivers/char/drm/sigio.c @@ -35,7 +35,6 @@ # include "xf86.h" # include "xf86drm.h" # include "xf86_OSlib.h" -# include "xf86drm.h" #else # include # include diff --git a/drivers/char/ibmmpeg2.h b/drivers/char/ibmmpeg2.h new file mode 100644 index 000000000000..68e10387c498 --- /dev/null +++ b/drivers/char/ibmmpeg2.h @@ -0,0 +1,94 @@ +/* ibmmpeg2.h - IBM MPEGCD21 definitions */ + +#ifndef __IBM_MPEG2__ +#define __IBM_MPEG2__ + +/* Define all MPEG Decoder registers */ +/* Chip Control and Status */ +#define IBM_MP2_CHIP_CONTROL 0x200*2 +#define IBM_MP2_CHIP_MODE 0x201*2 +/* Timer Control and Status */ +#define IBM_MP2_SYNC_STC2 0x202*2 +#define IBM_MP2_SYNC_STC1 0x203*2 +#define IBM_MP2_SYNC_STC0 0x204*2 +#define IBM_MP2_SYNC_PTS2 0x205*2 +#define IBM_MP2_SYNC_PTS1 0x206*2 +#define IBM_MP2_SYNC_PTS0 0x207*2 +/* Video FIFO Control */ +#define IBM_MP2_FIFO 0x208*2 +#define IBM_MP2_FIFOW 0x100*2 +#define IBM_MP2_FIFO_STAT 0x209*2 +#define IBM_MP2_RB_THRESHOLD 0x22b*2 +/* Command buffer */ +#define IBM_MP2_COMMAND 0x20a*2 +#define IBM_MP2_CMD_DATA 0x20b*2 +#define IBM_MP2_CMD_STAT 0x20c*2 +#define IBM_MP2_CMD_ADDR 0x20d*2 +/* Internal Processor Control and Status */ +#define IBM_MP2_PROC_IADDR 0x20e*2 +#define IBM_MP2_PROC_IDATA 0x20f*2 +#define IBM_MP2_WR_PROT 0x235*2 +/* DRAM Access */ +#define IBM_MP2_DRAM_ADDR 0x210*2 +#define IBM_MP2_DRAM_DATA 0x212*2 +#define IBM_MP2_DRAM_CMD_STAT 0x213*2 +#define IBM_MP2_BLOCK_SIZE 0x23b*2 +#define IBM_MP2_SRC_ADDR 0x23c*2 +/* Onscreen Display */ +#define IBM_MP2_OSD_ADDR 0x214*2 +#define IBM_MP2_OSD_DATA 0x215*2 +#define IBM_MP2_OSD_MODE 0x217*2 +#define IBM_MP2_OSD_LINK_ADDR 0x229*2 +#define IBM_MP2_OSD_SIZE 0x22a*2 +/* Interrupt Control */ +#define IBM_MP2_HOST_INT 0x218*2 +#define IBM_MP2_MASK0 0x219*2 +#define IBM_MP2_HOST_INT1 0x23e*2 +#define IBM_MP2_MASK1 0x23f*2 +/* Audio Control */ +#define IBM_MP2_AUD_IADDR 0x21a*2 +#define IBM_MP2_AUD_IDATA 0x21b*2 +#define IBM_MP2_AUD_FIFO 0x21c*2 +#define IBM_MP2_AUD_FIFOW 0x101*2 +#define IBM_MP2_AUD_CTL 0x21d*2 +#define IBM_MP2_BEEP_CTL 0x21e*2 +#define IBM_MP2_FRNT_ATTEN 0x22d*2 +/* Display Control */ +#define IBM_MP2_DISP_MODE 0x220*2 +#define IBM_MP2_DISP_DLY 0x221*2 +#define IBM_MP2_VBI_CTL 0x222*2 +#define IBM_MP2_DISP_LBOR 0x223*2 +#define IBM_MP2_DISP_TBOR 0x224*2 +/* Polarity Control */ +#define IBM_MP2_INFC_CTL 0x22c*2 + +/* control commands */ +#define IBM_MP2_PLAY 0 +#define IBM_MP2_PAUSE 1 +#define IBM_MP2_SINGLE_FRAME 2 +#define IBM_MP2_FAST_FORWARD 3 +#define IBM_MP2_SLOW_MOTION 4 +#define IBM_MP2_IMED_NORM_PLAY 5 +#define IBM_MP2_RESET_WINDOW 6 +#define IBM_MP2_FREEZE_FRAME 7 +#define IBM_MP2_RESET_VID_RATE 8 +#define IBM_MP2_CONFIG_DECODER 9 +#define IBM_MP2_CHANNEL_SWITCH 10 +#define IBM_MP2_RESET_AUD_RATE 11 +#define IBM_MP2_PRE_OP_CHN_SW 12 +#define IBM_MP2_SET_STILL_MODE 14 + +/* Define Xilinx FPGA Internal Registers */ + +/* general control register 0 */ +#define XILINX_CTL0 0x600 +/* genlock delay resister 1 */ +#define XILINX_GLDELAY 0x602 +/* send 16 bits to CS3310 port */ +#define XILINX_CS3310 0x604 +/* send 16 bits to CS3310 and complete */ +#define XILINX_CS3310_CMPLT 0x60c +/* pulse width modulator control */ +#define XILINX_PWM 0x606 + +#endif diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 991e7b510ec1..995f817eb711 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include diff --git a/drivers/char/mem.c b/drivers/char/mem.c index dd53a44b504c..71fe66f5c268 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c @@ -56,6 +56,9 @@ extern void adbdev_init(void); #ifdef CONFIG_USB extern void usb_init(void); #endif +#ifdef CONFIG_PPDEV +extern int pp_init(void); +#endif static ssize_t do_write_mem(struct file * file, void *p, unsigned long realp, const char * buf, size_t count, loff_t *ppos) @@ -672,6 +675,9 @@ int __init chr_dev_init(void) #endif #ifdef CONFIG_VIDEO_DEV videodev_init(); +#endif +#ifdef CONFIG_PPDEV + pp_init(); #endif return 0; } diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index 0717fa418264..b4f50243e90e 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -105,7 +105,6 @@ #include #include #include -#include /* to get the struct task_struct */ #include /* used in new tty drivers */ #include /* used in new tty drivers */ #include diff --git a/drivers/char/pms.c b/drivers/char/pms.c index c96570b73d2d..1e50880a0713 100644 --- a/drivers/char/pms.c +++ b/drivers/char/pms.c @@ -624,7 +624,7 @@ static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count) { int y; int dw = 2*dev->width; - char *src = (char *)bus_to_virt(mem_base); + u32 src = mem_base; char tmp[dw+32]; /* using a temp buffer is faster than direct */ int cnt = 0; @@ -639,8 +639,14 @@ static int pms_capture(struct pms_device *dev, char *buf, int rgb555, int count) for (y = 0; y < dev->height; y++ ) { - *src = 0; /* synchronisiert neue Zeile */ - memcpy(tmp, src, dw+32); /* discard 16 word */ + isa_writeb(0, src); /* synchronisiert neue Zeile */ + + /* + * This is in truth a fifo, be very careful as if you + * forgot this odd things will occur 8) + */ + + isa_memcpy_fromio(tmp, src, dw+32); /* discard 16 word */ cnt -= dev->height; while (cnt <= 0) { diff --git a/drivers/char/saa7121.h b/drivers/char/saa7121.h new file mode 100644 index 000000000000..74e37d405208 --- /dev/null +++ b/drivers/char/saa7121.h @@ -0,0 +1,132 @@ +/* saa7121.h - saa7121 initializations + Copyright (C) 1999 Nathan Laredo (laredo@gnu.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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ +#ifndef __SAA7121_H__ +#define __SAA7121_H__ + +#define NTSC_BURST_START 0x19 /* 28 */ +#define NTSC_BURST_END 0x1d /* 29 */ +#define NTSC_CHROMA_PHASE 0x67 /* 5a */ +#define NTSC_GAINU 0x76 /* 5b */ +#define NTSC_GAINV 0xa5 /* 5c */ +#define NTSC_BLACK_LEVEL 0x2a /* 5d */ +#define NTSC_BLANKING_LEVEL 0x2e /* 5e */ +#define NTSC_VBI_BLANKING 0x2e /* 5f */ +#define NTSC_DAC_CONTROL 0x11 /* 61 */ +#define NTSC_BURST_AMP 0x3f /* 62 */ +#define NTSC_SUBC3 0x1f /* 63 */ +#define NTSC_SUBC2 0x7c /* 64 */ +#define NTSC_SUBC1 0xf0 /* 65 */ +#define NTSC_SUBC0 0x21 /* 66 */ +#define NTSC_HTRIG 0x72 /* 6c */ +#define NTSC_VTRIG 0x00 /* 6c */ +#define NTSC_MULTI 0x30 /* 6e */ +#define NTSC_CCTTX 0x11 /* 6f */ +#define NTSC_FIRST_ACTIVE 0x12 /* 7a */ +#define NTSC_LAST_ACTIVE 0x02 /* 7b */ +#define NTSC_MSB_VERTICAL 0x40 /* 7c */ + +#define PAL_BURST_START 0x21 /* 28 */ +#define PAL_BURST_END 0x1d /* 29 */ +#define PAL_CHROMA_PHASE 0x3f /* 5a */ +#define PAL_GAINU 0x7d /* 5b */ +#define PAL_GAINV 0xaf /* 5c */ +#define PAL_BLACK_LEVEL 0x23 /* 5d */ +#define PAL_BLANKING_LEVEL 0x35 /* 5e */ +#define PAL_VBI_BLANKING 0x35 /* 5f */ +#define PAL_DAC_CONTROL 0x02 /* 61 */ +#define PAL_BURST_AMP 0x2f /* 62 */ +#define PAL_SUBC3 0xcb /* 63 */ +#define PAL_SUBC2 0x8a /* 64 */ +#define PAL_SUBC1 0x09 /* 65 */ +#define PAL_SUBC0 0x2a /* 66 */ +#define PAL_HTRIG 0x86 /* 6c */ +#define PAL_VTRIG 0x04 /* 6d */ +#define PAL_MULTI 0x20 /* 6e */ +#define PAL_CCTTX 0x15 /* 6f */ +#define PAL_FIRST_ACTIVE 0x16 /* 7a */ +#define PAL_LAST_ACTIVE 0x36 /* 7b */ +#define PAL_MSB_VERTICAL 0x40 /* 7c */ + +/* Initialization Sequence */ + +static __u8 init7121ntsc[] = { + 0x26, 0x0, 0x27, 0x0, + 0x28, NTSC_BURST_START, 0x29, NTSC_BURST_END, + 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, + 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, + 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, + 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, + 0x3a, 0x03, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, + 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, + 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, + 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, + 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, + 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, + 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, + 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, + 0x5a, NTSC_CHROMA_PHASE, 0x5b, NTSC_GAINU, + 0x5c, NTSC_GAINV, 0x5d, NTSC_BLACK_LEVEL, + 0x5e, NTSC_BLANKING_LEVEL, 0x5f, NTSC_VBI_BLANKING, + 0x60, 0x0, 0x61, NTSC_DAC_CONTROL, + 0x62, NTSC_BURST_AMP, 0x63, NTSC_SUBC3, + 0x64, NTSC_SUBC2, 0x65, NTSC_SUBC1, + 0x66, NTSC_SUBC0, 0x67, 0x80, 0x68, 0x80, + 0x69, 0x80, 0x6a, 0x80, 0x6b, 0x29, + 0x6c, NTSC_HTRIG, 0x6d, NTSC_VTRIG, + 0x6e, NTSC_MULTI, 0x6f, NTSC_CCTTX, + 0x70, 0xc9, 0x71, 0x68, 0x72, 0x60, 0x73, 0x0, + 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, + 0x78, 0x0, 0x79, 0x0, 0x7a, NTSC_FIRST_ACTIVE, + 0x7b, NTSC_LAST_ACTIVE, 0x7c, NTSC_MSB_VERTICAL, + 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 +}; +#define INIT7121LEN (sizeof(init7121ntsc)/2) + +static __u8 init7121pal[] = { + 0x26, 0x0, 0x27, 0x0, + 0x28, PAL_BURST_START, 0x29, PAL_BURST_END, + 0x2a, 0x0, 0x2b, 0x0, 0x2c, 0x0, 0x2d, 0x0, + 0x2e, 0x0, 0x2f, 0x0, 0x30, 0x0, 0x31, 0x0, + 0x32, 0x0, 0x33, 0x0, 0x34, 0x0, 0x35, 0x0, + 0x36, 0x0, 0x37, 0x0, 0x38, 0x0, 0x39, 0x0, + 0x3a, 0x03, 0x3b, 0x0, 0x3c, 0x0, 0x3d, 0x0, + 0x3e, 0x0, 0x3f, 0x0, 0x40, 0x0, 0x41, 0x0, + 0x42, 0x0, 0x43, 0x0, 0x44, 0x0, 0x45, 0x0, + 0x46, 0x0, 0x47, 0x0, 0x48, 0x0, 0x49, 0x0, + 0x4a, 0x0, 0x4b, 0x0, 0x4c, 0x0, 0x4d, 0x0, + 0x4e, 0x0, 0x4f, 0x0, 0x50, 0x0, 0x51, 0x0, + 0x52, 0x0, 0x53, 0x0, 0x54, 0x0, 0x55, 0x0, + 0x56, 0x0, 0x57, 0x0, 0x58, 0x0, 0x59, 0x0, + 0x5a, PAL_CHROMA_PHASE, 0x5b, PAL_GAINU, + 0x5c, PAL_GAINV, 0x5d, PAL_BLACK_LEVEL, + 0x5e, PAL_BLANKING_LEVEL, 0x5f, PAL_VBI_BLANKING, + 0x60, 0x0, 0x61, PAL_DAC_CONTROL, + 0x62, PAL_BURST_AMP, 0x63, PAL_SUBC3, + 0x64, PAL_SUBC2, 0x65, PAL_SUBC1, + 0x66, PAL_SUBC0, 0x67, 0x80, 0x68, 0x80, + 0x69, 0x80, 0x6a, 0x80, 0x6b, 0x29, + 0x6c, PAL_HTRIG, 0x6d, PAL_VTRIG, + 0x6e, PAL_MULTI, 0x6f, PAL_CCTTX, + 0x70, 0xc9, 0x71, 0x68, 0x72, 0x60, 0x73, 0x0, + 0x74, 0x0, 0x75, 0x0, 0x76, 0x0, 0x77, 0x0, + 0x78, 0x0, 0x79, 0x0, 0x7a, PAL_FIRST_ACTIVE, + 0x7b, PAL_LAST_ACTIVE, 0x7c, PAL_MSB_VERTICAL, + 0x7d, 0x0, 0x7e, 0x0, 0x7f, 0x0 +}; +#endif diff --git a/drivers/char/saa7146.h b/drivers/char/saa7146.h new file mode 100644 index 000000000000..481308e6c0cb --- /dev/null +++ b/drivers/char/saa7146.h @@ -0,0 +1,117 @@ +/* + saa7146.h - definitions philips saa7146 based cards + Copyright (C) 1999 Nathan Laredo (laredo@gnu.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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SAA7146__ +#define __SAA7146__ + +#define SAA7146_VERSION_CODE 0x000101 + +#include +#include + +#include +#include + +#ifndef O_NONCAP +#define O_NONCAP O_TRUNC +#endif + +#define MAX_GBUFFERS 2 +#define FBUF_SIZE 0x190000 + +#ifdef __KERNEL__ + +struct saa7146_window +{ + int x, y; + ushort width, height; + ushort bpp, bpl; + ushort swidth, sheight; + short cropx, cropy; + ushort cropwidth, cropheight; + unsigned long vidadr; + int color_fmt; + ushort depth; +}; + +/* Per-open data for handling multiple opens on one device */ +struct device_open +{ + int isopen; + int noncapturing; + struct saa7146 *dev; +}; +#define MAX_OPENS 3 + +struct saa7146 +{ + struct video_device video_dev; + struct video_picture picture; + struct video_audio audio_dev; + struct video_info vidinfo; + int user; + int cap; + int capuser; + int irqstate; /* irq routine is state driven */ + int writemode; + int playmode; + unsigned int nr; + unsigned long irq; /* IRQ used by SAA7146 card */ + unsigned short id; + struct i2c_bus i2c; + struct pci_dev *dev; + unsigned char revision; + unsigned char boardcfg[64]; /* 64 bytes of config from eeprom */ + unsigned long saa7146_adr; /* bus address of IO mem from PCI BIOS */ + struct saa7146_window win; + unsigned char *saa7146_mem; /* pointer to mapped IO memory */ + struct device_open open_data[MAX_OPENS]; +#define MAX_MARKS 16 + /* for a/v sync */ + int endmark[MAX_MARKS], endmarkhead, endmarktail; + u32 *dmaRPS1, *pageRPS1, *dmaRPS2, *pageRPS2, *dmavid1, *dmavid2, + *dmavid3, *dmaa1in, *dmaa1out, *dmaa2in, *dmaa2out, + *pagedebi, *pagevid1, *pagevid2, *pagevid3, *pagea1in, + *pagea1out, *pagea2in, *pagea2out; + wait_queue_head_t i2cq, debiq, audq, vidq; + u8 *vidbuf, *audbuf, *osdbuf, *dmadebi; + int audhead, vidhead, osdhead, audtail, vidtail, osdtail; + spinlock_t lock; /* the device lock */ +}; +#endif + +#ifdef _ALPHA_SAA7146 +#define saawrite(dat,adr) writel((dat),(char *) (saa->saa7146_adr+(adr))) +#define saaread(adr) readl(saa->saa7146_adr+(adr)) +#else +#define saawrite(dat,adr) writel((dat), (char *) (saa->saa7146_mem+(adr))) +#define saaread(adr) readl(saa->saa7146_mem+(adr)) +#endif + +#define saaand(dat,adr) saawrite((dat) & saaread(adr), adr) +#define saaor(dat,adr) saawrite((dat) | saaread(adr), adr) +#define saaaor(dat,mask,adr) saawrite((dat) | ((mask) & saaread(adr)), adr) + +/* bitmask of attached hardware found */ +#define SAA7146_UNKNOWN 0x00000000 +#define SAA7146_SAA7111 0x00000001 +#define SAA7146_SAA7121 0x00000002 +#define SAA7146_IBMMPEG 0x00000004 + +#endif diff --git a/drivers/char/saa7146reg.h b/drivers/char/saa7146reg.h new file mode 100644 index 000000000000..6cc910f50a4b --- /dev/null +++ b/drivers/char/saa7146reg.h @@ -0,0 +1,283 @@ +/* + saa7146.h - definitions philips saa7146 based cards + Copyright (C) 1999 Nathan Laredo (laredo@gnu.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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __SAA7146_REG__ +#define __SAA7146_REG__ +#define SAA7146_BASE_ODD1 0x00 +#define SAA7146_BASE_EVEN1 0x04 +#define SAA7146_PROT_ADDR1 0x08 +#define SAA7146_PITCH1 0x0c +#define SAA7146_PAGE1 0x10 +#define SAA7146_NUM_LINE_BYTE1 0x14 +#define SAA7146_BASE_ODD2 0x18 +#define SAA7146_BASE_EVEN2 0x1c +#define SAA7146_PROT_ADDR2 0x20 +#define SAA7146_PITCH2 0x24 +#define SAA7146_PAGE2 0x28 +#define SAA7146_NUM_LINE_BYTE2 0x2c +#define SAA7146_BASE_ODD3 0x30 +#define SAA7146_BASE_EVEN3 0x34 +#define SAA7146_PROT_ADDR3 0x38 +#define SAA7146_PITCH3 0x3c +#define SAA7146_PAGE3 0x40 +#define SAA7146_NUM_LINE_BYTE3 0x44 +#define SAA7146_PCI_BT_V1 0x48 +#define SAA7146_PCI_BT_V2 0x49 +#define SAA7146_PCI_BT_V3 0x4a +#define SAA7146_PCI_BT_DEBI 0x4b +#define SAA7146_PCI_BT_A 0x4c +#define SAA7146_DD1_INIT 0x50 +#define SAA7146_DD1_STREAM_B 0x54 +#define SAA7146_DD1_STREAM_A 0x56 +#define SAA7146_BRS_CTRL 0x58 +#define SAA7146_HPS_CTRL 0x5c +#define SAA7146_HPS_V_SCALE 0x60 +#define SAA7146_HPS_V_GAIN 0x64 +#define SAA7146_HPS_H_PRESCALE 0x68 +#define SAA7146_HPS_H_SCALE 0x6c +#define SAA7146_BCS_CTRL 0x70 +#define SAA7146_CHROMA_KEY_RANGE 0x74 +#define SAA7146_CLIP_FORMAT_CTRL 0x78 +#define SAA7146_DEBI_CONFIG 0x7c +#define SAA7146_DEBI_COMMAND 0x80 +#define SAA7146_DEBI_PAGE 0x84 +#define SAA7146_DEBI_AD 0x88 +#define SAA7146_I2C_TRANSFER 0x8c +#define SAA7146_I2C_STATUS 0x90 +#define SAA7146_BASE_A1_IN 0x94 +#define SAA7146_PROT_A1_IN 0x98 +#define SAA7146_PAGE_A1_IN 0x9C +#define SAA7146_BASE_A1_OUT 0xa0 +#define SAA7146_PROT_A1_OUT 0xa4 +#define SAA7146_PAGE_A1_OUT 0xa8 +#define SAA7146_BASE_A2_IN 0xac +#define SAA7146_PROT_A2_IN 0xb0 +#define SAA7146_PAGE_A2_IN 0xb4 +#define SAA7146_BASE_A2_OUT 0xb8 +#define SAA7146_PROT_A2_OUT 0xbc +#define SAA7146_PAGE_A2_OUT 0xc0 +#define SAA7146_RPS_PAGE0 0xc4 +#define SAA7146_RPS_PAGE1 0xc8 +#define SAA7146_RPS_THRESH0 0xcc +#define SAA7146_RPS_THRESH1 0xd0 +#define SAA7146_RPS_TOV0 0xd4 +#define SAA7146_RPS_TOV1 0xd8 +#define SAA7146_IER 0xdc +#define SAA7146_GPIO_CTRL 0xe0 +#define SAA7146_EC1SSR 0xe4 +#define SAA7146_EC2SSR 0xe8 +#define SAA7146_ECT1R 0xec +#define SAA7146_ECT2R 0xf0 +#define SAA7146_ACON1 0xf4 +#define SAA7146_ACON2 0xf8 +#define SAA7146_MC1 0xfc +#define SAA7146_MC2 0x100 +#define SAA7146_RPS_ADDR0 0x104 +#define SAA7146_RPS_ADDR1 0x108 +#define SAA7146_ISR 0x10c +#define SAA7146_PSR 0x110 +#define SAA7146_SSR 0x114 +#define SAA7146_EC1R 0x118 +#define SAA7146_EC2R 0x11c +#define SAA7146_VDP1 0x120 +#define SAA7146_VDP2 0x124 +#define SAA7146_VDP3 0x128 +#define SAA7146_ADP1 0x12c +#define SAA7146_ADP2 0x130 +#define SAA7146_ADP3 0x134 +#define SAA7146_ADP4 0x138 +#define SAA7146_DDP 0x13c +#define SAA7146_LEVEL_REP 0x140 +#define SAA7146_FB_BUFFER1 0x144 +#define SAA7146_FB_BUFFER2 0x148 +#define SAA7146_A_TIME_SLOT1 0x180 +#define SAA7146_A_TIME_SLOT2 0x1C0 + +/* bitfield defines */ +#define MASK_31 0x80000000 +#define MASK_30 0x40000000 +#define MASK_29 0x20000000 +#define MASK_28 0x10000000 +#define MASK_27 0x08000000 +#define MASK_26 0x04000000 +#define MASK_25 0x02000000 +#define MASK_24 0x01000000 +#define MASK_23 0x00800000 +#define MASK_22 0x00400000 +#define MASK_21 0x00200000 +#define MASK_20 0x00100000 +#define MASK_19 0x00080000 +#define MASK_18 0x00040000 +#define MASK_17 0x00020000 +#define MASK_16 0x00010000 +#define MASK_15 0x00008000 +#define MASK_14 0x00004000 +#define MASK_13 0x00002000 +#define MASK_12 0x00001000 +#define MASK_11 0x00000800 +#define MASK_10 0x00000400 +#define MASK_09 0x00000200 +#define MASK_08 0x00000100 +#define MASK_07 0x00000080 +#define MASK_06 0x00000040 +#define MASK_05 0x00000020 +#define MASK_04 0x00000010 +#define MASK_03 0x00000008 +#define MASK_02 0x00000004 +#define MASK_01 0x00000002 +#define MASK_00 0x00000001 +#define MASK_B0 0x000000ff +#define MASK_B1 0x0000ff00 +#define MASK_B2 0x00ff0000 +#define MASK_B3 0xff000000 +#define MASK_W0 0x0000ffff +#define MASK_W1 0xffff0000 +#define MASK_PA 0xfffffffc +#define MASK_PR 0xfffffffe +#define MASK_ER 0xffffffff +#define MASK_NONE 0x00000000 + +#define SAA7146_PAGE_MAP_EN MASK_11 +/* main control register 1 */ +#define SAA7146_MC1_MRST_N MASK_15 +#define SAA7146_MC1_ERPS1 MASK_13 +#define SAA7146_MC1_ERPS0 MASK_12 +#define SAA7146_MC1_EDP MASK_11 +#define SAA7146_MC1_EVP MASK_10 +#define SAA7146_MC1_EAP MASK_09 +#define SAA7146_MC1_EI2C MASK_08 +#define SAA7146_MC1_TR_E_DEBI MASK_07 +#define SAA7146_MC1_TR_E_1 MASK_06 +#define SAA7146_MC1_TR_E_2 MASK_05 +#define SAA7146_MC1_TR_E_3 MASK_04 +#define SAA7146_MC1_TR_E_A2_OUT MASK_03 +#define SAA7146_MC1_TR_E_A2_IN MASK_02 +#define SAA7146_MC1_TR_E_A1_OUT MASK_01 +#define SAA7146_MC1_TR_E_A1_IN MASK_00 +/* main control register 2 */ +#define SAA7146_MC2_RPS_SIG4 MASK_15 +#define SAA7146_MC2_RPS_SIG3 MASK_14 +#define SAA7146_MC2_RPS_SIG2 MASK_13 +#define SAA7146_MC2_RPS_SIG1 MASK_12 +#define SAA7146_MC2_RPS_SIG0 MASK_11 +#define SAA7146_MC2_UPLD_D1_B MASK_10 +#define SAA7146_MC2_UPLD_D1_A MASK_09 +#define SAA7146_MC2_UPLD_BRS MASK_08 +#define SAA7146_MC2_UPLD_HPS_H MASK_06 +#define SAA7146_MC2_UPLD_HPS_V MASK_05 +#define SAA7146_MC2_UPLD_DMA3 MASK_04 +#define SAA7146_MC2_UPLD_DMA2 MASK_03 +#define SAA7146_MC2_UPLD_DMA1 MASK_02 +#define SAA7146_MC2_UPLD_DEBI MASK_01 +#define SAA7146_MC2_UPLD_I2C MASK_00 +/* Primary Status Register and Interrupt Enable/Status Registers */ +#define SAA7146_PSR_PPEF MASK_31 +#define SAA7146_PSR_PABO MASK_30 +#define SAA7146_PSR_PPED MASK_29 +#define SAA7146_PSR_RPS_I1 MASK_28 +#define SAA7146_PSR_RPS_I0 MASK_27 +#define SAA7146_PSR_RPS_LATE1 MASK_26 +#define SAA7146_PSR_RPS_LATE0 MASK_25 +#define SAA7146_PSR_RPS_E1 MASK_24 +#define SAA7146_PSR_RPS_E0 MASK_23 +#define SAA7146_PSR_RPS_TO1 MASK_22 +#define SAA7146_PSR_RPS_TO0 MASK_21 +#define SAA7146_PSR_UPLD MASK_20 +#define SAA7146_PSR_DEBI_S MASK_19 +#define SAA7146_PSR_DEBI_E MASK_18 +#define SAA7146_PSR_I2C_S MASK_17 +#define SAA7146_PSR_I2C_E MASK_16 +#define SAA7146_PSR_A2_IN MASK_15 +#define SAA7146_PSR_A2_OUT MASK_14 +#define SAA7146_PSR_A1_IN MASK_13 +#define SAA7146_PSR_A1_OUT MASK_12 +#define SAA7146_PSR_AFOU MASK_11 +#define SAA7146_PSR_V_PE MASK_10 +#define SAA7146_PSR_VFOU MASK_09 +#define SAA7146_PSR_FIDA MASK_08 +#define SAA7146_PSR_FIDB MASK_07 +#define SAA7146_PSR_PIN3 MASK_06 +#define SAA7146_PSR_PIN2 MASK_05 +#define SAA7146_PSR_PIN1 MASK_04 +#define SAA7146_PSR_PIN0 MASK_03 +#define SAA7146_PSR_ECS MASK_02 +#define SAA7146_PSR_EC3S MASK_01 +#define SAA7146_PSR_EC0S MASK_00 +/* Secondary Status Register */ +#define SAA7146_SSR_PRQ MASK_31 +#define SAA7146_SSR_PMA MASK_30 +#define SAA7146_SSR_RPS_RE1 MASK_29 +#define SAA7146_SSR_RPS_PE1 MASK_28 +#define SAA7146_SSR_RPS_A1 MASK_27 +#define SAA7146_SSR_RPS_RE0 MASK_26 +#define SAA7146_SSR_RPS_PE0 MASK_25 +#define SAA7146_SSR_RPS_A0 MASK_24 +#define SAA7146_SSR_DEBI_TO MASK_23 +#define SAA7146_SSR_DEBI_EF MASK_22 +#define SAA7146_SSR_I2C_EA MASK_21 +#define SAA7146_SSR_I2C_EW MASK_20 +#define SAA7146_SSR_I2C_ER MASK_19 +#define SAA7146_SSR_I2C_EL MASK_18 +#define SAA7146_SSR_I2C_EF MASK_17 +#define SAA7146_SSR_V3P MASK_16 +#define SAA7146_SSR_V2P MASK_15 +#define SAA7146_SSR_V1P MASK_14 +#define SAA7146_SSR_VF3 MASK_13 +#define SAA7146_SSR_VF2 MASK_12 +#define SAA7146_SSR_VF1 MASK_11 +#define SAA7146_SSR_AF2_IN MASK_10 +#define SAA7146_SSR_AF2_OUT MASK_09 +#define SAA7146_SSR_AF1_IN MASK_08 +#define SAA7146_SSR_AF1_OUT MASK_07 +#define SAA7146_SSR_VGT MASK_05 +#define SAA7146_SSR_LNQG MASK_04 +#define SAA7146_SSR_EC5S MASK_03 +#define SAA7146_SSR_EC4S MASK_02 +#define SAA7146_SSR_EC2S MASK_01 +#define SAA7146_SSR_EC1S MASK_00 +/* I2C status register */ +#define SAA7146_I2C_ABORT MASK_07 +#define SAA7146_I2C_SPERR MASK_06 +#define SAA7146_I2C_APERR MASK_05 +#define SAA7146_I2C_DTERR MASK_04 +#define SAA7146_I2C_DRERR MASK_03 +#define SAA7146_I2C_AL MASK_02 +#define SAA7146_I2C_ERR MASK_01 +#define SAA7146_I2C_BUSY MASK_00 +/* output formats */ +#define SAA7146_YUV422 0 +#define SAA7146_RGB16 0 +#define SAA7146_YUV444 1 +#define SAA7146_RGB24 1 +#define SAA7146_ARGB32 2 +#define SAA7146_YUV411 3 +#define SAA7146_ARGB15 3 +#define SAA7146_YUV2 4 +#define SAA7146_RGAB15 4 +#define SAA7146_Y8 6 +#define SAA7146_YUV8 7 +#define SAA7146_RGB8 7 +#define SAA7146_YUV444p 8 +#define SAA7146_YUV422p 9 +#define SAA7146_YUV420p 10 +#define SAA7146_YUV1620 11 +#define SAA7146_Y1 13 +#define SAA7146_Y2 14 +#define SAA7146_YUV1 15 +#endif diff --git a/drivers/char/stradis.c b/drivers/char/stradis.c new file mode 100644 index 000000000000..d0675a09ce23 --- /dev/null +++ b/drivers/char/stradis.c @@ -0,0 +1,2287 @@ +/* + * stradis.c - stradis 4:2:2 mpeg decoder driver + * + * Stradis 4:2:2 MPEG-2 Decoder Driver + * Copyright (C) 1999 Nathan Laredo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "saa7146.h" +#include "saa7146reg.h" +#include "ibmmpeg2.h" +#include "saa7121.h" +#include "cs8420.h" + +#define DEBUG(x) /* debug driver */ +#undef IDEBUG(x) /* debug irq handler */ +#undef MDEBUG(x) /* debug memory management */ + +#define SAA7146_MAX 6 + +static struct saa7146 saa7146s[SAA7146_MAX]; + +static int saa_num = 0; /* number of SAA7146s in use */ + +#define nDebNormal 0x00480000 +#define nDebNoInc 0x00480000 +#define nDebVideo 0xd0480000 +#define nDebAudio 0xd0400000 +#define nDebDMA 0x02c80000 + +#define oDebNormal 0x13c80000 +#define oDebNoInc 0x13c80000 +#define oDebVideo 0xd1080000 +#define oDebAudio 0xd1080000 +#define oDebDMA 0x03080000 + +#define NewCard (saa->boardcfg[3]) +#define ChipControl (saa->boardcfg[1]) +#define NTSCFirstActive (saa->boardcfg[4]) +#define PALFirstActive (saa->boardcfg[5]) +#define NTSCLastActive (saa->boardcfg[54]) +#define PALLastActive (saa->boardcfg[55]) +#define Have2MB (saa->boardcfg[18] & 0x40) +#define HaveCS8420 (saa->boardcfg[18] & 0x04) +#define IBMMPEGCD20 (saa->boardcfg[18] & 0x20) +#define HaveCS3310 (saa->boardcfg[18] & 0x01) +#define CS3310MaxLvl ((saa->boardcfg[30] << 8) | saa->boardcfg[31]) +#define HaveCS4341 (saa->boardcfg[40] == 2) +#define SDIType (saa->boardcfg[27]) +#define CurrentMode (saa->boardcfg[2]) + +#define debNormal (NewCard ? nDebNormal : oDebNormal) +#define debNoInc (NewCard ? nDebNoInc : oDebNoInc) +#define debVideo (NewCard ? nDebVideo : oDebVideo) +#define debAudio (NewCard ? nDebAudio : oDebAudio) +#define debDMA (NewCard ? nDebDMA : oDebDMA) + +#ifdef DEBUG +int stradis_driver(void) /* for the benefit of ksymoops */ +{ + return 1; +} +#endif + +#ifdef USE_RESCUE_EEPROM_SDM275 +static unsigned char rescue_eeprom[64] = { +0x00,0x01,0x04,0x13,0x26,0x0f,0x10,0x00,0x00,0x00,0x43,0x63,0x22,0x01,0x29,0x15,0x73,0x00,0x1f, 'd', 'e', 'c', 'x', 'l', 'd', 'v', 'a',0x02,0x00,0x01,0x00,0xcc,0xa4,0x63,0x09,0xe2,0x10,0x00,0x0a,0x00,0x02,0x02, 'd', 'e', 'c', 'x', 'l', 'a',0x00,0x00,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +#endif + +/* ----------------------------------------------------------------------- */ +/* Hardware I2C functions */ +static void I2CWipe(struct saa7146 *saa) +{ + int i; + /* set i2c to ~=100kHz, abort transfer, clear busy */ + saawrite(0x600 | SAA7146_I2C_ABORT, SAA7146_I2C_STATUS); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + saawrite(0x600, SAA7146_I2C_STATUS); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + saawrite(0x600, SAA7146_I2C_STATUS); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); +} +/* read I2C */ +static int I2CRead(struct i2c_bus *bus, unsigned char addr, + unsigned char subaddr, int dosub) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + + + if (saaread(SAA7146_I2C_STATUS) & 0x3c) + I2CWipe(saa); + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) + schedule(); + if (i == 1000) + I2CWipe(saa); + if (dosub) + saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 8) | + ((subaddr & 0xff) << 16) | 0xed, SAA7146_I2C_TRANSFER); + else + saawrite(((addr & 0xfe) << 24) | (((addr | 1) & 0xff) << 16) | + 0xf1, SAA7146_I2C_TRANSFER); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + /* wait for valid data */ + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) + schedule(); + if (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_ERR) + return -1; + if (i == 1000) + printk("i2c setup read timeout\n"); + saawrite(0x41, SAA7146_I2C_TRANSFER); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | + SAA7146_MC2_UPLD_I2C, SAA7146_MC2); + /* wait for i2c registers to be programmed */ + for (i = 0; i < 1000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_I2C); i++) + schedule(); + /* wait for valid data */ + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_BUSY); i++) + schedule(); + if (saaread(SAA7146_I2C_TRANSFER) & SAA7146_I2C_ERR) + return -1; + if (i == 1000) + printk("i2c read timeout\n"); + return ((saaread(SAA7146_I2C_TRANSFER) >> 24) & 0xff); +} +static int I2CReadOld(struct i2c_bus *bus, unsigned char addr) +{ + return I2CRead(bus, addr, 0, 0); +} + +/* set both to write both bytes, reset it to write only b1 */ + +static int I2CWrite(struct i2c_bus *bus, unsigned char addr, unsigned char b1, + unsigned char b2, int both) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + u32 data; + + if (saaread(SAA7146_I2C_STATUS) & 0x3c) + I2CWipe(saa); + for (i = 0; i < 1000 && + (saaread(SAA7146_I2C_STATUS) & SAA7146_I2C_BUSY); i++) + schedule(); + if (i == 1000) + I2CWipe(saa); + data = ((addr & 0xfe) << 24) | ((b1 & 0xff) << 16); + if (both) + data |= ((b2 & 0xff) << 8) | 0xe5; + else + data |= 0xd1; + saawrite(data, SAA7146_I2C_TRANSFER); + saawrite((SAA7146_MC2_UPLD_I2C << 16) | SAA7146_MC2_UPLD_I2C, + SAA7146_MC2); + return 0; +} + +static void attach_inform(struct i2c_bus *bus, int id) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + + DEBUG(printk(KERN_DEBUG "stradis%d: i2c: device found=%02x\n", saa->nr, id)); + if (id == 0xa0) { /* we have rev2 or later board, fill in info */ + for (i = 0; i < 64; i++) + saa->boardcfg[i] = I2CRead(bus, 0xa0, i, 1); +#ifdef USE_RESCUE_EEPROM_SDM275 + if (saa->boardcfg[0] != 0) { + printk("stradis%d: WARNING: EEPROM STORED VALUES HAVE BEEN IGNORED\n", saa->nr); + for (i = 0; i < 64; i++) + saa->boardcfg[i] = rescue_eeprom[i]; + } +#endif + printk("stradis%d: config =", saa->nr); + for (i = 0; i < 51; i++) { + printk(" %02x",saa->boardcfg[i]); + } + printk("\n"); + } +} + +static void detach_inform(struct i2c_bus *bus, int id) +{ + struct saa7146 *saa = (struct saa7146 *) bus->data; + int i; + i = saa->nr; +} + +static void I2CBusScan(struct i2c_bus *bus) +{ + int i; + for (i = 0; i < 0xff; i += 2) + if ((I2CRead(bus, i, 0, 0)) >= 0) + attach_inform(bus, i); +} + +static struct i2c_bus saa7146_i2c_bus_template = +{ + "saa7146", + I2C_BUSID_BT848, + NULL, + SPIN_LOCK_UNLOCKED, + attach_inform, + detach_inform, + NULL, + NULL, + I2CReadOld, + I2CWrite, +}; + +static int debiwait_maxwait = 0; + +static int wait_for_debi_done(struct saa7146 *saa) +{ + int i; + + /* wait for registers to be programmed */ + for (i = 0; i < 100000 && + !(saaread(SAA7146_MC2) & SAA7146_MC2_UPLD_DEBI); i++) + saaread(SAA7146_MC2); + /* wait for transfer to complete */ + for (i = 0; i < 500000 && + (saaread(SAA7146_PSR) & SAA7146_PSR_DEBI_S); i++) + saaread(SAA7146_MC2); + if (i > debiwait_maxwait) + printk("wait-for-debi-done maxwait: %d\n", + debiwait_maxwait = i); + + if (i == 500000) + return -1; + return 0; +} + +static int debiwrite(struct saa7146 *saa, u32 config, int addr, + u32 val, int count) +{ + u32 cmd; + if (count <= 0 || count > 32764) + return -1; + if (wait_for_debi_done(saa) < 0) + return -1; + saawrite(config, SAA7146_DEBI_CONFIG); + if (count <= 4) /* immediate transfer */ + saawrite(val, SAA7146_DEBI_AD); + else /* block transfer */ + saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); + saawrite((cmd = (count << 17) | (addr & 0xffff)), SAA7146_DEBI_COMMAND); + saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, + SAA7146_MC2); + return 0; +} + +static u32 debiread(struct saa7146 *saa, u32 config, int addr, int count) +{ + u32 result = 0; + + if (count > 32764 || count <= 0) + return 0; + if (wait_for_debi_done(saa) < 0) + return 0; + saawrite(virt_to_bus(saa->dmadebi), SAA7146_DEBI_AD); + saawrite((count << 17) | 0x10000 | (addr & 0xffff), + SAA7146_DEBI_COMMAND); + saawrite(config, SAA7146_DEBI_CONFIG); + saawrite((SAA7146_MC2_UPLD_DEBI << 16) | SAA7146_MC2_UPLD_DEBI, + SAA7146_MC2); + if (count > 4) /* not an immediate transfer */ + return count; + wait_for_debi_done(saa); + result = saaread(SAA7146_DEBI_AD); + if (count == 1) + result &= 0xff; + if (count == 2) + result &= 0xffff; + if (count == 3) + result &= 0xffffff; + return result; +} + +/* MUST be a multiple of 8 bytes and 8-byte aligned and < 32768 bytes */ +/* data copied into saa->dmadebi buffer, caller must re-enable interrupts */ +static void ibm_block_dram_read(struct saa7146 *saa, int address, int bytes) +{ + int i, j; + u32 *buf; + buf = (u32 *) saa->dmadebi; + if (bytes > 0x7000) + bytes = 0x7000; + saawrite(0, SAA7146_IER); /* disable interrupts */ + for (i=0; i < 10000 && + (debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) + & 0x8000); i++) + saaread(SAA7146_MC2); + if (i == 10000) + printk(KERN_ERR "stradis%d: dram_busy never cleared\n", + saa->nr); + debiwrite(saa, debNormal, IBM_MP2_SRC_ADDR, (address<<16) | + (address>>16), 4); + debiwrite(saa, debNormal, IBM_MP2_BLOCK_SIZE, bytes, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 0x8a10, 2); + for (j = 0; j < bytes/4; j++) { + for (i = 0; i < 10000 && + (!(debiread(saa, debNormal, IBM_MP2_DRAM_CMD_STAT, 2) + & 0x4000)); i++) + saaread(SAA7146_MC2); + if (i == 10000) + printk(KERN_ERR "stradis%d: dram_ready never set\n", + saa->nr); + buf[j] = debiread(saa, debNormal, IBM_MP2_DRAM_DATA, 4); + } +} + +static void do_irq_send_data(struct saa7146 *saa) +{ + int split, audbytes, vidbytes; + + saawrite(SAA7146_PSR_PIN1, SAA7146_IER); + /* if special feature mode in effect, disable audio sending */ + if (saa->playmode != VID_PLAY_NORMAL) + saa->audtail = saa->audhead = 0; + if (saa->audhead <= saa->audtail) + audbytes = saa->audtail - saa->audhead; + else + audbytes = 65536 - (saa->audhead - saa->audtail); + if (saa->vidhead <= saa->vidtail) + vidbytes = saa->vidtail - saa->vidhead; + else + vidbytes = 524288 - (saa->vidhead - saa->vidtail); + if (audbytes == 0 && vidbytes == 0 && saa->osdtail == saa->osdhead) { + saawrite(0, SAA7146_IER); + return; + } + /* if at least 1 block audio waiting and audio fifo isn't full */ + if (audbytes >= 2048 && (debiread(saa, debNormal, + IBM_MP2_AUD_FIFO, 2) & 0xff) < 60) { + if (saa->audhead > saa->audtail) + split = 65536 - saa->audhead; + else + split = 0; + audbytes = 2048; + if (split > 0 && split < 2048) { + memcpy(saa->dmadebi, saa->audbuf + saa->audhead, + split); + saa->audhead = 0; + audbytes -= split; + } else + split = 0; + memcpy(saa->dmadebi + split, saa->audbuf + saa->audhead, + audbytes); + saa->audhead += audbytes; + saa->audhead &= 0xffff; + debiwrite(saa, debAudio, (NewCard? IBM_MP2_AUD_FIFO : + IBM_MP2_AUD_FIFOW), 0, 2048); + wake_up_interruptible(&saa->audq); + /* if at least 1 block video waiting and video fifo isn't full */ + } else if (vidbytes >= 30720 && (debiread(saa, debNormal, + IBM_MP2_FIFO, 2)) < 16384) { + if (saa->vidhead > saa->vidtail) + split = 524288 - saa->vidhead; + else + split = 0; + vidbytes = 30720; + if (split > 0 && split < 30720) { + memcpy(saa->dmadebi, saa->vidbuf + saa->vidhead, + split); + saa->vidhead = 0; + vidbytes -= split; + } else + split = 0; + memcpy(saa->dmadebi + split, saa->vidbuf + saa->vidhead, + vidbytes); + saa->vidhead += vidbytes; + saa->vidhead &= 0x7ffff; + debiwrite(saa, debVideo, (NewCard ? IBM_MP2_FIFO : + IBM_MP2_FIFOW), 0, 30720); + wake_up_interruptible(&saa->vidq); + } + saawrite(SAA7146_PSR_DEBI_S | SAA7146_PSR_PIN1, SAA7146_IER); +} + +static void send_osd_data(struct saa7146 *saa) +{ + int size = saa->osdtail - saa->osdhead; + if (size > 30720) + size = 30720; + /* ensure some multiple of 8 bytes is transferred */ + size = 8 * ((size + 8)>>3); + if (size) { + debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, + (saa->osdhead>>3), 2); + memcpy(saa->dmadebi, &saa->osdbuf[saa->osdhead], size); + saa->osdhead += size; + /* block transfer of next 8 bytes to ~32k bytes */ + debiwrite(saa, debNormal, IBM_MP2_OSD_DATA, 0, size); + } + if (saa->osdhead >= saa->osdtail) { + saa->osdhead = saa->osdtail = 0; + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); + } +} + +static void saa7146_irq(int irq, void *dev_id, struct pt_regs *regs) +{ + struct saa7146 *saa = (struct saa7146 *) dev_id; + u32 stat, astat; + int count; + + count = 0; + while (1) { + /* get/clear interrupt status bits */ + stat = saaread(SAA7146_ISR); + astat = stat & saaread(SAA7146_IER); + if (!astat) + return; + saawrite(astat, SAA7146_ISR); + if (astat & SAA7146_PSR_DEBI_S) { + do_irq_send_data(saa); + } + if (astat & SAA7146_PSR_PIN1) { + int istat; + /* the following read will trigger DEBI_S */ + istat = debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); + if (istat & 1) { + saawrite(0, SAA7146_IER); + send_osd_data(saa); + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + } + if (istat & 0x20) { /* Video Start */ + saa->vidinfo.frame_count++; + } + if (istat & 0x400) { /* Picture Start */ + /* update temporal reference */ + } + if (istat & 0x200) { /* Picture Resolution Change */ + /* read new resolution */ + } + if (istat & 0x100) { /* New User Data found */ + /* read new user data */ + } + if (istat & 0x1000) { /* new GOP/SMPTE */ + /* read new SMPTE */ + } + if (istat & 0x8000) { /* Sequence Start Code */ + /* reset frame counter, load sizes */ + saa->vidinfo.frame_count = 0; + saa->vidinfo.h_size = 704; + saa->vidinfo.v_size = 480; +#if 0 + if (saa->endmarkhead != saa->endmarktail) { + saa->audhead = + saa->endmark[saa->endmarkhead]; + saa->endmarkhead++; + if (saa->endmarkhead >= MAX_MARKS) + saa->endmarkhead = 0; + } +#endif + } + if (istat & 0x4000) { /* Sequence Error Code */ + if (saa->endmarkhead != saa->endmarktail) { + saa->audhead = + saa->endmark[saa->endmarkhead]; + saa->endmarkhead++; + if (saa->endmarkhead >= MAX_MARKS) + saa->endmarkhead = 0; + } + } + } +#ifdef IDEBUG + if (astat & SAA7146_PSR_PPEF) { + IDEBUG(printk("stradis%d irq: PPEF\n", saa->nr)); + } + if (astat & SAA7146_PSR_PABO) { + IDEBUG(printk("stradis%d irq: PABO\n", saa->nr)); + } + if (astat & SAA7146_PSR_PPED) { + IDEBUG(printk("stradis%d irq: PPED\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_I1) { + IDEBUG(printk("stradis%d irq: RPS_I1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_I0) { + IDEBUG(printk("stradis%d irq: RPS_I0\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_LATE1) { + IDEBUG(printk("stradis%d irq: RPS_LATE1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_LATE0) { + IDEBUG(printk("stradis%d irq: RPS_LATE0\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_E1) { + IDEBUG(printk("stradis%d irq: RPS_E1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_E0) { + IDEBUG(printk("stradis%d irq: RPS_E0\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_TO1) { + IDEBUG(printk("stradis%d irq: RPS_TO1\n", saa->nr)); + } + if (astat & SAA7146_PSR_RPS_TO0) { + IDEBUG(printk("stradis%d irq: RPS_TO0\n", saa->nr)); + } + if (astat & SAA7146_PSR_UPLD) { + IDEBUG(printk("stradis%d irq: UPLD\n", saa->nr)); + } + if (astat & SAA7146_PSR_DEBI_E) { + IDEBUG(printk("stradis%d irq: DEBI_E\n", saa->nr)); + } + if (astat & SAA7146_PSR_I2C_S) { + IDEBUG(printk("stradis%d irq: I2C_S\n", saa->nr)); + } + if (astat & SAA7146_PSR_I2C_E) { + IDEBUG(printk("stradis%d irq: I2C_E\n", saa->nr)); + } + if (astat & SAA7146_PSR_A2_IN) { + IDEBUG(printk("stradis%d irq: A2_IN\n", saa->nr)); + } + if (astat & SAA7146_PSR_A2_OUT) { + IDEBUG(printk("stradis%d irq: A2_OUT\n", saa->nr)); + } + if (astat & SAA7146_PSR_A1_IN) { + IDEBUG(printk("stradis%d irq: A1_IN\n", saa->nr)); + } + if (astat & SAA7146_PSR_A1_OUT) { + IDEBUG(printk("stradis%d irq: A1_OUT\n", saa->nr)); + } + if (astat & SAA7146_PSR_AFOU) { + IDEBUG(printk("stradis%d irq: AFOU\n", saa->nr)); + } + if (astat & SAA7146_PSR_V_PE) { + IDEBUG(printk("stradis%d irq: V_PE\n", saa->nr)); + } + if (astat & SAA7146_PSR_VFOU) { + IDEBUG(printk("stradis%d irq: VFOU\n", saa->nr)); + } + if (astat & SAA7146_PSR_FIDA) { + IDEBUG(printk("stradis%d irq: FIDA\n", saa->nr)); + } + if (astat & SAA7146_PSR_FIDB) { + IDEBUG(printk("stradis%d irq: FIDB\n", saa->nr)); + } + if (astat & SAA7146_PSR_PIN3) { + IDEBUG(printk("stradis%d irq: PIN3\n", saa->nr)); + } + if (astat & SAA7146_PSR_PIN2) { + IDEBUG(printk("stradis%d irq: PIN2\n", saa->nr)); + } + if (astat & SAA7146_PSR_PIN0) { + IDEBUG(printk("stradis%d irq: PIN0\n", saa->nr)); + } + if (astat & SAA7146_PSR_ECS) { + IDEBUG(printk("stradis%d irq: ECS\n", saa->nr)); + } + if (astat & SAA7146_PSR_EC3S) { + IDEBUG(printk("stradis%d irq: EC3S\n", saa->nr)); + } + if (astat & SAA7146_PSR_EC0S) { + IDEBUG(printk("stradis%d irq: EC0S\n", saa->nr)); + } +#endif + count++; + if (count > 15) + printk(KERN_WARNING "stradis%d: irq loop %d\n", + saa->nr, count); + if (count > 20) { + saawrite(0, SAA7146_IER); + printk(KERN_ERR + "stradis%d: IRQ loop cleared\n", saa->nr); + } + } +} + +static int ibm_send_command(struct saa7146 *saa, + int command, int data, int chain) +{ + int i; + + if (chain) + debiwrite(saa, debNormal, IBM_MP2_COMMAND, (command << 1) | 1, 2); + else + debiwrite(saa, debNormal, IBM_MP2_COMMAND, command << 1, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_DATA, data, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_STAT, 1, 2); + for (i = 0; i < 100 && + (debiread(saa, debNormal, IBM_MP2_CMD_STAT, 2) & 1); i++) + schedule(); + if (i == 100) + return -1; + return 0; +} + +static void cs4341_setlevel(struct saa7146 *saa, int left, int right) +{ + I2CWrite(&(saa->i2c), 0x22, 0x03, + left > 94 ? 94 : left, 2); + I2CWrite(&(saa->i2c), 0x22, 0x04, + right > 94 ? 94 : right, 2); +} + +static void initialize_cs4341(struct saa7146 *saa) +{ + int i; + for (i = 0; i < 200; i++) { + /* auto mute off, power on, no de-emphasis */ + /* I2S data up to 24-bit 64xFs internal SCLK */ + I2CWrite(&(saa->i2c), 0x22, 0x01, 0x11, 2); + /* ATAPI mixer setings */ + I2CWrite(&(saa->i2c), 0x22, 0x02, 0x49, 2); + /* attenuation left 3db */ + I2CWrite(&(saa->i2c), 0x22, 0x03, 0x00, 2); + /* attenuation right 3db */ + I2CWrite(&(saa->i2c), 0x22, 0x04, 0x00, 2); + I2CWrite(&(saa->i2c), 0x22, 0x01, 0x10, 2); + if (I2CRead(&(saa->i2c), 0x22, 0x02, 1) == 0x49) + break; + schedule(); + } + printk("stradis%d: CS4341 initialized (%d)\n", saa->nr, i); + return; +} + +static void initialize_cs8420(struct saa7146 *saa, int pro) +{ + int i; + u8 *sequence; + if (pro) + sequence = mode8420pro; + else + sequence = mode8420con; + for (i = 0; i < INIT8420LEN; i++) + I2CWrite(&(saa->i2c), 0x20, init8420[i * 2], + init8420[i * 2 + 1], 2); + for (i = 0; i < MODE8420LEN; i++) + I2CWrite(&(saa->i2c), 0x20, sequence[i * 2], + sequence[i * 2 + 1], 2); + printk("stradis%d: CS8420 initialized\n", saa->nr); +} + +static void initialize_saa7121(struct saa7146 *saa, int dopal) +{ + int i, mod; + u8 *sequence; + if (dopal) + sequence = init7121pal; + else + sequence = init7121ntsc; + mod = saaread(SAA7146_PSR) & 0x08; + /* initialize PAL/NTSC video encoder */ + for (i = 0; i < INIT7121LEN; i++) { + if (NewCard) { /* handle new card encoder differences */ + if (sequence[i*2] == 0x3a) + I2CWrite(&(saa->i2c), 0x88, 0x3a, 0x13, 2); + else if (sequence[i*2] == 0x6b) + I2CWrite(&(saa->i2c), 0x88, 0x6b, 0x20, 2); + else if (sequence[i*2] == 0x6c) + I2CWrite(&(saa->i2c), 0x88, 0x6c, + dopal ? 0x09 : 0xf5, 2); + else if (sequence[i*2] == 0x6d) + I2CWrite(&(saa->i2c), 0x88, 0x6d, + dopal ? 0x20 : 0x00, 2); + else if (sequence[i*2] == 0x7a) + I2CWrite(&(saa->i2c), 0x88, 0x7a, + dopal ? (PALFirstActive - 1) : + (NTSCFirstActive - 4), 2); + else if (sequence[i*2] == 0x7b) + I2CWrite(&(saa->i2c), 0x88, 0x7b, + dopal ? PALLastActive : + NTSCLastActive, 2); + else I2CWrite(&(saa->i2c), 0x88, sequence[i * 2], + sequence[i * 2 + 1], 2); + } else { + if (sequence[i*2] == 0x6b && mod) + I2CWrite(&(saa->i2c), 0x88, 0x6b, + (sequence[i * 2 + 1] ^ 0x09), 2); + else if (sequence[i*2] == 0x7a) + I2CWrite(&(saa->i2c), 0x88, 0x7a, + dopal ? (PALFirstActive - 1) : + (NTSCFirstActive - 4), 2); + else if (sequence[i*2] == 0x7b) + I2CWrite(&(saa->i2c), 0x88, 0x7b, + dopal ? PALLastActive : + NTSCLastActive, 2); + else + I2CWrite(&(saa->i2c), 0x88, sequence[i * 2], + sequence[i * 2 + 1], 2); + } + } +} + +static void set_genlock_offset(struct saa7146 *saa, int noffset) +{ + int nCode; + int PixelsPerLine = 858; + if (CurrentMode == VIDEO_MODE_PAL) + PixelsPerLine = 864; + if (noffset > 500) + noffset = 500; + else if (noffset < -500) + noffset = -500; + nCode = noffset + 0x100; + if (nCode == 1) + nCode = 0x401; + else if (nCode < 1) nCode = 0x400 + PixelsPerLine + nCode; + debiwrite(saa, debNormal, XILINX_GLDELAY, nCode, 2); +} + +static void set_out_format(struct saa7146 *saa, int mode) +{ + initialize_saa7121(saa, (mode == VIDEO_MODE_NTSC ? 0 : 1)); + saa->boardcfg[2] = mode; + /* do not adjust analog video parameters here, use saa7121 init */ + /* you will affect the SDI output on the new card */ + if (mode == VIDEO_MODE_PAL) { /* PAL */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x0808, 2); + mdelay(50); + saawrite(0x012002c0, SAA7146_NUM_LINE_BYTE1); + if (NewCard) { + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + 0xe100, 2); + mdelay(50); + } + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + NewCard ? 0xe500: 0x6500, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, + (1 << 8) | + (NewCard ? PALFirstActive : PALFirstActive-6), 2); + } else { /* NTSC */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x0800, 2); + mdelay(50); + saawrite(0x00f002c0, SAA7146_NUM_LINE_BYTE1); + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + NewCard ? 0xe100: 0x6100, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_DLY, + (1 << 8) | + (NewCard ? NTSCFirstActive : NTSCFirstActive-6), 2); + } +} + + +/* Intialize bitmangler to map from a byte value to the mangled word that + * must be output to program the Xilinx part through the DEBI port. + * Xilinx Data Bit->DEBI Bit: 0->15 1->7 2->6 3->12 4->11 5->2 6->1 7->0 + * transfer FPGA code, init IBM chip, transfer IBM microcode + * rev2 card mangles: 0->7 1->6 2->5 3->4 4->3 5->2 6->1 7->0 + */ +static u16 bitmangler[256]; + +static int initialize_fpga(struct video_code *bitdata) +{ + int i, num, startindex, failure = 0, loadtwo, loadfile = 0; + u16 *dmabuf; + u8 *newdma; + struct saa7146 *saa; + + /* verify fpga code */ + for (startindex = 0; startindex < bitdata->datasize; startindex++) + if (bitdata->data[startindex] == 255) + break; + if (startindex == bitdata->datasize) { + printk(KERN_INFO "stradis: bad fpga code\n"); + return -1; + } + /* initialize all detected cards */ + for (num = 0; num < saa_num; num++) { + saa = &saa7146s[num]; + if (saa->boardcfg[0] > 20) + continue; /* card was programmed */ + loadtwo = (saa->boardcfg[18] & 0x10); + if (!NewCard) /* we have an old board */ + for (i = 0; i < 256; i++) + bitmangler[i] = ((i & 0x01) << 15) | + ((i & 0x02) << 6) | ((i & 0x04) << 4) | + ((i & 0x08) << 9) | ((i & 0x10) << 7) | + ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | + ((i & 0x80) >> 7); + else /* else we have a new board */ + for (i = 0; i < 256; i++) + bitmangler[i] = ((i & 0x01) << 7) | + ((i & 0x02) << 5) | ((i & 0x04) << 3) | + ((i & 0x08) << 1) | ((i & 0x10) >> 1) | + ((i & 0x20) >> 3) | ((i & 0x40) >> 5) | + ((i & 0x80) >> 7); + + dmabuf = (u16 *) saa->dmadebi; + newdma = (u8 *) saa->dmadebi; + if (NewCard) { /* SDM2xxx */ + if (!strncmp(bitdata->loadwhat, "decoder2", 8)) + continue; /* fpga not for this card */ + if (!strncmp(&saa->boardcfg[42], + bitdata->loadwhat, 8)) { + loadfile = 1; + } else if (loadtwo && !strncmp(&saa->boardcfg[19], + bitdata->loadwhat, 8)) { + loadfile = 2; + } else if (!saa->boardcfg[42] && /* special */ + !strncmp("decxl", bitdata->loadwhat, 8)) { + loadfile = 1; + } else + continue; /* fpga not for this card */ + if (loadfile != 1 && loadfile != 2) { + continue; /* skip to next card */ + } + if (saa->boardcfg[0] && loadfile == 1 ) + continue; /* skip to next card */ + if (saa->boardcfg[0] != 1 && loadfile == 2) + continue; /* skip to next card */ + saa->boardcfg[0]++; /* mark fpga handled */ + printk("stradis%d: loading %s\n", saa->nr, + bitdata->loadwhat); + if (loadtwo && loadfile == 2) + goto send_fpga_stuff; + /* turn on the Audio interface to set PROG low */ + saawrite(0x00400040, SAA7146_GPIO_CTRL); + saaread(SAA7146_PSR); /* ensure posted write */ + /* wait for everyone to reset */ + mdelay(10); + saawrite(0x00400000, SAA7146_GPIO_CTRL); + } else { /* original card */ + if (strncmp(bitdata->loadwhat, "decoder2", 8)) + continue; /* fpga not for this card */ + /* Pull the Xilinx PROG signal WS3 low */ + saawrite(0x02000200, SAA7146_MC1); + /* Turn on the Audio interface so can set PROG low */ + saawrite(0x000000c0, SAA7146_ACON1); + /* Pull the Xilinx INIT signal (GPIO2) low */ + saawrite(0x00400000, SAA7146_GPIO_CTRL); + /* Make sure everybody resets */ + saaread(SAA7146_PSR); /* ensure posted write */ + mdelay(10); + /* Release the Xilinx PROG signal */ + saawrite(0x00000000, SAA7146_ACON1); + /* Turn off the Audio interface */ + saawrite(0x02000000, SAA7146_MC1); + } + /* Release Xilinx INIT signal (WS2) */ + saawrite(0x00000000, SAA7146_GPIO_CTRL); + /* Wait for the INIT to go High */ + for (i = 0; i < 10000 && + !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++) + schedule(); + if (i == 1000) { + printk(KERN_INFO "stradis%d: no fpga INIT\n", saa->nr); + return -1; + } +send_fpga_stuff: + if (NewCard) { + for (i = startindex; i < bitdata->datasize; i++) + newdma[i - startindex] = + bitmangler[bitdata->data[i]]; + debiwrite(saa, 0x01420000, 0, 0, + ((bitdata->datasize - startindex) + 5)); + if (loadtwo) { + if (loadfile == 1) { + printk("stradis%d: " + "awaiting 2nd FPGA bitfile\n", + saa->nr); + continue; /* skip to next card */ + } + + } + } else { + for (i = startindex; i < bitdata->datasize; i++) + dmabuf[i - startindex] = + bitmangler[bitdata->data[i]]; + debiwrite(saa, 0x014a0000, 0, 0, + ((bitdata->datasize - startindex) + 5) * 2); + } + for (i = 0; i < 1000 && + !(saaread(SAA7146_PSR) & SAA7146_PSR_PIN2); i++) + schedule(); + if (i == 1000) { + printk(KERN_INFO "stradis%d: FPGA load failed\n", + saa->nr); + failure++; + continue; + } + if (!NewCard) { + /* Pull the Xilinx INIT signal (GPIO2) low */ + saawrite(0x00400000, SAA7146_GPIO_CTRL); + saaread(SAA7146_PSR); /* ensure posted write */ + mdelay(2); + saawrite(0x00000000, SAA7146_GPIO_CTRL); + mdelay(2); + } + printk(KERN_INFO "stradis%d: FPGA Loaded\n", saa->nr); + saa->boardcfg[0] = 26; /* mark fpga programmed */ + /* set VXCO to its lowest frequency */ + debiwrite(saa, debNormal, XILINX_PWM, 0, 2); + if (NewCard) { + /* mute CS3310 */ + if (HaveCS3310) + debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, + 0, 2); + /* set VXCO to PWM mode, release reset, blank on */ + debiwrite(saa, debNormal, XILINX_CTL0, 0xffc4, 2); + mdelay(10); + /* unmute CS3310 */ + if (HaveCS3310) + debiwrite(saa, debNormal, XILINX_CTL0, + 0x2020, 2); + } + /* set source Black */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); + saa->boardcfg[4] = 22; /* set NTSC First Active Line */ + saa->boardcfg[5] = 23; /* set PAL First Active Line */ + saa->boardcfg[54] = 2; /* set NTSC Last Active Line - 256 */ + saa->boardcfg[55] = 54; /* set PAL Last Active Line - 256 */ + set_out_format(saa, VIDEO_MODE_NTSC); + mdelay(50); + /* begin IBM chip init */ + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); + saaread(SAA7146_PSR); /* wait for reset */ + mdelay(5); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); + debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0x10, 2); + debiwrite(saa, debNormal, IBM_MP2_CMD_ADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); + if (NewCard) { + mdelay(5); + /* set i2s rate converter to 48KHz */ + debiwrite(saa, debNormal, 0x80c0, 6, 2); + /* we must init CS8420 first since rev b pulls i2s */ + /* master clock low and CS4341 needs i2s master to */ + /* run the i2c port. */ + if (HaveCS8420) { + /* 0=consumer, 1=pro */ + initialize_cs8420(saa, 0); + } + mdelay(5); + if (HaveCS4341) + initialize_cs4341(saa); + } + debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); + debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); + if (NewCard) + set_genlock_offset(saa, 0); + debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); +#if 0 + /* enable genlock */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x8000, 2); +#else + /* disable genlock */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x8080, 2); +#endif + } + return failure; +} + +static int do_ibm_reset(struct saa7146 *saa) +{ + /* failure if decoder not previously programmed */ + if (saa->boardcfg[0] < 37) + return -EIO; + /* mute CS3310 */ + if (HaveCS3310) + debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, 0, 2); + /* disable interrupts */ + saawrite(0, SAA7146_IER); + saa->audhead = saa->audtail = 0; + saa->vidhead = saa->vidtail = 0; + /* tristate debi bus, disable debi transfers */ + saawrite(0x00880000, SAA7146_MC1); + /* ensure posted write */ + saaread(SAA7146_MC1); + mdelay(50); + /* re-enable debi transfers */ + saawrite(0x00880088, SAA7146_MC1); + /* set source Black */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x1707, 2); + /* begin IBM chip init */ + set_out_format(saa, CurrentMode); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 4, 2); + saaread(SAA7146_PSR); /* wait for reset */ + mdelay(5); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); + debiread(saa, debNormal, IBM_MP2_CHIP_CONTROL, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_MODE, 0x2e, 2); + if (NewCard) { + mdelay(5); + /* set i2s rate converter to 48KHz */ + debiwrite(saa, debNormal, 0x80c0, 6, 2); + /* we must init CS8420 first since rev b pulls i2s */ + /* master clock low and CS4341 needs i2s master to */ + /* run the i2c port. */ + if (HaveCS8420) { + /* 0=consumer, 1=pro */ + initialize_cs8420(saa, 1); + } + mdelay(5); + if (HaveCS4341) + initialize_cs4341(saa); + } + debiwrite(saa, debNormal, IBM_MP2_INFC_CTL, 0x48, 2); + debiwrite(saa, debNormal, IBM_MP2_BEEP_CTL, 0xa000, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_LBOR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_TBOR, 0, 2); + if (NewCard) + set_genlock_offset(saa, 0); + debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); + if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, + (ChipControl == 0x43 ? 0xe800 : 0xe000), 1)) { + printk(KERN_ERR "stradis%d: IBM config failed\n", saa->nr); + } + if (HaveCS3310) { + int i = CS3310MaxLvl; + debiwrite(saa, debNormal, XILINX_CS3310_CMPLT, ((i<<8)|i), 2); + } + /* start video decoder */ + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); + /* 256k vid, 3520 bytes aud */ + debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, 0x4037, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); + ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); + /* enable buffer threshold irq */ + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); + /* clear pending interrupts */ + debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); + debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); + return 0; +} + +/* load the decoder microcode */ +static int initialize_ibmmpeg2(struct video_code *microcode) +{ + int i, num; + struct saa7146 *saa; + + for (num = 0; num < saa_num; num++) { + saa = &saa7146s[num]; + /* check that FPGA is loaded */ + debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0xa55a, 2); + if ((i = debiread(saa, debNormal, IBM_MP2_OSD_SIZE, 2)) != + 0xa55a) { + printk(KERN_INFO "stradis%d: %04x != 0xa55a\n", + saa->nr, i); +#if 0 + return -1; +#endif + } + if (!strncmp(microcode->loadwhat, "decoder.vid", 11)) { + if (saa->boardcfg[0] > 27) + continue; /* skip to next card */ + /* load video control store */ + saa->boardcfg[1] = 0x13; /* no-sync default */ + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); + debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); + for (i = 0; i < microcode->datasize / 2; i++) + debiwrite(saa, debNormal, IBM_MP2_PROC_IDATA, + (microcode->data[i * 2] << 8) | + microcode->data[i * 2 + 1], 2); + debiwrite(saa, debNormal, IBM_MP2_PROC_IADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + saa->boardcfg[0] = 28; + } + if (!strncmp(microcode->loadwhat, "decoder.aud", 11)) { + if (saa->boardcfg[0] > 35) + continue; /* skip to next card */ + /* load audio control store */ + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 1, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); + for (i = 0; i < microcode->datasize; i++) + debiwrite(saa, debNormal, IBM_MP2_AUD_IDATA, + microcode->data[i], 1); + debiwrite(saa, debNormal, IBM_MP2_AUD_IADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_WR_PROT, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_OSD_SIZE, 0x2000, 2); + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4552, 2); + if (ibm_send_command(saa, IBM_MP2_CONFIG_DECODER, + 0xe000, 1)) { + printk(KERN_ERR + "stradis%d: IBM config failed\n", + saa->nr); + return -1; + } + /* set PWM to center value */ + if (NewCard) { + debiwrite(saa, debNormal, XILINX_PWM, + saa->boardcfg[14] + + (saa->boardcfg[13]<<8), 2); + } else + debiwrite(saa, debNormal, XILINX_PWM, + 0x46, 2); + if (HaveCS3310) { + i = CS3310MaxLvl; + debiwrite(saa, debNormal, + XILINX_CS3310_CMPLT, ((i<<8)|i), 2); + } + printk(KERN_INFO + "stradis%d: IBM MPEGCD%d Initialized\n", + saa->nr, 18 + (debiread(saa, debNormal, + IBM_MP2_CHIP_CONTROL, 2) >> 12)); + /* start video decoder */ + debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + debiwrite(saa, debNormal, IBM_MP2_RB_THRESHOLD, + 0x4037, 2); /* 256k vid, 3520 bytes aud */ + debiwrite(saa, debNormal, IBM_MP2_AUD_CTL, 0x4573, 2); + ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); + /* enable buffer threshold irq */ + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00c, 2); + debiread(saa, debNormal, IBM_MP2_HOST_INT, 2); + /* enable gpio irq */ + saawrite(0x00002000, SAA7146_GPIO_CTRL); + /* enable decoder output to HPS */ + debiwrite(saa, debNormal, XILINX_CTL0, 0x1711, 2); + saa->boardcfg[0] = 37; + } + } + return 0; +} + +static u32 palette2fmt[] = +{ /* some of these YUV translations are wrong */ + 0xffffffff, 0x86000000, 0x87000000, 0x80000000, 0x8100000, 0x82000000, + 0x83000000, 0x00000000, 0x03000000, 0x03000000, 0x0a00000, 0x03000000, + 0x06000000, 0x00000000, 0x03000000, 0x0a000000, 0x0300000 +}; +static int bpp2fmt[4] = +{ + VIDEO_PALETTE_HI240, VIDEO_PALETTE_RGB565, VIDEO_PALETTE_RGB24, + VIDEO_PALETTE_RGB32 +}; + +/* I wish I could find a formula to calculate these... */ +static u32 h_prescale[64] = +{ + 0x10000000, 0x18040202, 0x18080000, 0x380c0606, 0x38100204, 0x38140808, + 0x38180000, 0x381c0000, 0x3820161c, 0x38242a3b, 0x38281230, 0x382c4460, + 0x38301040, 0x38340080, 0x38380000, 0x383c0000, 0x3840fefe, 0x3844ee9f, + 0x3848ee9f, 0x384cee9f, 0x3850ee9f, 0x38542a3b, 0x38581230, 0x385c0000, + 0x38600000, 0x38640000, 0x38680000, 0x386c0000, 0x38700000, 0x38740000, + 0x38780000, 0x387c0000, 0x30800000, 0x38840000, 0x38880000, 0x388c0000, + 0x38900000, 0x38940000, 0x38980000, 0x389c0000, 0x38a00000, 0x38a40000, + 0x38a80000, 0x38ac0000, 0x38b00000, 0x38b40000, 0x38b80000, 0x38bc0000, + 0x38c00000, 0x38c40000, 0x38c80000, 0x38cc0000, 0x38d00000, 0x38d40000, + 0x38d80000, 0x38dc0000, 0x38e00000, 0x38e40000, 0x38e80000, 0x38ec0000, + 0x38f00000, 0x38f40000, 0x38f80000, 0x38fc0000, +}; +static u32 v_gain[64] = +{ + 0x016000ff, 0x016100ff, 0x016100ff, 0x016200ff, 0x016200ff, 0x016200ff, + 0x016200ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, 0x016300ff, + 0x016300ff, 0x016300ff, 0x016300ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, + 0x016400ff, 0x016400ff, 0x016400ff, 0x016400ff, +}; + + +static void saa7146_set_winsize(struct saa7146 *saa) +{ + u32 format; + int offset, yacl, ysci; + saa->win.color_fmt = format = + (saa->win.depth == 15) ? palette2fmt[VIDEO_PALETTE_RGB555] : + palette2fmt[bpp2fmt[(saa->win.bpp - 1) & 3]]; + offset = saa->win.x * saa->win.bpp + saa->win.y * saa->win.bpl; + saawrite(saa->win.vidadr + offset, SAA7146_BASE_EVEN1); + saawrite(saa->win.vidadr + offset + saa->win.bpl, SAA7146_BASE_ODD1); + saawrite(saa->win.bpl * 2, SAA7146_PITCH1); + saawrite(saa->win.vidadr + saa->win.bpl * saa->win.sheight, + SAA7146_PROT_ADDR1); + saawrite(0, SAA7146_PAGE1); + saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); + offset = (704 / (saa->win.width - 1)) & 0x3f; + saawrite(h_prescale[offset], SAA7146_HPS_H_PRESCALE); + offset = (720896 / saa->win.width) / (offset + 1); + saawrite((offset<<12)|0x0c, SAA7146_HPS_H_SCALE); + if (CurrentMode == VIDEO_MODE_NTSC) { + yacl = /*(480 / saa->win.height - 1) & 0x3f*/ 0; + ysci = 1024 - (saa->win.height * 1024 / 480); + } else { + yacl = /*(576 / saa->win.height - 1) & 0x3f*/ 0; + ysci = 1024 - (saa->win.height * 1024 / 576); + } + saawrite((1<<31)|(ysci<<21)|(yacl<<15), SAA7146_HPS_V_SCALE); + saawrite(v_gain[yacl], SAA7146_HPS_V_GAIN); + saawrite(((SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_HPS_V | + SAA7146_MC2_UPLD_HPS_H) << 16) | (SAA7146_MC2_UPLD_DMA1 | + SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_HPS_H), + SAA7146_MC2); +} + +/* clip_draw_rectangle(cm,x,y,w,h) -- handle clipping an area + * bitmap is fixed width, 128 bytes (1024 pixels represented) + * arranged most-sigificant-bit-left in 32-bit words + * based on saa7146 clipping hardware, it swaps bytes if LE + * much of this makes up for egcs brain damage -- so if you + * are wondering "why did he do this?" it is because the C + * was adjusted to generate the optimal asm output without + * writing non-portable __asm__ directives. + */ + +static void clip_draw_rectangle(u32 *clipmap, int x, int y, int w, int h) +{ + register int startword, endword; + register u32 bitsleft, bitsright; + u32 *temp; + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + if (w <= 0 || h <= 0 || x > 1023 || y > 639) + return; /* throw away bad clips */ + if (x + w > 1024) + w = 1024 - x; + if (y + h > 640) + h = 640 - y; + startword = (x >> 5); + endword = ((x + w) >> 5); + bitsleft = (0xffffffff >> (x & 31)); + bitsright = (0xffffffff << (~((x + w) - (endword<<5)))); + temp = &clipmap[(y<<5) + startword]; + w = endword - startword; + if (!w) { + bitsleft |= bitsright; + for (y = 0; y < h; y++) { + *temp |= bitsleft; + temp += 32; + } + } else { + for (y = 0; y < h; y++) { + *temp++ |= bitsleft; + for (x = 1; x < w; x++) + *temp++ = 0xffffffff; + *temp |= bitsright; + temp += (32 - w); + } + } +} + +static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr) +{ + int i, width, height; + u32 *clipmap; + + clipmap = saa->dmavid2; + if((width=saa->win.width)>1023) + width = 1023; /* sanity check */ + if((height=saa->win.height)>640) + height = 639; /* sanity check */ + if (ncr > 0) { /* rectangles pased */ + /* convert rectangular clips to a bitmap */ + memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ + for (i = 0; i < ncr; i++) + clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, + cr[i].width, cr[i].height); + } + /* clip against viewing window AND screen + so we do not have to rely on the user program + */ + clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ? + (saa->win.swidth-saa->win.x) : width, 0, 1024, 768); + clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ? + (saa->win.sheight-saa->win.y) : height,1024,768); + if (saa->win.x<0) + clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768); + if (saa->win.y<0) + clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y)); +} + +static int saa_ioctl(struct video_device *dev, unsigned int cmd, void *arg) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + switch (cmd) { + case VIDIOCGCAP: + { + struct video_capability b; + strcpy(b.name, saa->video_dev.name); + b.type = VID_TYPE_CAPTURE | + VID_TYPE_OVERLAY | + VID_TYPE_CLIPPING | + VID_TYPE_FRAMERAM | + VID_TYPE_SCALES; + b.channels = 1; + b.audios = 1; + b.maxwidth = 768; + b.maxheight = 576; + b.minwidth = 32; + b.minheight = 32; + if (copy_to_user(arg, &b, sizeof(b))) + return -EFAULT; + return 0; + } + case VIDIOCGPICT: + { + struct video_picture p = saa->picture; + if (saa->win.depth == 8) + p.palette = VIDEO_PALETTE_HI240; + if (saa->win.depth == 15) + p.palette = VIDEO_PALETTE_RGB555; + if (saa->win.depth == 16) + p.palette = VIDEO_PALETTE_RGB565; + if (saa->win.depth == 24) + p.palette = VIDEO_PALETTE_RGB24; + if (saa->win.depth == 32) + p.palette = VIDEO_PALETTE_RGB32; + if (copy_to_user(arg, &p, sizeof(p))) + return -EFAULT; + return 0; + } + case VIDIOCSPICT: + { + struct video_picture p; + u32 format; + if (copy_from_user(&p, arg, sizeof(p))) + return -EFAULT; + if (p.palette < sizeof(palette2fmt) / sizeof(u32)) { + format = palette2fmt[p.palette]; + saa->win.color_fmt = format; + saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); + } + saawrite(((p.brightness & 0xff00) << 16) | + ((p.contrast & 0xfe00) << 7) | + ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL); + saa->picture = p; + /* upload changed registers */ + saawrite(((SAA7146_MC2_UPLD_HPS_H | + SAA7146_MC2_UPLD_HPS_V) << 16) | + SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V, + SAA7146_MC2); + return 0; + } + case VIDIOCSWIN: + { + struct video_window vw; + struct video_clip *vcp = NULL; + + if (copy_from_user(&vw, arg, sizeof(vw))) + return -EFAULT; + + if (vw.flags || vw.width < 16 || vw.height < 16) { /* stop capture */ + saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); + return -EINVAL; + } + if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */ + int i = vw.x; + vw.x = (vw.x + 3) & ~3; + i = vw.x - i; + vw.width -= i; + } + saa->win.x = vw.x; + saa->win.y = vw.y; + saa->win.width = vw.width; + if (saa->win.width > 768) + saa->win.width = 768; + saa->win.height = vw.height; + if (CurrentMode == VIDEO_MODE_NTSC) { + if (saa->win.height > 480) + saa->win.height = 480; + } else { + if (saa->win.height > 576) + saa->win.height = 576; + } + + /* stop capture */ + saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); + saa7146_set_winsize(saa); + + /* + * Do any clips. + */ + if (vw.clipcount < 0) { + if (copy_from_user(saa->dmavid2, vw.clips, + VIDEO_CLIPMAP_SIZE)) + return -EFAULT; + } else if (vw.clipcount > 0) { + if ((vcp = vmalloc(sizeof(struct video_clip) * + (vw.clipcount))) == NULL) + return -ENOMEM; + if (copy_from_user(vcp, vw.clips, + sizeof(struct video_clip) * + vw.clipcount)) { + vfree(vcp); + return -EFAULT; + } + } else /* nothing clipped */ + memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE); + make_clip_tab(saa, vcp, vw.clipcount); + if (vw.clipcount > 0) + vfree(vcp); + + /* start capture & clip dma if we have an address */ + if ((saa->cap & 3) && saa->win.vidadr != 0) + saawrite(((SAA7146_MC1_TR_E_1 | + SAA7146_MC1_TR_E_2) << 16) | 0xffff, + SAA7146_MC1); + return 0; + } + case VIDIOCGWIN: + { + struct video_window vw; + vw.x = saa->win.x; + vw.y = saa->win.y; + vw.width = saa->win.width; + vw.height = saa->win.height; + vw.chromakey = 0; + vw.flags = 0; + if (copy_to_user(arg, &vw, sizeof(vw))) + return -EFAULT; + return 0; + } + case VIDIOCCAPTURE: + { + int v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if (v == 0) { + saa->cap &= ~1; + saawrite((SAA7146_MC1_TR_E_1 << 16), + SAA7146_MC1); + } else { + if (saa->win.vidadr == 0 || saa->win.width == 0 + || saa->win.height == 0) + return -EINVAL; + saa->cap |= 1; + saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff, + SAA7146_MC1); + } + return 0; + } + case VIDIOCGFBUF: + { + struct video_buffer v; + v.base = (void *) saa->win.vidadr; + v.height = saa->win.sheight; + v.width = saa->win.swidth; + v.depth = saa->win.depth; + v.bytesperline = saa->win.bpl; + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + + } + case VIDIOCSFBUF: + { + struct video_buffer v; + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + if (v.depth != 8 && v.depth != 15 && v.depth != 16 && + v.depth != 24 && v.depth != 32 && v.width > 16 && + v.height > 16 && v.bytesperline > 16) + return -EINVAL; + if (v.base) + saa->win.vidadr = (unsigned long) v.base; + saa->win.sheight = v.height; + saa->win.swidth = v.width; + saa->win.bpp = ((v.depth + 7) & 0x38) / 8; + saa->win.depth = v.depth; + saa->win.bpl = v.bytesperline; + + DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", + v.base, v.width, v.height, saa->win.bpp, saa->win.bpl)); + saa7146_set_winsize(saa); + return 0; + } + case VIDIOCKEY: + { + /* Will be handled higher up .. */ + return 0; + } + + case VIDIOCGAUDIO: + { + struct video_audio v; + v = saa->audio_dev; + v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); + v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; + strcpy(v.name, "MPEG"); + v.mode = VIDEO_SOUND_STEREO; + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSAUDIO: + { + struct video_audio v; + int i; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + i = (~(v.volume>>8))&0xff; + if (!HaveCS4341) { + if (v.flags & VIDEO_AUDIO_MUTE) { + debiwrite(saa, debNormal, + IBM_MP2_FRNT_ATTEN, + 0xffff, 2); + } + if (!(v.flags & VIDEO_AUDIO_MUTE)) + debiwrite(saa, debNormal, + IBM_MP2_FRNT_ATTEN, + 0x0000, 2); + if (v.flags & VIDEO_AUDIO_VOLUME) + debiwrite(saa, debNormal, + IBM_MP2_FRNT_ATTEN, + (i<<8)|i, 2); + } else { + if (v.flags & VIDEO_AUDIO_MUTE) + cs4341_setlevel(saa, 0xff, 0xff); + if (!(v.flags & VIDEO_AUDIO_MUTE)) + cs4341_setlevel(saa, 0, 0); + if (v.flags & VIDEO_AUDIO_VOLUME) + cs4341_setlevel(saa, i, i); + } + saa->audio_dev = v; + return 0; + } + + case VIDIOCGUNIT: + { + struct video_unit vu; + vu.video = saa->video_dev.minor; + vu.vbi = VIDEO_NO_UNIT; + vu.radio = VIDEO_NO_UNIT; + vu.audio = VIDEO_NO_UNIT; + vu.teletext = VIDEO_NO_UNIT; + if (copy_to_user((void *) arg, (void *) &vu, sizeof(vu))) + return -EFAULT; + return 0; + } + case VIDIOCSPLAYMODE: + { + struct video_play_mode pmode; + if (copy_from_user((void *) &pmode, arg, + sizeof(struct video_play_mode))) + return -EFAULT; + switch (pmode.mode) { + case VID_PLAY_VID_OUT_MODE: + if (pmode.p1 != VIDEO_MODE_NTSC && + pmode.p1 != VIDEO_MODE_PAL) + return -EINVAL; + set_out_format(saa, pmode.p1); + return 0; + case VID_PLAY_GENLOCK: + debiwrite(saa, debNormal, + XILINX_CTL0, + (pmode.p1 ? 0x8000 : 0x8080), + 2); + if (NewCard) + set_genlock_offset(saa, + pmode.p2); + return 0; + case VID_PLAY_NORMAL: + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + ibm_send_command(saa, + IBM_MP2_PLAY, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_PAUSE: + /* IBM removed the PAUSE command */ + /* they say use SINGLE_FRAME now */ + case VID_PLAY_SINGLE_FRAME: + ibm_send_command(saa, + IBM_MP2_SINGLE_FRAME, + 0, 0); + if (saa->playmode == pmode.mode) { + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + } + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_FAST_FORWARD: + ibm_send_command(saa, + IBM_MP2_FAST_FORWARD, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_SLOW_MOTION: + ibm_send_command(saa, + IBM_MP2_SLOW_MOTION, + pmode.p1, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_IMMEDIATE_NORMAL: + /* ensure transfers resume */ + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + ibm_send_command(saa, + IBM_MP2_IMED_NORM_PLAY, 0, 0); + saa->playmode = VID_PLAY_NORMAL; + return 0; + case VID_PLAY_SWITCH_CHANNELS: + saa->audhead = saa->audtail = 0; + saa->vidhead = saa->vidtail = 0; + ibm_send_command(saa, + IBM_MP2_FREEZE_FRAME, 0, 1); + ibm_send_command(saa, + IBM_MP2_RESET_AUD_RATE, 0, 1); + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, 0, 2); + ibm_send_command(saa, + IBM_MP2_CHANNEL_SWITCH, 0, 1); + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + ibm_send_command(saa, + IBM_MP2_PLAY, 0, 0); + saa->playmode = VID_PLAY_NORMAL; + return 0; + case VID_PLAY_FREEZE_FRAME: + ibm_send_command(saa, + IBM_MP2_FREEZE_FRAME, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_STILL_MODE: + ibm_send_command(saa, + IBM_MP2_SET_STILL_MODE, 0, 0); + saa->playmode = pmode.mode; + return 0; + case VID_PLAY_MASTER_MODE: + if (pmode.p1 == VID_PLAY_MASTER_NONE) + saa->boardcfg[1] = 0x13; + else if (pmode.p1 == + VID_PLAY_MASTER_VIDEO) + saa->boardcfg[1] = 0x23; + else if (pmode.p1 == + VID_PLAY_MASTER_AUDIO) + saa->boardcfg[1] = 0x43; + else + return -EINVAL; + debiwrite(saa, debNormal, + IBM_MP2_CHIP_CONTROL, + ChipControl, 2); + return 0; + case VID_PLAY_ACTIVE_SCANLINES: + if (CurrentMode == VIDEO_MODE_PAL) { + if (pmode.p1 < 1 || + pmode.p2 > 625) + return -EINVAL; + saa->boardcfg[5] = pmode.p1; + saa->boardcfg[55] = (pmode.p1 + + (pmode.p2/2) - 1) & + 0xff; + } else { + if (pmode.p1 < 4 || + pmode.p2 > 525) + return -EINVAL; + saa->boardcfg[4] = pmode.p1; + saa->boardcfg[54] = (pmode.p1 + + (pmode.p2/2) - 4) & + 0xff; + } + set_out_format(saa, CurrentMode); + case VID_PLAY_RESET: + return do_ibm_reset(saa); + case VID_PLAY_END_MARK: + if (saa->endmarktail < + saa->endmarkhead) { + if (saa->endmarkhead - + saa->endmarktail < 2) + return -ENOSPC; + } else if (saa->endmarkhead <= + saa->endmarktail) { + if (saa->endmarktail - + saa->endmarkhead > + (MAX_MARKS - 2)) + return -ENOSPC; + } else + return -ENOSPC; + saa->endmark[saa->endmarktail] = + saa->audtail; + saa->endmarktail++; + if (saa->endmarktail >= MAX_MARKS) + saa->endmarktail = 0; + } + return -EINVAL; + } + case VIDIOCSWRITEMODE: + { + int mode; + if (copy_from_user((void *) &mode, arg, sizeof(int))) + return -EFAULT; + if (mode == VID_WRITE_MPEG_AUD || + mode == VID_WRITE_MPEG_VID || + mode == VID_WRITE_CC || + mode == VID_WRITE_TTX || + mode == VID_WRITE_OSD) { + saa->writemode = mode; + return 0; + } + return -EINVAL; + } + case VIDIOCSMICROCODE: + { + struct video_code ucode; + __u8 *udata; + int i; + if (copy_from_user((void *) &ucode, arg, + sizeof(ucode))) + return -EFAULT; + if (ucode.datasize > 65536 || ucode.datasize < 1024 || + strncmp(ucode.loadwhat, "dec", 3)) + return -EINVAL; + if ((udata = vmalloc(ucode.datasize)) == NULL) + return -ENOMEM; + if (copy_from_user((void *) udata, ucode.data, + ucode.datasize)) { + vfree(udata); + return -EFAULT; + } + ucode.data = udata; + if (!strncmp(ucode.loadwhat, "decoder.aud", 11) + || !strncmp(ucode.loadwhat, "decoder.vid", 11)) + i = initialize_ibmmpeg2(&ucode); + else + i = initialize_fpga(&ucode); + vfree(udata); + if (i) + return -EINVAL; + return 0; + + } + case VIDIOCGCHAN: /* this makes xawtv happy */ + { + struct video_channel v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + v.flags = VIDEO_VC_AUDIO; + v.tuners = 0; + v.type = VID_TYPE_MPEG_DECODER; + v.norm = CurrentMode; + strcpy(v.name, "MPEG2"); + if (copy_to_user(arg, &v, sizeof(v))) + return -EFAULT; + return 0; + } + case VIDIOCSCHAN: /* this makes xawtv happy */ + { + struct video_channel v; + if (copy_from_user(&v, arg, sizeof(v))) + return -EFAULT; + /* do nothing */ + return 0; + } + default: + return -ENOIOCTLCMD; + } + return 0; +} + +static int saa_init_done(struct video_device *dev) +{ + return 0; +} + +static int saa_mmap(struct video_device *dev, const char *adr, + unsigned long size) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + printk(KERN_DEBUG "stradis%d: saa_mmap called\n", saa->nr); + return -EINVAL; +} + +static long saa_read(struct video_device *dev, char *buf, + unsigned long count, int nonblock) +{ + return -EINVAL; +} + +static long saa_write(struct video_device *dev, const char *buf, + unsigned long count, int nonblock) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + unsigned long todo = count; + int blocksize, split; + unsigned long flags; + + while (todo > 0) { + if (saa->writemode == VID_WRITE_MPEG_AUD) { + spin_lock_irqsave(&saa->lock, flags); + if (saa->audhead <= saa->audtail) + blocksize = 65536-(saa->audtail - saa->audhead); + else + blocksize = saa->audhead - saa->audtail; + spin_unlock_irqrestore(&saa->lock, flags); + if (blocksize < 16384) { + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); + /* wait for buffer space to open */ + interruptible_sleep_on(&saa->audq); + } + spin_lock_irqsave(&saa->lock, flags); + if (saa->audhead <= saa->audtail) { + blocksize = 65536-(saa->audtail - saa->audhead); + split = 65536 - saa->audtail; + } else { + blocksize = saa->audhead - saa->audtail; + split = 65536; + } + spin_unlock_irqrestore(&saa->lock, flags); + blocksize--; + if (blocksize > todo) + blocksize = todo; + /* double check that we really have space */ + if (!blocksize) + return -ENOSPC; + if (split < blocksize) { + if (copy_from_user(saa->audbuf + + saa->audtail, buf, split)) + return -EFAULT; + buf += split; + todo -= split; + blocksize -= split; + saa->audtail = 0; + } + if (copy_from_user(saa->audbuf + saa->audtail, buf, + blocksize)) + return -EFAULT; + saa->audtail += blocksize; + todo -= blocksize; + buf += blocksize; + saa->audtail &= 0xffff; + } else if (saa->writemode == VID_WRITE_MPEG_VID) { + spin_lock_irqsave(&saa->lock, flags); + if (saa->vidhead <= saa->vidtail) + blocksize=524288-(saa->vidtail - saa->vidhead); + else + blocksize = saa->vidhead - saa->vidtail; + spin_unlock_irqrestore(&saa->lock, flags); + if (blocksize < 65536) { + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); + /* wait for buffer space to open */ + interruptible_sleep_on(&saa->vidq); + } + spin_lock_irqsave(&saa->lock, flags); + if (saa->vidhead <= saa->vidtail) { + blocksize=524288-(saa->vidtail - saa->vidhead); + split = 524288 - saa->vidtail; + } else { + blocksize = saa->vidhead - saa->vidtail; + split = 524288; + } + spin_unlock_irqrestore(&saa->lock, flags); + blocksize--; + if (blocksize > todo) + blocksize = todo; + /* double check that we really have space */ + if (!blocksize) + return -ENOSPC; + if (split < blocksize) { + if (copy_from_user(saa->vidbuf + + saa->vidtail, buf, split)) + return -EFAULT; + buf += split; + todo -= split; + blocksize -= split; + saa->vidtail = 0; + } + if (copy_from_user(saa->vidbuf + saa->vidtail, buf, + blocksize)) + return -EFAULT; + saa->vidtail += blocksize; + todo -= blocksize; + buf += blocksize; + saa->vidtail &= 0x7ffff; + } else if (saa->writemode == VID_WRITE_OSD) { + if (count > 131072) + return -ENOSPC; + if (copy_from_user(saa->osdbuf, buf, count)) + return -EFAULT; + buf += count; + saa->osdhead = 0; + saa->osdtail = count; + debiwrite(saa, debNormal, IBM_MP2_OSD_ADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_OSD_LINK_ADDR, 0, 2); + debiwrite(saa, debNormal, IBM_MP2_MASK0, 0xc00d, 2); + debiwrite(saa, debNormal, IBM_MP2_DISP_MODE, + debiread(saa, debNormal, + IBM_MP2_DISP_MODE, 2) | 1, 2); + /* trigger osd data transfer */ + saawrite(SAA7146_PSR_DEBI_S | + SAA7146_PSR_PIN1, SAA7146_IER); + saawrite(SAA7146_PSR_PIN1, SAA7146_PSR); + } + } + return count; +} + +static int saa_open(struct video_device *dev, int flags) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + + saa->video_dev.busy = 0; + saa->user++; + if (saa->user > 1) + return 0; /* device open already, don't reset */ + saa->writemode = VID_WRITE_MPEG_VID; /* default to video */ + return 0; +} + +static void saa_close(struct video_device *dev) +{ + struct saa7146 *saa = (struct saa7146 *) dev; + saa->user--; + saa->video_dev.busy = 0; + if (saa->user > 0) /* still someone using device */ + return; + saawrite(0x007f0000, SAA7146_MC1); /* stop all overlay dma */ +} + +/* template for video_device-structure */ +static struct video_device saa_template = +{ + "SAA7146A", + VID_TYPE_CAPTURE | VID_TYPE_OVERLAY, + VID_HARDWARE_SAA7146, + saa_open, + saa_close, + saa_read, + saa_write, + NULL, /* poll */ + saa_ioctl, + saa_mmap, + saa_init_done, + NULL, + 0, + 0 +}; + +static int configure_saa7146(struct pci_dev *dev, int num) +{ + int result; + struct saa7146 *saa; + + saa = &saa7146s[num]; + + saa->endmarkhead = saa->endmarktail = 0; + saa->win.x = saa->win.y = 0; + saa->win.width = saa->win.cropwidth = 720; + saa->win.height = saa->win.cropheight = 480; + saa->win.cropx = saa->win.cropy = 0; + saa->win.bpp = 2; + saa->win.depth = 16; + saa->win.color_fmt = palette2fmt[VIDEO_PALETTE_RGB565]; + saa->win.bpl = 1024 * saa->win.bpp; + saa->win.swidth = 1024; + saa->win.sheight = 768; + saa->picture.brightness = 32768; + saa->picture.contrast = 38768; + saa->picture.colour = 32768; + saa->cap = 0; + saa->dev = dev; + saa->nr = num; + saa->playmode = VID_PLAY_NORMAL; + memset(saa->boardcfg, 0, 64); /* clear board config area */ + saa->saa7146_mem = NULL; + saa->dmavid1 = saa->dmavid2 = saa->dmavid3 = saa->dmaa1in = + saa->dmaa1out = saa->dmaa2in = saa->dmaa2out = + saa->pagevid1 = saa->pagevid2 = saa->pagevid3 = saa->pagea1in = + saa->pagea1out = saa->pagea2in = saa->pagea2out = + saa->pagedebi = saa->dmaRPS1 = saa->dmaRPS2 = saa->pageRPS1 = + saa->pageRPS2 = NULL; + saa->audbuf = saa->vidbuf = saa->osdbuf = saa->dmadebi = NULL; + saa->audhead = saa->vidtail = 0; + + init_waitqueue_head(&saa->i2cq); + init_waitqueue_head(&saa->audq); + init_waitqueue_head(&saa->debiq); + init_waitqueue_head(&saa->vidq); + spin_lock_init(&saa->lock); + + saa->id = dev->device; + saa->irq = dev->irq; + saa->video_dev.minor = -1; + saa->saa7146_adr = dev->resource[0].start; + pci_read_config_byte(dev, PCI_CLASS_REVISION, &saa->revision); + saa->saa7146_mem = ioremap(((saa->saa7146_adr) & + PCI_BASE_ADDRESS_MEM_MASK), 0x200); + memcpy(&(saa->i2c), &saa7146_i2c_bus_template, sizeof(struct i2c_bus)); + memcpy(&saa->video_dev, &saa_template, sizeof(saa_template)); + sprintf(saa->i2c.name, "stradis%d", num); + saa->i2c.data = saa; + saawrite(0, SAA7146_IER); /* turn off all interrupts */ + result = request_irq(saa->irq, saa7146_irq, + SA_SHIRQ | SA_INTERRUPT, "stradis", (void *) saa); + if (result == -EINVAL) + printk(KERN_ERR "stradis%d: Bad irq number or handler\n", + num); + if (result == -EBUSY) + printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP" + " config in BIOS\n", num, saa->irq); + if (result < 0) + return result; + pci_set_master(dev); + if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0) + return -1; +#if 0 + /* i2c generic interface is currently BROKEN */ + i2c_register_bus(&saa->i2c); +#endif + return 0; +} + +static int init_saa7146(int i) +{ + struct saa7146 *saa = &saa7146s[i]; + + saa->user = 0; + /* reset the saa7146 */ + saawrite(0xffff0000, SAA7146_MC1); + mdelay(5); + /* enable debi and i2c transfers and pins */ + saawrite(((SAA7146_MC1_EDP | SAA7146_MC1_EI2C | + SAA7146_MC1_TR_E_DEBI) << 16) | 0xffff, SAA7146_MC1); + /* ensure proper state of chip */ + saawrite(0x00000000, SAA7146_PAGE1); + saawrite(0x00f302c0, SAA7146_NUM_LINE_BYTE1); + saawrite(0x00000000, SAA7146_PAGE2); + saawrite(0x01400080, SAA7146_NUM_LINE_BYTE2); + saawrite(0x00000000, SAA7146_DD1_INIT); + saawrite(0x00000000, SAA7146_DD1_STREAM_B); + saawrite(0x00000000, SAA7146_DD1_STREAM_A); + saawrite(0x00000000, SAA7146_BRS_CTRL); + saawrite(0x80400040, SAA7146_BCS_CTRL); + saawrite(0x0000e000 /*| (1<<29)*/, SAA7146_HPS_CTRL); + saawrite(0x00000060, SAA7146_CLIP_FORMAT_CTRL); + saawrite(0x00000000, SAA7146_ACON1); + saawrite(0x00000000, SAA7146_ACON2); + saawrite(0x00000600, SAA7146_I2C_STATUS); + saawrite(((SAA7146_MC2_UPLD_D1_B | SAA7146_MC2_UPLD_D1_A | + SAA7146_MC2_UPLD_BRS | SAA7146_MC2_UPLD_HPS_H | + SAA7146_MC2_UPLD_HPS_V | SAA7146_MC2_UPLD_DMA2 | + SAA7146_MC2_UPLD_DMA1 | SAA7146_MC2_UPLD_I2C) << 16) | 0xffff, + SAA7146_MC2); + /* setup arbitration control registers */ + saawrite(0x1412121a, SAA7146_PCI_BT_V1); + + /* allocate 32k dma buffer + 4k for page table */ + if ((saa->dmadebi = kmalloc(32768 + 4096, GFP_KERNEL)) == NULL) { + printk(KERN_ERR "stradis%d: debi kmalloc failed\n", i); + return -1; + } +#if 0 + saa->pagedebi = saa->dmadebi + 32768; /* top 4k is for mmu */ + saawrite(virt_to_bus(saa->pagedebi) /*|0x800 */ , SAA7146_DEBI_PAGE); + for (i = 0; i < 12; i++) /* setup mmu page table */ + saa->pagedebi[i] = virt_to_bus((saa->dmadebi + i * 4096)); +#endif + saa->audhead = saa->vidhead = saa->osdhead = 0; + saa->audtail = saa->vidtail = saa->osdtail = 0; + if (saa->vidbuf == NULL) + if ((saa->vidbuf = vmalloc(524288)) == NULL) { + printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); + return -ENOMEM; + } + if (saa->audbuf == NULL) + if ((saa->audbuf = vmalloc(65536)) == NULL) { + printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); + vfree(saa->vidbuf); + saa->vidbuf = NULL; + return -ENOMEM; + } + if (saa->osdbuf == NULL) + if ((saa->osdbuf = vmalloc(131072)) == NULL) { + printk(KERN_ERR "stradis%d: malloc failed\n", saa->nr); + vfree(saa->vidbuf); + vfree(saa->audbuf); + saa->vidbuf = saa->audbuf = NULL; + return -ENOMEM; + } + /* allocate 81920 byte buffer for clipping */ + if ((saa->dmavid2 = kmalloc(VIDEO_CLIPMAP_SIZE, GFP_KERNEL)) == NULL) { + printk(KERN_ERR "stradis%d: clip kmalloc failed\n", saa->nr); + vfree(saa->vidbuf); + vfree(saa->audbuf); + vfree(saa->osdbuf); + saa->vidbuf = saa->audbuf = saa->osdbuf = NULL; + saa->dmavid2 = NULL; + return -1; + } + memset(saa->dmavid2, 0x00, VIDEO_CLIPMAP_SIZE); /* clip everything */ + /* setup clipping registers */ + saawrite(virt_to_bus(saa->dmavid2), SAA7146_BASE_EVEN2); + saawrite(virt_to_bus(saa->dmavid2) + 128, SAA7146_BASE_ODD2); + saawrite(virt_to_bus(saa->dmavid2) + VIDEO_CLIPMAP_SIZE, + SAA7146_PROT_ADDR2); + saawrite(256, SAA7146_PITCH2); + saawrite(4, SAA7146_PAGE2); /* dma direction: read, no byteswap */ + saawrite(((SAA7146_MC2_UPLD_DMA2) << 16) | SAA7146_MC2_UPLD_DMA2, + SAA7146_MC2); + I2CBusScan(&(saa->i2c)); + return 0; +} + +static void release_saa(void) +{ + u8 command; + int i; + struct saa7146 *saa; + + for (i = 0; i < saa_num; i++) { + saa = &saa7146s[i]; + + /* turn off all capturing, DMA and IRQs */ + saawrite(0xffff0000, SAA7146_MC1); /* reset chip */ + saawrite(0, SAA7146_MC2); + saawrite(0, SAA7146_IER); + saawrite(0xffffffffUL, SAA7146_ISR); +#if 0 + /* unregister i2c_bus */ + i2c_unregister_bus((&saa->i2c)); +#endif + + /* disable PCI bus-mastering */ + pci_read_config_byte(saa->dev, PCI_COMMAND, &command); + /* Should this be &=~ ?? */ + command &= ~PCI_COMMAND_MASTER; + pci_write_config_byte(saa->dev, PCI_COMMAND, command); + /* unmap and free memory */ + saa->audhead = saa->audtail = saa->osdhead = 0; + saa->vidhead = saa->vidtail = saa->osdtail = 0; + if (saa->vidbuf) + vfree(saa->vidbuf); + if (saa->audbuf) + vfree(saa->audbuf); + if (saa->osdbuf) + vfree(saa->osdbuf); + if (saa->dmavid2) + kfree((void *) saa->dmavid2); + saa->audbuf = saa->vidbuf = saa->osdbuf = NULL; + saa->dmavid2 = NULL; + if (saa->dmadebi) + kfree((void *) saa->dmadebi); + if (saa->dmavid1) + kfree((void *) saa->dmavid1); + if (saa->dmavid2) + kfree((void *) saa->dmavid2); + if (saa->dmavid3) + kfree((void *) saa->dmavid3); + if (saa->dmaa1in) + kfree((void *) saa->dmaa1in); + if (saa->dmaa1out) + kfree((void *) saa->dmaa1out); + if (saa->dmaa2in) + kfree((void *) saa->dmaa2in); + if (saa->dmaa2out) + kfree((void *) saa->dmaa2out); + if (saa->dmaRPS1) + kfree((void *) saa->dmaRPS1); + if (saa->dmaRPS2) + kfree((void *) saa->dmaRPS2); + free_irq(saa->irq, saa); + if (saa->saa7146_mem) + iounmap(saa->saa7146_mem); + if (saa->video_dev.minor != -1) + video_unregister_device(&saa->video_dev); + } +} + +#ifdef MODULE +int init_module(void) +{ +#else +int init_stradis_cards(struct video_init *unused) +{ +#endif + struct pci_dev *dev = pci_devices; + int result = 0, i; + u32 newcard; + + saa_num = 0; + + while (dev) { + if (dev->vendor == PCI_VENDOR_ID_PHILIPS) + if (dev->device == PCI_DEVICE_ID_PHILIPS_SAA7146) { + pci_read_config_dword(dev, + PCI_SUBSYSTEM_VENDOR_ID, &newcard); + if (!newcard) + printk(KERN_INFO "stradis%d: rev1 decoder\n", saa_num); + else + printk(KERN_INFO "stradis%d: SDM2xx found\n", saa_num); + result = configure_saa7146(dev, saa_num++); + } + if (result) + return result; + dev = dev->next; + } + if (saa_num) + printk(KERN_INFO "stradis: %d card(s) found.\n", saa_num); + else + return -EINVAL; + for (i = 0; i < saa_num; i++) + if (init_saa7146(i) < 0) { + release_saa(); + return -EIO; + } + return 0; +} + +#ifdef MODULE +void cleanup_module(void) +{ + release_saa(); + printk(KERN_INFO "stradis: module cleanup complete\n"); +} + +#endif diff --git a/drivers/char/videodev.c b/drivers/char/videodev.c index 5f02b26e1ad5..05f2eeeeaead 100644 --- a/drivers/char/videodev.c +++ b/drivers/char/videodev.c @@ -60,6 +60,9 @@ static struct video_init video_init_list[]={ {"i2c-tuner", i2c_tuner_init}, {"bttv", init_bttv_cards}, #endif +#ifdef CONFIG_VIDEO_STRADIS + {"stradis", init_stradis_cards}, +#endif #ifdef CONFIG_VIDEO_BWQCAM {"bw-qcam", init_bw_qcams}, #endif diff --git a/drivers/i2o/README b/drivers/i2o/README index de2d393b31da..4efb923fb7b3 100644 --- a/drivers/i2o/README +++ b/drivers/i2o/README @@ -9,13 +9,13 @@ AUTHORS (so far) -Alan Cox, Building Number Three Ltd. +Alan Cox, Building Number Three Ltd. Core code, SCSI and Block OSMs -Steve Ralston, LSI Logic Corp. +Steve Ralston, LSI Logic Corp. Debugging SCSI and Block OSM -Deepak Saxena, Intel Corp. +Deepak Saxena, Intel Corp. /proc interface, bug fixes Ioctl interfaces for control Debugging LAN OSM @@ -23,18 +23,21 @@ Deepak Saxena, Intel Corp. Philip Rumpf Fixed assorted dumb SMP locking bugs -Juha Sievanen, University of Helsinki Finland +Juha Sievanen, University of Helsinki Finland LAN OSM code /proc interface to LAN class Bug fixes Core code extensions -Auvo Häkkinen, University of Helsinki Finland +Auvo Häkkinen, University of Helsinki Finland LAN OSM code /Proc interface to LAN class Bug fixes Core code extensions +Taneli Vähäkangas, University of Helsinki Finland + Fixes to i2o_config + CREDITS This work was made possible by @@ -75,6 +78,7 @@ o Long term message flow control o PCI IOP's without interrupts are not supported yet o Push FAIL handling into the core o DDM control interfaces for module load etc +o Event handling Block: o Real error handler @@ -87,7 +91,8 @@ SCSI: o Find the right way to associate drives/luns/busses Lan: Batch mode sends - Fix the "killing interrupt handler" in i2o_set_multicast_list + Performance tuning + Event handling Tape: o Anyone seen anything implementing this ? diff --git a/drivers/i2o/README.ioctl b/drivers/i2o/README.ioctl index 49f34c078db7..3c1dd462ecfe 100644 --- a/drivers/i2o/README.ioctl +++ b/drivers/i2o/README.ioctl @@ -208,18 +208,16 @@ VIII. Downloading Software DESCRIPTION - This function downloads the software pointed by sw->buf to the - iop identified by sw->iop. The DownloadFlags, SwID, SwType and SwSize - fields of the ExecSwDownload message are filled in with the values of - sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen). - - Once the ioctl() is called and software transfer begins, the - user can read the value *(sw->maxfrag) and *(sw->curfrag) to - determine the status of the software transfer. As the IOP - is very slow when it comes to SW transfers, this can be - used by a separate thread to report status to the user. The - user _should not_ write to this memory location until the ioctl() - has returned. + This function downloads a software fragment pointed by sw->buf + to the iop identified by sw->iop. The DownloadFlags, SwID, SwType + and SwSize fields of the ExecSwDownload message are filled in with + the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen). + + The fragments _must_ be sent in order and be 8K in size. The last + fragment _may_ be shorter, however. The kernel will compute its + size based on information in the sw->swlen field. + + Please note that SW transfers can take a long time. RETURNS @@ -234,7 +232,7 @@ VIII. Downloading Software IX. Uploading Software SYNOPSIS - + ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw); struct i2o_sw_xfer @@ -251,19 +249,17 @@ IX. Uploading Software DESCRIPTION - This function uploads software from the IOP identified by sw->iop - and places it in the buffer pointed to by sw->buf. The length of the - buffer is given in *(sw->swlen). The UploadFlags, SwID and SwType - fields of the ExecSwUpload message are filled in - with the values of sw->flags, sw->sw_id and sw->sw_type. - - Once the ioctl() is called and software transfer begins, the - user can read the value *(sw->maxfrag) and *(sw->curfrag) to - determine the status of the software transfer. As the IOP - is very slow when it comes to SW transfers, this can be - used by a separate thread to report status to the user. The - user _should not_ write to this memory location until the ioctl() - has returned. + This function uploads a software fragment from the IOP identified + by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields. + The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload + message are filled in with the values of sw->flags, sw->sw_id, + sw->sw_type and *(sw->swlen). + + The fragments _must_ be requested in order and be 8K in size. The + user is responsible for allocating memory pointed by sw->buf. The + last fragment _may_ be shorter. + + Please note that SW transfers can take a long time. RETURNS diff --git a/drivers/i2o/i2o_config.c b/drivers/i2o/i2o_config.c index c8682f077b2a..96d9c17e17ae 100644 --- a/drivers/i2o/i2o_config.c +++ b/drivers/i2o/i2o_config.c @@ -11,7 +11,11 @@ * - Added software download ioctl (still testing) * Modified 09/10/1999 by Auvo Häkkinen * - Changes to i2o_cfg_reply(), ioctl_parms() - * - Added ioct_validate() (not yet tested) + * - Added ioct_validate() + * Modified 09/30/1999 by Taneli Vähäkangas + * - Fixed ioctl_swdl() + * Modified 10/04/1999 by Taneli Vähäkangas + * - Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -33,8 +37,6 @@ #include #include -#include "i2o_proc.h" - static int i2o_cfg_token = 0; static int i2o_cfg_context = -1; static void *page_buf; @@ -196,7 +198,7 @@ int ioctl_gethrt(unsigned long arg) struct i2o_controller *c; struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg; struct i2o_cmd_hrtlct kcmd; - pi2o_hrt hrt; + i2o_hrt *hrt; int len; u32 reslen; int ret = 0; @@ -214,7 +216,7 @@ int ioctl_gethrt(unsigned long arg) if(!c) return -ENXIO; - hrt = (pi2o_hrt)c->hrt; + hrt = (i2o_hrt *)c->hrt; i2o_unlock_controller(c); @@ -235,7 +237,7 @@ int ioctl_getlct(unsigned long arg) struct i2o_controller *c; struct i2o_cmd_hrtlct *cmd = (struct i2o_cmd_hrtlct*)arg; struct i2o_cmd_hrtlct kcmd; - pi2o_lct lct; + i2o_lct *lct; int len; int ret = 0; u32 reslen; @@ -253,7 +255,7 @@ int ioctl_getlct(unsigned long arg) if(!c) return -ENXIO; - lct = (pi2o_lct)c->lct; + lct = (i2o_lct *)c->lct; i2o_unlock_controller(c); len = (unsigned int)lct->table_size << 2; @@ -317,14 +319,14 @@ static int ioctl_parms(unsigned long arg, unsigned int type) return -ENOMEM; } - len = i2o_issue_params(i2o_cmd, c, kcmd.tid, - ops, kcmd.oplen, res, 65536); + len = i2o_issue_params(i2o_cmd, c, kcmd.tid, + ops, kcmd.oplen, res, sizeof(res)); i2o_unlock_controller(c); kfree(ops); - if (len) { + if (len < 0) { kfree(res); - return len; /* -DetailedStatus || -ETIMEDOUT */ + return len; /* -DetailedStatus */ } put_user(len, kcmd.reslen); @@ -414,7 +416,7 @@ int ioctl_html(unsigned long arg) } token = i2o_post_wait(c, msg, 9*4, 10); - if(token) + if(token != I2O_POST_WAIT_OK) { i2o_unlock_controller(c); kfree(res); @@ -437,139 +439,175 @@ int ioctl_html(unsigned long arg) return ret; } - + int ioctl_swdl(unsigned long arg) { struct i2o_sw_xfer kxfer; struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg; - unsigned char maxfrag = 0, curfrag = 0; - unsigned char buffer[8192]; + unsigned char maxfrag = 0, curfrag = 1; + unsigned char *buffer; u32 msg[9]; - unsigned int token = 0, diff = 0, swlen = 0, swxfer = 0; + unsigned int status = 0, swlen = 0, fragsize = 8192; struct i2o_controller *c; - int foo = 0; - printk("*** foo%d ***\n", foo++); if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) - { - printk( "i2o_config: can't copy i2o_sw cmd @ %p\n", pxfer); return -EFAULT; - } - printk("*** foo%d ***\n", foo++); - printk("Attempting to copy swlen from %p\n", kxfer.swlen); if(get_user(swlen, kxfer.swlen) < 0) - { - printk( "i2o_config: can't copy swlen\n"); return -EFAULT; - } - printk("*** foo%d ***\n", foo++); - maxfrag = swlen >> 13; // Transfer in 8k fragments - - printk("Attempting to write maxfrag @ %p\n", kxfer.maxfrag); - if(put_user(maxfrag, kxfer.maxfrag) < 0) - { - printk( "i2o_config: can't write maxfrag\n"); + if(get_user(maxfrag, kxfer.maxfrag) < 0) return -EFAULT; - } - printk("*** foo%d ***\n", foo++); - printk("Attempting to write curfrag @ %p\n", kxfer.curfrag); - if(put_user(curfrag, kxfer.curfrag) < 0) - { - printk( "i2o_config: can't write curfrag\n"); + if(get_user(curfrag, kxfer.curfrag) < 0) return -EFAULT; - } - printk("*** foo%d ***\n", foo++); - if(!kxfer.buf) - { - printk( "i2o_config: NULL software buffer\n"); + if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192; + + if(!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize)) return -EFAULT; - } - printk("*** foo%d ***\n", foo++); - // access_ok doesn't check for NULL... - if(!access_ok(VERIFY_READ, kxfer.buf, swlen)) - { - printk( "i2o_config: Cannot read sw buffer\n"); - return -EFAULT; - } - printk("*** foo%d ***\n", foo++); - c = i2o_find_controller(kxfer.iop); if(!c) return -ENXIO; - printk("*** foo%d ***\n", foo++); + + buffer=kmalloc(fragsize, GFP_KERNEL); + if (buffer==NULL) + { + i2o_unlock_controller(c); + return -ENOMEM; + } + __copy_from_user(buffer, kxfer.buf, fragsize); msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7; msg[1]= I2O_CMD_SW_DOWNLOAD<<24 | HOST_TID<<12 | ADAPTER_TID; msg[2]= (u32)cfg_handler.context; msg[3]= 0; - msg[4]= ((u32)kxfer.flags)<<24|((u32)kxfer.sw_type)<<16|((u32)maxfrag)<<8|((u32)curfrag); + msg[4]= (((u32)kxfer.flags)<<24) | (((u32)kxfer.sw_type)<<16) | + (((u32)maxfrag)<<8) | (((u32)curfrag)); msg[5]= swlen; msg[6]= kxfer.sw_id; - msg[7]= (0xD0000000 | 8192); + msg[7]= (0xD0000000 | fragsize); msg[8]= virt_to_phys(buffer); - printk("*** foo%d ***\n", foo++); - - // - // Loop through all fragments but last and transfer them... - // We already checked memory, so from now we assume it's all good - // - for(curfrag = 0; curfrag < maxfrag-1; curfrag++) - { - printk("Transfering fragment %d\n", curfrag); +// printk("i2o_config: swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_post_wait(c, msg, sizeof(msg), 60); - msg[4] |= (u32)curfrag; - - __copy_from_user(buffer, kxfer.buf, 8192); - swxfer += 8192; - - // Yes...that's one minute, but the spec states that - // transfers take a long time, and I've seen just how - // long they can take. - token = i2o_post_wait(c, msg, sizeof(msg), 60); - if (token) // Something very wrong - { - i2o_unlock_controller(c); - printk("Timeout downloading software"); - return -ETIMEDOUT; - } - - __put_user(curfrag, kxfer.curfrag); - } - - // Last frag is special case since it's not exactly 8K - diff = swlen - swxfer; - msg[4] |= (u32)maxfrag; - msg[7] = (0xD0000000 | diff); - __copy_from_user(buffer, kxfer.buf, 8192); - token = i2o_post_wait(c, msg, sizeof(msg), 60); - if(token) // Something very wrong + i2o_unlock_controller(c); + kfree(buffer); + + if (status != I2O_POST_WAIT_OK) { - i2o_unlock_controller(c); - printk("Timeout downloading software"); + // it fails if you try and send frags out of order + // and for some yet unknown reasons too + printk("i2o_config: swdl failed, DetailedStatus = %d\n", status); return -ETIMEDOUT; } - __put_user(curfrag, kxfer.curfrag); - i2o_unlock_controller(c); return 0; } -/* To be written */ int ioctl_swul(unsigned long arg) { - return -EINVAL; + struct i2o_sw_xfer kxfer; + struct i2o_sw_xfer *pxfer = (struct i2o_sw_xfer *)arg; + unsigned char maxfrag = 0, curfrag = 1; + unsigned char *buffer; + u32 msg[9]; + unsigned int status = 0, swlen = 0, fragsize = 8192; + struct i2o_controller *c; + + if(copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if(get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + if(get_user(maxfrag, kxfer.maxfrag) < 0) + return -EFAULT; + + if(get_user(curfrag, kxfer.curfrag) < 0) + return -EFAULT; + + if(curfrag==maxfrag) fragsize = swlen-(maxfrag-1)*8192; + + if(!kxfer.buf || !access_ok(VERIFY_WRITE, kxfer.buf, fragsize)) + return -EFAULT; + + c = i2o_find_controller(kxfer.iop); + if(!c) + return -ENXIO; + + buffer=kmalloc(fragsize, GFP_KERNEL); + if (buffer==NULL) + { + i2o_unlock_controller(c); + return -ENOMEM; + } + + msg[0]= NINE_WORD_MSG_SIZE | SGL_OFFSET_7; + msg[1]= I2O_CMD_SW_UPLOAD<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2]= (u32)cfg_handler.context; + msg[3]= 0; + msg[4]= (u32)kxfer.flags<<24|(u32)kxfer.sw_type<<16|(u32)maxfrag<<8|(u32)curfrag; + msg[5]= swlen; + msg[6]= kxfer.sw_id; + msg[7]= (0xD0000000 | fragsize); + msg[8]= virt_to_bus(buffer); + +// printk("i2o_config: swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize); + status = i2o_post_wait(c, msg, sizeof(msg), 60); + i2o_unlock_controller(c); + + if (status != I2O_POST_WAIT_OK) + { + kfree(buffer); + printk("i2o_config: swul failed, DetailedStatus = %d\n", status); + return -ETIMEDOUT; + } + + __copy_to_user(kxfer.buf, buffer, fragsize); + kfree(buffer); + + return 0; } -/* To be written */ int ioctl_swdel(unsigned long arg) { - return -EINVAL; + struct i2o_controller *c; + struct i2o_sw_xfer kxfer, *pxfer = (struct i2o_sw_xfer *)arg; + u32 msg[7]; + unsigned int swlen; + int token; + + if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer))) + return -EFAULT; + + if (get_user(swlen, kxfer.swlen) < 0) + return -EFAULT; + + c = i2o_find_controller(kxfer.iop); + if (!c) + return -ENXIO; + + msg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0; + msg[1] = I2O_CMD_SW_REMOVE<<24 | HOST_TID<<12 | ADAPTER_TID; + msg[2] = (u32)i2o_cfg_context; + msg[3] = 0; + msg[4] = (u32)kxfer.flags<<24 | (u32)kxfer.sw_type<<16; + msg[5] = swlen; + msg[6] = kxfer.sw_id; + + token = i2o_post_wait(c, msg, sizeof(msg), 10); + i2o_unlock_controller(c); + + if (token != I2O_POST_WAIT_OK) + { + printk("i2o_config: swdel failed, DetailedStatus = %d\n", token); + return -ETIMEDOUT; + } + + return 0; } int ioctl_validate(unsigned long arg) @@ -591,7 +629,7 @@ int ioctl_validate(unsigned long arg) token = i2o_post_wait(c, msg, sizeof(msg), 10); i2o_unlock_controller(c); - if (token) + if (token != I2O_POST_WAIT_OK) { printk("Can't validate configuration, ErrorStatus = %d\n", token); @@ -644,7 +682,7 @@ int init_module(void) int __init i2o_config_init(void) #endif { - printk(KERN_INFO "i2o configuration manager v 0.02\n"); + printk(KERN_INFO "i2o configuration manager v 0.03\n"); if((page_buf = kmalloc(4096, GFP_KERNEL))==NULL) { diff --git a/drivers/i2o/i2o_core.c b/drivers/i2o/i2o_core.c index c8a6db4a4ddd..8642540c0588 100644 --- a/drivers/i2o/i2o_core.c +++ b/drivers/i2o/i2o_core.c @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -927,7 +928,7 @@ static int i2o_parse_lct(struct i2o_controller *c) u32 *p; struct i2o_device *d; char str[22]; - pi2o_lct lct = c->lct; + i2o_lct *lct = c->lct; max = lct->table_size; @@ -1168,6 +1169,9 @@ static int i2o_reset_controller(struct i2o_controller *c) /* Wait for a reply */ time=jiffies; + + /* DPT driver claims they need this */ + mdelay(5); #ifdef DRIVERDEBUG printk(KERN_INFO "Reset posted, waiting...\n"); @@ -1192,7 +1196,7 @@ static int i2o_reset_controller(struct i2o_controller *c) { /* * Once the reset is sent, the IOP goes into the INIT state - * which is inditerminate. We need to wait until the IOP + * which is indeterminate. We need to wait until the IOP * has rebooted before we can let the system talk to * it. We read the inbound Free_List until a message is * available. If we can't read one in the given ammount of @@ -1230,6 +1234,7 @@ int i2o_status_get(struct i2o_controller *c) u32 m; u32 *msg; u8 *status_block; + int i; #ifdef DRIVERDEBUG printk(KERN_INFO "Getting status block for iop%d\n", c->unit); @@ -1238,7 +1243,7 @@ int i2o_status_get(struct i2o_controller *c) kfree(c->status_block); c->status_block = - (pi2o_status_block)kmalloc(sizeof(i2o_status_block),GFP_KERNEL); + (i2o_status_block *)kmalloc(sizeof(i2o_status_block),GFP_KERNEL); if(c->status_block == NULL) { #ifdef DRIVERDEBUG @@ -1248,45 +1253,53 @@ int i2o_status_get(struct i2o_controller *c) } status_block = (u8*)c->status_block; + + for(i=0;i<5;i++) + { + m=i2o_wait_message(c, "StatusGet"); + if(m==0xFFFFFFFF) + return -ETIMEDOUT; + + memset(status_block, 0, sizeof(i2o_status_block)); + + msg=(u32 *)(c->mem_offset+m); + + __raw_writel(NINE_WORD_MSG_SIZE|SGL_OFFSET_0, &msg[0]); + __raw_writel(I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID, &msg[1]); + __raw_writel(0, &msg[2]); + __raw_writel(0, &msg[3]); + __raw_writel(0, &msg[4]); + __raw_writel(0, &msg[5]); + __raw_writel(virt_to_bus(c->status_block), &msg[6]); + __raw_writel(0, &msg[7]); /* 64bit host FIXME */ + __raw_writel(sizeof(i2o_status_block), &msg[8]); + + printk("SB is %d bytes.\n", sizeof(i2o_status_block)); - m=i2o_wait_message(c, "StatusGet"); - if(m==0xFFFFFFFF) - return -ETIMEDOUT; - - msg=(u32 *)(c->mem_offset+m); - - msg[0]=NINE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1]=I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID; - msg[2]=core_context; - msg[3]=0; - msg[4]=0; - msg[5]=0; - msg[6]=virt_to_phys(c->status_block); - msg[7]=0; /* 64bit host FIXME */ - msg[8]=88; - - i2o_post_message(c,m); - - /* Wait for a reply */ - time=jiffies; + i2o_post_message(c,m); + + /* DPT work around */ + mdelay(5); - while(status_block[87]!=0xFF) - { - if((jiffies-time)>=5*HZ) + /* Wait for a reply */ + time=jiffies; + + while((jiffies-time)<=HZ) { + if(status_block[87]!=0) + { + /* Ok the reply has arrived. Fill in the important stuff */ + c->inbound_size = (status_block[12]|(status_block[13]<<8))*4; + return 0; + } + schedule(); + barrier(); + } #ifdef DRIVERDEBUG - printk(KERN_ERR "IOP get status timeout.\n"); + printk(KERN_ERR "IOP get status timeout.\n"); #endif - return -ETIMEDOUT; - } - schedule(); - barrier(); } - - /* Ok the reply has arrived. Fill in the important stuff */ - c->inbound_size = (status_block[12]|(status_block[13]<<8))*4; - - return 0; + return 0;//-ETIMEDOUT; } @@ -1354,7 +1367,7 @@ static int i2o_systab_send(struct i2o_controller* iop) */ static void __init i2o_sys_init() { - struct i2o_controller *iop; + struct i2o_controller *iop, *niop; int ret; u32 m; @@ -1362,18 +1375,30 @@ static void __init i2o_sys_init() printk(KERN_INFO "This may take a few minutes if there are many devices\n"); /* Get the status for each IOP */ - for(iop = i2o_controller_chain; iop; iop = iop->next) + for(iop = i2o_controller_chain; iop; iop = niop) { + niop = iop->next; #ifdef DRIVERDEBUG printk(KERN_INFO "Getting initial status for iop%d\n", iop->unit); #endif - i2o_status_get(iop); + if(i2o_status_get(iop)<0) + { + printk("Unable to obtain status of IOP, attempting a reset.\n"); + i2o_reset_controller(iop); + if(i2o_status_get(iop)<0) + { + printk("IOP not responding.\n"); + i2o_delete_controller(iop); + continue; + } + } if(iop->status_block->iop_state == ADAPTER_STATE_FAULTED) { printk(KERN_CRIT "i2o: iop%d has hardware fault\n", iop->unit); i2o_delete_controller(iop); + continue; } if(iop->status_block->iop_state == ADAPTER_STATE_HOLD || @@ -1384,7 +1409,7 @@ static void __init i2o_sys_init() int msg[256]; #ifdef DRIVERDEBUG - printk(KERN_INFO "iop%d already running...trying to reboot", + printk(KERN_INFO "iop%d already running...trying to reboot\n", iop->unit); #endif i2o_init_outbound_q(iop); @@ -1396,6 +1421,7 @@ static void __init i2o_sys_init() { printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit); i2o_delete_controller(iop); + continue; } } } @@ -1403,9 +1429,11 @@ static void __init i2o_sys_init() /* * Now init the outbound queue for each one. */ - for(iop = i2o_controller_chain; iop; iop = iop->next) + for(iop = i2o_controller_chain; iop; iop = niop) { int i; + + niop = iop->next; if((ret=i2o_init_outbound_q(iop))) { @@ -1413,6 +1441,7 @@ static void __init i2o_sys_init() "IOP%d initialization failed: Could not initialize outbound q\n", iop->unit); i2o_delete_controller(iop); + continue; } iop->page_frame = kmalloc(MSG_POOL_SIZE, GFP_KERNEL); @@ -1438,18 +1467,20 @@ static void __init i2o_sys_init() /* * OK..parse the HRT */ - for(iop = i2o_controller_chain; iop; iop = iop->next) + for(iop = i2o_controller_chain; iop; iop = niop) { + niop = iop->next; if(i2o_hrt_get(iop)) { printk(KERN_CRIT "iop%d: Could not get HRT!\n", iop->unit); i2o_delete_controller(iop); - break; + continue; } if(i2o_parse_hrt(iop)) { printk(KERN_CRIT "iop%d: Could not parse HRT!\n", iop->unit); i2o_delete_controller(iop); + continue; } } @@ -1466,15 +1497,17 @@ static void __init i2o_sys_init() return; } - for(iop = i2o_controller_chain; iop; iop = iop->next) + for(iop = i2o_controller_chain; iop; iop = niop) #ifdef DRIVERDEBUG { + niop = iop->next; printk(KERN_INFO "Sending system table to iop%d\n", iop->unit); #endif if(i2o_systab_send(iop)) { printk(KERN_CRIT "iop%d: Error sending system table\n", iop->unit); i2o_delete_controller(iop); + continue; } #ifdef DRIVERDEBUG } @@ -1483,8 +1516,9 @@ static void __init i2o_sys_init() /* * Enable */ - for(iop = i2o_controller_chain; iop; iop = iop->next) + for(iop = i2o_controller_chain; iop; iop = niop) { + niop = iop->next; #ifdef DRIVERDEBUG printk(KERN_INFO "Enableing iop%d\n", iop->unit); #endif @@ -1492,14 +1526,16 @@ static void __init i2o_sys_init() { printk(KERN_ERR "Could not enable iop%d\n", iop->unit); i2o_delete_controller(iop); + continue; } } /* * OK..one last thing and we're ready to go! */ - for(iop = i2o_controller_chain; iop; iop = iop->next) + for(iop = i2o_controller_chain; iop; iop = niop) { + niop = iop->next; #ifdef DRIVERDEBUG printk(KERN_INFO "Getting LCT for iop%d\n", iop->unit); #endif @@ -1507,6 +1543,7 @@ static void __init i2o_sys_init() { printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit); i2o_delete_controller(iop); + continue; } else i2o_parse_lct(iop); @@ -1667,7 +1704,7 @@ int i2o_init_outbound_q(struct i2o_controller *c) msg[4]= 4096; /* Host page frame size */ msg[5]= MSG_FRAME_SIZE<<16|0x80; /* Outbound msg frame size and Initcode */ msg[6]= 0xD0000004; /* Simple SG LE, EOB */ - msg[7]= virt_to_phys(workspace); + msg[7]= virt_to_bus(workspace); *((u32 *)workspace)=0; /* @@ -1685,7 +1722,6 @@ int i2o_init_outbound_q(struct i2o_controller *c) { printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n", c->unit); - kfree(workspace); return -ETIMEDOUT; } schedule(); @@ -2419,7 +2455,7 @@ static void i2o_report_util_cmd(u8 cmd) case I2O_CMD_UTIL_DEVICE_RELEASE: printk("UTIL_DEVICE_RELEASE, "); break; - case I2O_CMD_UTIL_ACK: + case I2O_CMD_UTIL_EVT_ACK: printk("UTIL_EVENT_ACKNOWLEDGE, "); break; case I2O_CMD_UTIL_EVT_REGISTER: diff --git a/drivers/i2o/i2o_lan.c b/drivers/i2o/i2o_lan.c index 60798606a4e0..c9516286333d 100644 --- a/drivers/i2o/i2o_lan.c +++ b/drivers/i2o/i2o_lan.c @@ -1,7 +1,7 @@ /* * linux/drivers/i2o/i2o_lan.c * - * I2O LAN CLASS OSM Prototyping, September 17th 1999 + * I2O LAN CLASS OSM Prototyping, November 8th 1999 * * (C) Copyright 1999 University of Helsinki, * Department of Computer Science @@ -11,7 +11,7 @@ * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. + * 2 of the License, or (at your option) any later version. * * Authors: Auvo Häkkinen * Juha Sievänen @@ -20,9 +20,7 @@ * Tested: in FDDI environment (using SysKonnect's DDM) * in Ethernet environment (using Intel 82558 DDM proto) * - * TODO: batch mode networking - * - we've not been able to test batch replies and - * batch receives + * TODO: batch mode sends * error checking / timeouts * code / test for other LAN classes */ @@ -39,6 +37,7 @@ #include #include #include +#include #include #include @@ -46,68 +45,65 @@ #include #include "i2o_lan.h" -//#define DRIVERDEBUG +#define DRIVERDEBUG #ifdef DRIVERDEBUG #define dprintk(s, args...) printk(s, ## args) #else #define dprintk(s, args...) #endif -#define MAX_LAN_CARDS 4 +/* Module params */ + +static u32 bucketpost = I2O_BUCKET_COUNT; +static u32 bucketthresh = I2O_BUCKET_THRESH; +static u32 rx_copybreak = 200; + +#define MAX_LAN_CARDS 16 static struct net_device *i2o_landevs[MAX_LAN_CARDS+1]; static int unit = -1; /* device unit number */ struct i2o_lan_local { u8 unit; struct i2o_device *i2o_dev; - int reply_flag; /* needed by scalar/table queries */ - struct fddi_statistics stats; /* see also struct net_device_stats */ + struct fddi_statistics stats; /* see also struct net_device_stats */ unsigned short (*type_trans)(struct sk_buff *, struct net_device *); - /* - * Due to way that interrupts can pile up, we need to keep track - * of buckets ourselves. Otherwise we'll end up flooding - * the DDM with buckets. - */ - u32 bucket_count; - - /* - * Keep track of no. of outstanding TXes - */ - u32 tx_count; - u32 max_tx; - u32 tx_full; - - spinlock_t lock; + u32 bucket_count; /* nbr of buckets sent to DDM */ + u32 tx_count; /* nbr of outstanding TXes */ + u32 max_tx; /* DDM's Tx queue len */ + spinlock_t lock; }; -/* function prototypes */ +static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, + struct i2o_message *m); +static void i2o_lan_event_reply(struct net_device *dev, u32 *msg); static int i2o_lan_receive_post(struct net_device *dev, u32 count); static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg); static void i2o_lan_release_buckets(struct net_device *dev, u32 *msg); -/* - * Module params - */ -static u32 bucketpost = I2O_BUCKET_COUNT; -static u32 bucketthresh = I2O_BUCKET_THRESH; -static u32 rx_copybreak = 200; +static struct i2o_handler i2o_lan_handler = { + i2o_lan_reply, + "I2O Lan OSM", + 0, // context + I2O_CLASS_LAN +}; +static int lan_context; -static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, + +static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_message *m) -{ +{ u32 *msg = (u32 *)m; u8 unit = (u8)(msg[2]>>16); // InitiatorContext struct net_device *dev = i2o_landevs[unit]; - if (msg[0] & (1<<13)) // Fail bit is set - { - printk(KERN_ERR "IOP failed to process the msg:\n"); + if (msg[0] & (1<<13)) { // Fail bit is set + printk(KERN_ERR "%s: IOP failed to process the msg:\n",dev->name); printk(KERN_ERR " Cmd = 0x%02X, InitiatorTid = %d, TargetTid = %d\n", (msg[1] >> 24) & 0xFF, (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF); printk(KERN_ERR " FailureCode = 0x%02X\n Severity = 0x%02X\n " "LowestVersion = 0x%02X\n HighestVersion = 0x%02X\n", - msg[4] >> 24, (msg[4] >> 16) & 0xFF, + msg[4] >> 24, (msg[4] >> 16) & 0xFF, (msg[4] >> 8) & 0xFF, msg[4] & 0xFF); printk(KERN_ERR " FailingHostUnit = 0x%04X\n FailingIOP = 0x%03X\n", msg[5] >> 16, msg[5] & 0xFFF); @@ -115,23 +111,21 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, } #ifndef DRIVERDEBUG - if (msg[4] >> 24) /* ReqStatus != SUCCESS */ + if (msg[4] >> 24) /* ReqStatus != SUCCESS */ #endif i2o_report_status(KERN_INFO, dev->name, msg); - + switch (msg[1] >> 24) { case LAN_RECEIVE_POST: { - if (dev->start) - { - if(!(msg[4]>>24)) - { + if (dev->start) { + if(!(msg[4]>>24)) { i2o_lan_receive_post_reply(dev,msg); break; } // Something VERY wrong if this is happening - printk( KERN_WARNING "i2olan: Device %s rejected bucket post\n", dev->name); + printk( KERN_WARNING "i2olan: Device %s rejected bucket post.\n", dev->name); } // Getting unused buckets back @@ -146,15 +140,16 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; u8 trl_count = msg[3] & 0x000000FF; - do { // The HDM has handled the outgoing packet + while (trl_count) { + // The HDM has handled the outgoing packet dev_kfree_skb((struct sk_buff *)msg[4 + trl_count]); - dprintk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n", + printk(KERN_INFO "%s: Request skb freed (trl_count=%d).\n", dev->name,trl_count); priv->tx_count--; - } while (--trl_count); + trl_count--; + } - if(dev->tbusy) - { + if (dev->tbusy) { clear_bit(0,(void*)&dev->tbusy); mark_bh(NET_BH); /* inform upper layers */ } @@ -162,45 +157,135 @@ static void i2o_lan_reply(struct i2o_handler *h, struct i2o_controller *iop, break; } - default: - if (msg[2] & 0x80000000) // reply to a UtilParamsGet/Set - { - int *flag = (int *)msg[3]; // flag for i2o_post_wait - if (msg[4] >> 24) // ReqStatus != SUCCESS - *flag = -(msg[4] & 0xFFFF); // DetailedStatus - else - *flag = I2O_POST_WAIT_OK; - } + case LAN_RESET: + case LAN_SUSPEND: + break; + + case I2O_CMD_UTIL_EVT_REGISTER: + case I2O_CMD_UTIL_EVT_ACK: + i2o_lan_event_reply(dev, msg); + break; + + default: + printk(KERN_ERR "%s: Sorry, no handler for the reply.\n", dev->name); + i2o_report_status(KERN_INFO, dev->name, msg); } } + +static void i2o_lan_event_reply(struct net_device *dev, u32 *msg) +{ + struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; + struct i2o_device *i2o_dev = priv->i2o_dev; + struct i2o_controller *iop = i2o_dev->controller; + struct i2o_reply { + u8 version_offset; + u8 msg_flags; + u16 msg_size; + u32 tid:12; + u32 initiator:12; + u32 function:8; + u32 initiator_context; + u32 transaction_context; + u32 evt_indicator; + u32 evt_data[(iop->inbound_size - 20) / 4]; /* max */ + } *evt = (struct i2o_reply *)msg; + + int evt_data_len = (evt->msg_size - 5) * 4; /* real */ + + if (evt->function == I2O_CMD_UTIL_EVT_REGISTER) { + printk(KERN_INFO "%s: I2O event - ", dev->name); + + switch (evt->evt_indicator) { + case I2O_EVT_IND_STATE_CHANGE: + printk("State chance 0x%08X.\n", + evt->evt_data[0]); + break; + case I2O_EVT_IND_GENERAL_WARNING: + printk("General warning 0x%02X.\n", + evt->evt_data[0]); + break; + case I2O_EVT_IND_CONFIGURATION_FLAG: + printk("Configuration requested.\n"); + break; + case I2O_EVT_IND_LOCK_RELEASE: + printk("Lock released.\n"); + break; + case I2O_EVT_IND_CAPABILITY_CHANGE: + printk("Capability change 0x%02X.\n", + evt->evt_data[0]); + break; + case I2O_EVT_IND_DEVICE_RESET: + printk("Device reset.\n"); + break; + case I2O_EVT_IND_EVT_MASK_MODIFIED: + printk("Event mask modified, 0x%08X.\n", + evt->evt_data[0]); + break; + case I2O_EVT_IND_FIELD_MODIFIED: { + u16 *work16 = (u16 *)evt->evt_data; + printk("Group 0x%04X, field %d changed.\n", + work16[0], work16[1]); + break; + } + case I2O_EVT_IND_VENDOR_EVT: { + int i; + printk("Vendor event:\n"); + for (i = 0; i < evt_data_len / 4; i++) + printk(" 0x%08X\n", evt->evt_data[i]); + break; + } + case I2O_EVT_IND_DEVICE_STATE: + printk("Device state changed 0x%08X.\n", + evt->evt_data[0]); + break; + case I2O_LAN_EVT_LINK_DOWN: + printk("Link to the physical device is lost.\n"); + break; + case I2O_LAN_EVT_LINK_UP: + printk("Link to the physical device is (re)established.\n"); + break; + case I2O_LAN_EVT_MEDIA_CHANGE: + printk("Media change.\n"); + break; + default: + printk("Event Indicator = 0x%08X.\n", + evt->evt_indicator); + } + + /* + * EventAck necessary only for events that cause the device + * to syncronize with the user + * + *if (i2o_event_ack(iop, i2o_dev->lct_data->tid, + * priv->unit << 16 | lan_context, + * evt->evt_indicator, + * evt->evt_data, evt_data_len) < 0) + * printk("%s: Event Acknowledge timeout.\n", dev->name); + */ + } + + /* else evt->function == I2O_CMD_UTIL_EVT_ACK) */ + /* Do we need to do something here too? */ +} + + void i2o_lan_release_buckets(struct net_device *dev, u32 *msg) { struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; u8 trl_count = (u8)(msg[3] & 0x000000FF); u32 *pskb = &msg[6]; - - while (trl_count) - { - dprintk("%s: Releasing unused sk_buff %p\n",dev->name, + + while (trl_count) { + dprintk("%s: Releasing unused sk_buff %p.\n",dev->name, (struct sk_buff*)(*pskb)); - dev_kfree_skb((struct sk_buff*)(*pskb)); + dev_kfree_skb((struct sk_buff*)(*pskb)); pskb++; priv->bucket_count--; trl_count--; } } -static struct i2o_handler i2o_lan_handler = -{ - i2o_lan_reply, - "I2O Lan OSM", - 0, // context - I2O_CLASS_LAN -}; -static int lan_context; - - static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg) { struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; @@ -210,25 +295,21 @@ static int i2o_lan_receive_post_reply(struct net_device *dev, u32 *msg) u8 trl_count = msg[3] & 0x000000FF; struct sk_buff *skb, *newskb; -static int n_calls = 0; -n_calls++; - #if 0 dprintk(KERN_INFO "TrlFlags = 0x%02X, TrlElementSize = %d, TrlCount = %d\n" - "msgsize = %d, buckets_remaining = %d\n", + "msgsize = %d, buckets_remaining = %d\n", msg[3]>>24, msg[3]&0x0000FF00, trl_count, msg[0]>>16, msg[5]); #endif - - while (trl_count--) - { + while (trl_count--) { skb = (struct sk_buff *)(bucket->context); packet = (struct i2o_packet_info *)bucket->packet_info; priv->bucket_count--; +#if 0 dprintk(KERN_INFO "Buckets_remaining = %d, bucket_count = %d, trl_count = %d\n", msg[5], priv->bucket_count, trl_count); -#if 0 - dprintk(KERN)INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n", + + dprintk(KERN_INFO "flags = 0x%02X, offset = 0x%06X, status = 0x%02X, length = %d\n", packet->flags, packet->offset, packet->status, packet->len); #endif if (packet->len < rx_copybreak) { @@ -241,15 +322,15 @@ n_calls++; newskb->protocol = priv->type_trans(newskb, dev); netif_rx(newskb); - dev_kfree_skb(skb); // FIXME: reuse this skb? + dev_kfree_skb(skb); // FIXME: reuse this skb? } else { - printk("I2OLAN-%s: Can't allocate skb.\n", dev->name); + printk("%s: Can't allocate skb.\n", dev->name); return -ENOMEM; } } else { skb_put(skb,packet->len); - skb->dev = dev; + skb->dev = dev; skb->protocol = priv->type_trans(skb, dev); netif_rx(skb); @@ -260,20 +341,17 @@ n_calls++; bucket++; // to next Packet Descriptor Block } - if (priv->bucket_count < bucketpost - bucketthresh) - i2o_lan_receive_post(dev, bucketpost - priv->bucket_count); - if ((msg[4] & 0x000000FF) == I2O_LAN_DSC_BUCKET_OVERRUN) - { - printk(KERN_INFO "%s: DDM out of buckets (count = %d)! " - "Number of posts = %d\n", dev->name, msg[5], n_calls); - n_calls = 0; - } + printk(KERN_INFO "%s: DDM out of buckets (count = %d)!\n", + dev->name, msg[5]); + + if (priv->bucket_count <= bucketpost - bucketthresh) + i2o_lan_receive_post(dev, bucketpost - priv->bucket_count); return 0; } -/* +/* * i2o_lan_receive_post(): Post buckets to receive packets. */ static int i2o_lan_receive_post(struct net_device *dev, u32 count) @@ -289,14 +367,12 @@ static int i2o_lan_receive_post(struct net_device *dev, u32 count) int n_elems = (iop->inbound_size - 16 ) / 12; /* msg header + SGLs */ u32 total = 0; int i; - - while (total < count) - { + + while (total < count) { m = I2O_POST_READ32(iop); if (m == 0xFFFFFFFF) return -ETIMEDOUT; - msg = bus_to_virt(iop->mem_offset + m); - + msg = (u32 *)(iop->mem_offset + m); bucket_count = (total + n_elems < count) ? n_elems : count - total; @@ -306,8 +382,7 @@ static int i2o_lan_receive_post(struct net_device *dev, u32 count) msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = bucket_count; // BucketCount - for (i = 0; i < bucket_count; i++) - { + for (i = 0; i < bucket_count; i++) { skb = dev_alloc_skb(bucket_len + 2); if (skb == NULL) return -ENOMEM; @@ -331,11 +406,11 @@ static int i2o_lan_receive_post(struct net_device *dev, u32 count) return 0; } -/* - * i2o_lan_reset(): Reset the LAN adapter into the operational state and +/* + * i2o_lan_reset(): Reset the LAN adapter into the operational state and * restore it to full operation. */ -static int i2o_lan_reset(struct net_device *dev) +static int i2o_lan_reset(struct net_device *dev) { struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; @@ -351,12 +426,12 @@ static int i2o_lan_reset(struct net_device *dev) if (i2o_post_this(iop, msg, sizeof(msg)) < 0) return -ETIMEDOUT; - return 0; + return 0; } -/* +/* * i2o_lan_suspend(): Put LAN adapter into a safe, non-active state. - * Reply to any LAN class message with status error_no_data_transfer + * Reply to any LAN class message with status error_no_data_transfer * / suspended. */ static int i2o_lan_suspend(struct net_device *dev) @@ -366,14 +441,14 @@ static int i2o_lan_suspend(struct net_device *dev) struct i2o_controller *iop = i2o_dev->controller; u32 msg[5]; - dprintk( "%s: LAN SUSPEND MESSAGE\n", dev->name ); + dprintk( "%s: LAN SUSPEND MESSAGE.\n", dev->name ); msg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0; msg[1] = LAN_SUSPEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid; msg[2] = priv->unit << 16 | lan_context; // InitiatorContext msg[3] = 0; // TransactionContext msg[4] = 1 << 16; // return posted buckets - if (i2o_post_this(iop, msg, sizeof(msg))< 0) + if (i2o_post_this(iop, msg, sizeof(msg)) < 0) return -ETIMEDOUT; return 0; @@ -385,9 +460,9 @@ static int i2o_lan_suspend(struct net_device *dev) static void i2o_set_batch_mode(struct net_device *dev) { -/* +/* * NOTE: we have not been able to test batch mode - * since HDMs we have, don't implement it + * since HDMs we have, don't implement it */ struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; @@ -400,11 +475,13 @@ static void i2o_set_batch_mode(struct net_device *dev) // enable batch mode, toggle automatically val = 0x00000000; // val = 0x00000001; // turn off batch mode - if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, 4) < 0) - printk(KERN_WARNING "Unable to enter I2O LAN batch mode.\n"); - else + if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0003, 0, &val, sizeof(val)) <0) + printk(KERN_WARNING "%s: Unable to enter I2O LAN batch mode.\n", + dev->name); + else dprintk(KERN_INFO "%s: I2O LAN batch mode enabled.\n",dev->name); // dprintk(KERN_INFO "%s: I2O LAN batch mode disabled.\n",dev->name); + /* * When PacketOrphanlimit is same as the maximum packet length, * the packets will never be split into two separate buckets @@ -413,31 +490,39 @@ static void i2o_set_batch_mode(struct net_device *dev) /* set LAN_OPERATION attributes */ val = dev->mtu + dev->hard_header_len; // PacketOrphanLimit - if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, 4)) - printk(KERN_WARNING "i2o_lan: Unable to set PacketOrphanLimit.\n"); + if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0004, 2, &val, sizeof(val)) < 0) + printk(KERN_WARNING "%s: Unable to set PacketOrphanLimit.\n", + dev->name); else - dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d\n", + dprintk(KERN_INFO "%s: PacketOrphanLimit set to %d.\n", dev->name,val); - + return; } -/* - * i2o_lan_open(): Open the device to send/receive packets via +/* + * i2o_lan_open(): Open the device to send/receive packets via * the network device. */ static int i2o_lan_open(struct net_device *dev) { struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; - struct i2o_device *i2o_dev = priv->i2o_dev; + struct i2o_device *i2o_dev = priv->i2o_dev; + struct i2o_controller *iop = i2o_dev->controller; + u32 evt_mask = 0xFFC00007; // All generic events, all lan evenst - if(i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) - { + if (i2o_claim_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) { printk(KERN_WARNING "%s: Unable to claim the I2O LAN device.\n", dev->name); return -EAGAIN; } - dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", dev->name, i2o_dev->lct_data->tid); - + dprintk(KERN_INFO "%s: I2O LAN device claimed (tid=%d).\n", + dev->name, i2o_dev->lct_data->tid); +#if 0 + if (i2o_event_register(iop, i2o_dev->lct_data->tid, + priv->unit << 16 | lan_context, evt_mask) < 0) + printk(KERN_WARNING "%s: Unable to set the event mask.\n", + dev->name); +#endif i2o_lan_reset(dev); dev->tbusy = 0; @@ -453,19 +538,26 @@ static int i2o_lan_open(struct net_device *dev) /* * i2o_lan_close(): End the transfering. - */ + */ static int i2o_lan_close(struct net_device *dev) { struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; - +//#if 0 + struct i2o_controller *iop = i2o_dev->controller; + + if (i2o_event_register(iop, i2o_dev->lct_data->tid, + priv->unit << 16 | lan_context, 0) < 0) + printk(KERN_WARNING "%s: Unable to clear the event mask.\n", + dev->name); +//#endif dev->tbusy = 1; dev->start = 0; i2o_lan_suspend(dev); - if(i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) + if (i2o_release_device(i2o_dev, &i2o_lan_handler, I2O_CLAIM_PRIMARY)) printk(KERN_WARNING "%s: Unable to unclaim I2O LAN device " - "(tid=%d)\n", dev->name, i2o_dev->lct_data->tid); + "(tid=%d).\n", dev->name, i2o_dev->lct_data->tid); MOD_DEC_USE_COUNT; @@ -473,9 +565,9 @@ static int i2o_lan_close(struct net_device *dev) } #if 0 -/* +/* * i2o_lan_sdu_send(): Send a packet, MAC header added by the HDM. - * Must be supported by Fibre Channel, optional for Ethernet/802.3, + * Must be supported by Fibre Channel, optional for Ethernet/802.3, * Token Ring, FDDI */ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev) @@ -484,12 +576,12 @@ static int i2o_lan_sdu_send(struct sk_buff *skb, struct net_device *dev) } #endif -/* +/* * i2o_lan_packet_send(): Send a packet as is, including the MAC header. - * - * Must be supported by Ethernet/802.3, Token Ring, FDDI, optional for + * + * Must be supported by Ethernet/802.3, Token Ring, FDDI, optional for * Fibre Channel - */ + */ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev) { struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; @@ -498,14 +590,13 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev) u32 m, *msg; u32 flags = 0; - /* + /* * Keep interrupt from changing dev->tbusy from underneath us * (Do we really need to do this?) */ spin_lock_irqsave(&priv->lock, flags); - if(test_and_set_bit(0,(void*)&dev->tbusy) != 0) - { + if(test_and_set_bit(0,(void*)&dev->tbusy) != 0) { spin_unlock_irqrestore(&priv->lock, flags); return 1; } @@ -515,9 +606,19 @@ static int i2o_lan_packet_send(struct sk_buff *skb, struct net_device *dev) spin_unlock_irqrestore(&priv->lock, flags); dev_kfree_skb(skb); return -ETIMEDOUT; - } - msg = bus_to_virt(iop->mem_offset + m); - + } + msg = (u32 *)(iop->mem_offset + m); + +#if 0 + __raw_writel(SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4,&msg[0]); + __raw_writel(LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid, &msg[1]); + __raw_writel(priv->unit << 16 | lan_context, &msg[2]); // InitiatorContext + __raw_writel(1 << 4, &msg[3]); // TransmitControlWord + __raw_writel(0xD5000000 | skb->len, &msg[4]); // MAC hdr included + __raw_writel((u32)skb, &msg[5]); // TransactionContext + __raw_writel(virt_to_bus(skb->data),&msg[6]); +#endif + msg[0] = SEVEN_WORD_MSG_SIZE | 1<<12 | SGL_OFFSET_4; msg[1] = LAN_PACKET_SEND<<24 | HOST_TID<<12 | i2o_dev->lct_data->tid; msg[2] = priv->unit << 16 | lan_context; // IntiatorContext @@ -552,8 +653,8 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) u64 val64[16]; u64 supported_group[4] = { 0, 0, 0, 0 }; - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, - val64, sizeof(val64)) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0100, -1, val64, + sizeof(val64)) < 0) printk("%s: Unable to query LAN_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_HISTORICAL_STATS queried.\n",dev->name); @@ -566,13 +667,13 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) priv->stats.rx_dropped = val64[6]; } - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1, + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0180, -1, &supported_group, sizeof(supported_group)) < 0) printk("%s: Unable to query LAN_SUPPORTED_OPTIONAL_HISTORICAL_STATS.\n",dev->name); if (supported_group[2]) { - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1, - val64, sizeof(val64) ) < 0) + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0183, -1, + val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_OPTIONAL_RX_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_OPTIONAL_RX_HISTORICAL_STATS queried.\n",dev->name); @@ -582,11 +683,10 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) } } - if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET) - { + if (i2o_dev->lct_data->sub_class == I2O_LAN_ETHERNET) { u64 supported_stats = 0; - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0200, -1, + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0200, -1, val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_802_3_HISTORICAL_STATS.\n",dev->name); else { @@ -596,14 +696,15 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) priv->stats.tx_carrier_errors = val64[6]; } - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0280, -1, - &supported_stats, 8) < 0) - printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS\n", dev->name); + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0280, -1, + &supported_stats, sizeof(supported_stats)) < 0) + printk("%s: Unable to query LAN_SUPPORTED_802_3_HISTORICAL_STATS.\n", dev->name); if (supported_stats != 0) { - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1, + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0281, -1, val64, sizeof(val64)) < 0) - printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name); +; +// printk("%s: Unable to query LAN_OPTIONAL_802_3_HISTORICAL_STATS.\n",dev->name); else { dprintk("%s: LAN_OPTIONAL_802_3_HISTORICAL_STATS queried.\n",dev->name); if (supported_stats & 0x1) @@ -616,13 +717,12 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) } #ifdef CONFIG_TR - if (i2o_dev->lct_data->sub_class == I2O_LAN_TR) - { - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0300, -1, + if (i2o_dev->lct_data->sub_class == I2O_LAN_TR) { + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0300, -1, val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_802_5_HISTORICAL_STATS.\n",dev->name); else { - struct tr_statistics *stats = + struct tr_statistics *stats = (struct tr_statistics *)&priv->stats; // dprintk("%s: LAN_802_5_HISTORICAL_STATS queried.\n",dev->name); @@ -642,9 +742,8 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) #endif #ifdef CONFIG_FDDI - if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI) - { - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0400, -1, + if (i2o_dev->lct_data->sub_class == I2O_LAN_FDDI) { + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0400, -1, val64, sizeof(val64)) < 0) printk("%s: Unable to query LAN_FDDI_HISTORICAL_STATS.\n",dev->name); else { @@ -666,90 +765,97 @@ static struct net_device_stats *i2o_lan_get_stats(struct net_device *dev) return (struct net_device_stats *)&priv->stats; } - + /* - * i2o_lan_set_multicast_list(): Enable a network device to receive packets - * not send to the protocol address. + * i2o_lan_set_mc_list(): Enable a network device to receive packets + * not send to the protocol address. */ -static void i2o_lan_set_multicast_list(struct net_device *dev) + +static void i2o_lan_set_mc_list(struct net_device *dev) { - struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; - struct i2o_device *i2o_dev = priv->i2o_dev; - struct i2o_controller *iop = i2o_dev->controller; - u32 filter_mask; - u32 work32[64]; + struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; + struct i2o_device *i2o_dev = priv->i2o_dev; + struct i2o_controller *iop = i2o_dev->controller; + u32 filter_mask; + u32 max_size_mc_table; + u32 mc_addr_group[64]; + + if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1, + &mc_addr_group, sizeof(mc_addr_group)) < 0 ) { + printk(KERN_WARNING "%s: Unable to query LAN_MAC_ADDRESS group.\n", dev->name); + return; + } - dprintk(KERN_INFO "%s: Entered i2o_lan_set_multicast_list().\n", dev->name); + max_size_mc_table = mc_addr_group[8]; -return; + if (dev->flags & IFF_PROMISC) { + filter_mask = 0x00000002; + dprintk(KERN_INFO "%s: Enabling promiscuous mode...\n", dev->name); + } -/* FIXME: Why does the next call kill the interrupt handler? - * The same piece of code works fine in function lan_open(), and in i2o_proc.c - * - * *because its trying to sleep in an irq - this must be async - Alan - */ + else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > max_size_mc_table) { + filter_mask = 0x00000004; + dprintk(KERN_INFO "%s: Enabling all multicast mode...\n", dev->name); + } - if (i2o_query_scalar(iop, i2o_dev->lct_data->tid, 0x0001, -1, - &work32, sizeof(work32)) < 0) - { - printk(KERN_WARNING "i2o_lan: Unable to query " - " LAN_MAC_ADDRESS table.\n"); - return; - } - printk(KERN_INFO "capab mask = 0x%08X, filter mask = 0x%08X\n", - work32[7], work32[6]); + else if (dev->mc_count) { + struct dev_mc_list *mc; + u8 mc_table[2 + 8 * dev->mc_count]; // RowCount, Addresses + u64 *work64 = (u64 *)(mc_table + 2); - filter_mask = work32[6]; + filter_mask = 0x00000000; + dprintk(KERN_INFO "%s: Enabling multicast mode...\n", dev->name); - if (dev->flags & IFF_PROMISC) - { - filter_mask |= 0x00000002; - dprintk(KERN_INFO "i2o_lan: Enabling promiscuous mode...\n"); + /* Fill multicast addr table */ + + memset(mc_table, 0, sizeof(mc_table)); + memcpy(mc_table, &dev->mc_count, 2); + for (mc = dev->mc_list; mc ; mc = mc->next, work64++ ) + memcpy(work64, mc->dmi_addr, mc->dmi_addrlen); + + /* Clear old mc table, copy new table to */ + + if (i2o_clear_table(iop, i2o_dev->lct_data->tid, 0x0002) < 0) + printk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); + + if ((i2o_row_add_table(iop, i2o_dev->lct_data->tid, 0x0002, -1, + mc_table, sizeof(mc_table))) < 0) + printk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); } - - else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > work32[5]) - { - filter_mask |= 0x00000000; - dprintk(KERN_INFO "i2o_lan: Enabling all multicast mode...\n"); - } - else if (dev->mc_count) - { - struct dev_mc_list *mclist; - int i; - u8 *work8 = (u8 *)work32; + else { + filter_mask = 0x00000300; // Broadcast, Multicast disabled + printk(KERN_INFO "%s: Enabling unicast mode...\n",dev->name); + } - dprintk(KERN_INFO "i2o_lan: Enabling multicast mode...\n"); - filter_mask = 0x00000004; + /* Finally copy new FilterMask to */ - /* Fill the multicast addresses */ - mclist = dev->mc_list; + if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0001, 3, + &filter_mask, sizeof(filter_mask)) <0) + printk(KERN_WARNING "%s: Unable to set MAC FilterMask.\n",dev->name); - for (i = 0; i < dev->mc_count; i++) - { - memcpy(work8, mclist->dmi_addr, mclist->dmi_addrlen); - work8 += 8; - mclist = mclist->next; - } + return; +} - if (i2o_clear_table(iop, i2o_dev->lct_data->tid, 0x0002) < 0) - dprintk("%s: Unable to clear LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); +/* + * i2o_lan_set_multicast_list(): + * Queue routine i2o_lan_set_mc_list() to be called later. + * Needs to be async. + */ - if (i2o_row_add_table(iop, i2o_dev->lct_data->tid, 0x0002, -1, - work32, dev->mc_count*8) < 0) - dprintk("%s: Unable to set LAN_MULTICAST_MAC_ADDRESS table.\n",dev->name); - } - - else { - filter_mask |= 0x00000300; // Broadcast, Multicast disabled - dprintk(KERN_INFO "i2o_lan: Enabling unicast mode...\n"); - } +static void i2o_lan_set_multicast_list(struct net_device *dev) +{ + struct tq_struct *task; - if (i2o_set_scalar(iop, i2o_dev->lct_data->tid, 0x0001, 3, - &filter_mask, 4) < 0) - printk(KERN_WARNING "i2o_lan: Unable to set MAC FilterMask.\n"); + task = (struct tq_struct *)kmalloc(sizeof(struct tq_struct), GFP_KERNEL); + if (task == NULL) + return; - return; + task->next = NULL; + task->sync = 0; + task->routine = (void *)i2o_lan_set_mc_list; + task->data = (void *)dev; + queue_task(task, &tq_scheduler); } struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) @@ -761,24 +867,21 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) unsigned short (*type_trans)(struct sk_buff *, struct net_device *); void (*unregister_dev)(struct net_device *dev); - switch (i2o_dev->lct_data->sub_class) - { + switch (i2o_dev->lct_data->sub_class) { case I2O_LAN_ETHERNET: - dev = init_etherdev(NULL, sizeof(struct i2o_lan_local)); + dev = init_etherdev(NULL, sizeof(struct i2o_lan_local)); if (dev == NULL) return NULL; type_trans = eth_type_trans; unregister_dev = unregister_netdev; break; - #ifdef CONFIG_ANYLAN case I2O_LAN_100VG: - printk(KERN_ERR "i2o_lan: 100base VG not yet supported\n"); + printk(KERN_ERR "i2o_lan: 100base VG not yet supported.\n"); break; #endif - #ifdef CONFIG_TR case I2O_LAN_TR: dev = init_trdev(NULL, sizeof(struct i2o_lan_local)); @@ -800,8 +903,7 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) dev->priv = (void *)(dev + 1); dev->name = (char *)(dev + 1) + sizeof(struct i2o_lan_local); - if (dev_alloc_name(dev,"fddi%d") < 0) - { + if (dev_alloc_name(dev,"fddi%d") < 0) { printk(KERN_WARNING "i2o_lan: Too many FDDI devices.\n"); kfree(dev); return NULL; @@ -817,13 +919,13 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) #ifdef CONFIG_FIBRE_CHANNEL case I2O_LAN_FIBRE_CHANNEL: - printk(KERN_INFO "i2o_lan: Fibre Channel not yet supported\n"); + printk(KERN_INFO "i2o_lan: Fibre Channel not yet supported.\n"); break; #endif case I2O_LAN_UNKNOWN: default: - printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported\n", + printk(KERN_ERR "i2o_lan: LAN type 0x%08X not supported.\n", i2o_dev->lct_data->sub_class); return NULL; } @@ -838,13 +940,12 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) priv->unit = unit; if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid, - 0x0001, 0, &hw_addr, 8) < 0) - { - printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name); + 0x0001, 0, &hw_addr, sizeof(hw_addr)) < 0) { + printk(KERN_ERR "%s: Unable to query hardware address.\n", dev->name); unit--; unregister_dev(dev); kfree(dev); - return NULL; + return NULL; } dprintk("%s: hwaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", @@ -854,18 +955,18 @@ struct net_device *i2o_lan_register_device(struct i2o_device *i2o_dev) dev->addr_len = 6; memcpy(dev->dev_addr, hw_addr, 6); - if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid, - 0x0007, 2, &max_tx, 4) < 0) - { - printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name); - unit--; - unregister_dev(dev); - kfree(dev); - return NULL; - } - printk(KERN_INFO "%s: Max TX Outstanding = %d\n", dev->name, max_tx); - priv->max_tx = max_tx; - priv->tx_count = 0; + if (i2o_query_scalar(i2o_dev->controller, i2o_dev->lct_data->tid, + 0x0007, 2, &max_tx, sizeof(max_tx)) < 0) + { + printk(KERN_ERR "%s: Unable to query max TX queue.\n", dev->name); + unit--; + unregister_dev(dev); + kfree(dev); + return NULL; + } + dprintk(KERN_INFO "%s: Max TX Outstanding = %d.\n", dev->name, max_tx); + priv->max_tx = max_tx; + priv->tx_count = 0; priv->lock = SPIN_LOCK_UNLOCKED; @@ -887,43 +988,41 @@ int __init i2o_lan_init(void) struct net_device *dev; int i; - if (i2o_install_handler(&i2o_lan_handler) < 0) - { - printk(KERN_ERR "Unable to register I2O LAN OSM.\n"); + printk(KERN_INFO "Linux I2O LAN OSM (c) 1999 University of Helsinki.\n"); + + if (i2o_install_handler(&i2o_lan_handler) < 0) { + printk(KERN_ERR "i2o_lan: Unable to register I2O LAN OSM.\n"); return -EINVAL; - } + } lan_context = i2o_lan_handler.context; for(i=0; i <= MAX_LAN_CARDS; i++) i2o_landevs[i] = NULL; - for (i=0; i < MAX_I2O_CONTROLLERS; i++) - { + for (i=0; i < MAX_I2O_CONTROLLERS; i++) { struct i2o_controller *iop = i2o_find_controller(i); struct i2o_device *i2o_dev; - if (iop==NULL) - continue; + if (iop==NULL) continue; + + for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) { - for (i2o_dev=iop->devices;i2o_dev != NULL;i2o_dev=i2o_dev->next) - { - if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN) + if (i2o_dev->lct_data->class_id != I2O_CLASS_LAN) continue; - if(i2o_dev->lct_data->user_tid != 0xFFF) + /* Make sure device not already claimed by an ISM */ + if (i2o_dev->lct_data->user_tid != 0xFFF) continue; - if (unit == MAX_LAN_CARDS) - { + if (unit == MAX_LAN_CARDS) { i2o_unlock_controller(iop); - printk(KERN_WARNING "Too many I2O LAN devices.\n"); + printk(KERN_WARNING "i2o_lan: Too many I2O LAN devices.\n"); return -EINVAL; } dev = i2o_lan_register_device(i2o_dev); - if (dev == NULL) - { - printk(KERN_ERR "Unable to register I2O LAN device\n"); + if (dev == NULL) { + printk(KERN_ERR "i2o_lan: Unable to register I2O LAN device.\n"); continue; // try next one } @@ -947,14 +1046,12 @@ void cleanup_module(void) { int i; - for (i = 0; i <= unit; i++) - { + for (i = 0; i <= unit; i++) { struct net_device *dev = i2o_landevs[i]; struct i2o_lan_local *priv = (struct i2o_lan_local *)dev->priv; struct i2o_device *i2o_dev = priv->i2o_dev; - switch (i2o_dev->lct_data->sub_class) - { + switch (i2o_dev->lct_data->sub_class) { case I2O_LAN_ETHERNET: unregister_netdev(dev); kfree(dev); @@ -976,11 +1073,11 @@ void cleanup_module(void) i2o_dev->lct_data->sub_class); } - dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n", + dprintk(KERN_INFO "%s: I2O LAN device unregistered.\n", dev->name); } - i2o_remove_handler(&i2o_lan_handler); + i2o_remove_handler(&i2o_lan_handler); } EXPORT_NO_SYMBOLS; @@ -992,4 +1089,4 @@ MODULE_PARM(bucketpost, "i"); // Number of buckets to post MODULE_PARM(bucketthresh, "i"); // Bucket post threshold MODULE_PARM(rx_copybreak, "i"); -#endif +#endif diff --git a/drivers/i2o/i2o_lan.h b/drivers/i2o/i2o_lan.h index 26efb34cfda6..7cd22e9acd2b 100644 --- a/drivers/i2o/i2o_lan.h +++ b/drivers/i2o/i2o_lan.h @@ -18,7 +18,7 @@ /* Tunable parameters first */ #define I2O_BUCKET_COUNT 256 -#define I2O_BUCKET_THRESH 16 +#define I2O_BUCKET_THRESH 8 /* LAN types */ #define I2O_LAN_ETHERNET 0x0030 @@ -108,5 +108,11 @@ struct i2o_bucket_descriptor { u32 context; /* FIXME: 64bit support */ struct i2o_packet_info packet_info[1]; }; + +/* Event Indicator Mask Flags for LAN OSM */ + +#define I2O_LAN_EVT_LINK_DOWN 0x01 +#define I2O_LAN_EVT_LINK_UP 0x02 +#define I2O_LAN_EVT_MEDIA_CHANGE 0x04 #endif /* _I2O_LAN_H */ diff --git a/drivers/i2o/i2o_pci.c b/drivers/i2o/i2o_pci.c index 80a85ac1a098..da3748797e97 100644 --- a/drivers/i2o/i2o_pci.c +++ b/drivers/i2o/i2o_pci.c @@ -5,11 +5,11 @@ * (C) Copyright 1999 Red Hat Software * * Written by Alan Cox, Building Number Three Ltd - * Modified by Deepak Saxena + * Modified by Deepak Saxena * * 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 + * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * * TODO: @@ -120,7 +120,7 @@ int __init i2o_pci_install(struct pci_dev *dev) if(c==NULL) { - printk(KERN_ERR "i2o_pci: insufficient memory to add controller.\n"); + printk(KERN_ERR "i2o: Insufficient memory to add controller.\n"); return -ENOMEM; } memset(c, 0, sizeof(*c)); @@ -137,7 +137,7 @@ int __init i2o_pci_install(struct pci_dev *dev) if(i==6) { - printk(KERN_ERR "i2o_pci: I2O controller has no memory regions defined.\n"); + printk(KERN_ERR "i2o: I2O controller has no memory regions defined.\n"); kfree(c); return -EINVAL; } @@ -145,11 +145,11 @@ int __init i2o_pci_install(struct pci_dev *dev) size = dev->resource[i].end-dev->resource[i].start+1; /* Map the I2O controller */ - printk(KERN_INFO "PCI I2O controller at 0x%08X size=%d\n", memptr, size); + printk(KERN_INFO "i2o: PCI I2O controller at 0x%08X size=%d\n", memptr, size); mem = ioremap(memptr, size); if(mem==NULL) { - printk(KERN_ERR "i2o_pci: Unable to map controller.\n"); + printk(KERN_ERR "i2o: Unable to map controller.\n"); kfree(c); return -EINVAL; } @@ -189,7 +189,7 @@ int __init i2o_pci_install(struct pci_dev *dev) if(i<0) { - printk(KERN_ERR "i2o: unable to install controller.\n"); + printk(KERN_ERR "i2o: Unable to install controller.\n"); kfree(c); iounmap(mem); return i; @@ -216,7 +216,7 @@ int __init i2o_pci_install(struct pci_dev *dev) } } - printk(KERN_INFO "Installed iop%d at IRQ%d\n", c->unit, dev->irq); + printk(KERN_INFO "%s: Installed at IRQ%d\n", c->name, dev->irq); I2O_IRQ_WRITE32(c,0x0); c->enabled = 1; return 0; @@ -227,7 +227,7 @@ int __init i2o_pci_scan(void) struct pci_dev *dev; int count=0; - printk(KERN_INFO "Checking for PCI I2O controllers...\n"); + printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n"); for(dev=pci_devices; dev!=NULL; dev=dev->next) { @@ -235,17 +235,17 @@ int __init i2o_pci_scan(void) continue; if((dev->class&0xFF)>1) { - printk(KERN_INFO "I2O controller found but does not support I2O 1.5 (skipping).\n"); + printk(KERN_INFO "i2o: I2O Controller found but does not support I2O 1.5 (skipping).\n"); continue; } - printk(KERN_INFO "I2O controller on bus %d at %d.\n", + printk(KERN_INFO "i2o: I2O controller on bus %d at %d.\n", dev->bus->number, dev->devfn); pci_set_master(dev); if(i2o_pci_install(dev)==0) count++; } if(count) - printk(KERN_INFO "%d I2O controller%s found and installed.\n", count, + printk(KERN_INFO "i2o: %d I2O controller%s found and installed.\n", count, count==1?"":"s"); return count?count:-ENODEV; } @@ -270,7 +270,7 @@ static void i2o_pci_activate(i2o_controller * c) if(i2o_activate_controller(c)) #endif /* MODULE */ { - printk("I2O: Failed to initialize iop%d\n", c->unit); + printk("%s: Failed to initialize.\n", c->name); #ifdef MODULE core->unlock(c); core->delete(c); diff --git a/drivers/i2o/i2o_proc.c b/drivers/i2o/i2o_proc.c index 4059a5189517..2636b089d08a 100644 --- a/drivers/i2o/i2o_proc.c +++ b/drivers/i2o/i2o_proc.c @@ -51,9 +51,6 @@ #include #include - -#include "i2o_proc.h" - #include "i2o_lan.h" /* @@ -69,24 +66,34 @@ typedef struct _i2o_proc_entry_t static int proc_context = 0; - static int i2o_proc_read_lct(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_hrt(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_stat(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_status(char *, char **, off_t, int, int *, void *); + static int i2o_proc_read_hw(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_dst(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_ddm_table(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_ds(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_driver_store(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_drivers_stored(char *, char **, off_t, int, int *, void *); + static int i2o_proc_read_groups(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_phys_device(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_claimed(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_users(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_priv_msgs(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_dev(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_authorized_users(char *, char **, off_t, int, int *, void *); + static int i2o_proc_read_dev_name(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_ddm(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_dev_identity(char *, char **, off_t, int, int *, void *); +static int i2o_proc_read_ddm_identity(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_uinfo(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_sgl_limits(char *, char **, off_t, int, int *, void *); + +static int i2o_proc_read_sensors(char *, char **, off_t, int, int *, void *); + static int print_serial_number(char *, int, u8 *, int); -static int i2o_proc_create_entries(void *, - i2o_proc_entry *, struct proc_dir_entry *); + +static int i2o_proc_create_entries(void *, i2o_proc_entry *, + struct proc_dir_entry *); static void i2o_proc_remove_entries(i2o_proc_entry *, struct proc_dir_entry *); static int i2o_proc_add_controller(struct i2o_controller *, struct proc_dir_entry * ); @@ -117,18 +124,8 @@ static int i2o_proc_read_lan_rx_info(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_lan_hist_stats(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_lan_supp_opt_stats(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_opt_tx_hist_stats(char *, char **, off_t, int, - int *, void *); -static int i2o_proc_read_lan_opt_rx_hist_stats(char *, char **, off_t, int, - int *, void *); static int i2o_proc_read_lan_eth_stats(char *, char **, off_t, int, int *, void *); -static int i2o_proc_read_lan_supp_eth_stats(char *, char **, off_t, int, int *, - void *); -static int i2o_proc_read_lan_opt_eth_stats(char *, char **, off_t, int, int *, - void *); static int i2o_proc_read_lan_tr_stats(char *, char **, off_t, int, int *, void *); static int i2o_proc_read_lan_fddi_stats(char *, char **, off_t, int, int *, @@ -155,11 +152,11 @@ static i2o_proc_entry generic_iop_entries[] = { {"hrt", S_IFREG|S_IRUGO, i2o_proc_read_hrt, NULL}, {"lct", S_IFREG|S_IRUGO, i2o_proc_read_lct, NULL}, - {"stat", S_IFREG|S_IRUGO, i2o_proc_read_stat, NULL}, + {"status", S_IFREG|S_IRUGO, i2o_proc_read_status, NULL}, {"hw", S_IFREG|S_IRUGO, i2o_proc_read_hw, NULL}, - {"dst", S_IFREG|S_IRUGO, i2o_proc_read_dst, NULL}, {"ddm_table", S_IFREG|S_IRUGO, i2o_proc_read_ddm_table, NULL}, - {"ds", S_IFREG|S_IRUGO, i2o_proc_read_ds, NULL}, + {"driver_store", S_IFREG|S_IRUGO, i2o_proc_read_driver_store, NULL}, + {"drivers_stored", S_IFREG|S_IRUGO, i2o_proc_read_drivers_stored, NULL}, {NULL, 0, NULL, NULL} }; @@ -169,11 +166,16 @@ static i2o_proc_entry generic_iop_entries[] = static i2o_proc_entry generic_dev_entries[] = { {"groups", S_IFREG|S_IRUGO, i2o_proc_read_groups, NULL}, + {"phys_dev", S_IFREG|S_IRUGO, i2o_proc_read_phys_device, NULL}, + {"claimed", S_IFREG|S_IRUGO, i2o_proc_read_claimed, NULL}, + {"users", S_IFREG|S_IRUGO, i2o_proc_read_users, NULL}, {"priv_msgs", S_IFREG|S_IRUGO, i2o_proc_read_priv_msgs, NULL}, - {"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev, NULL}, - {"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm, NULL}, - {"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL}, + {"authorized_users", S_IFREG|S_IRUGO, i2o_proc_read_authorized_users, NULL}, + {"dev_identity", S_IFREG|S_IRUGO, i2o_proc_read_dev_identity, NULL}, + {"ddm_identity", S_IFREG|S_IRUGO, i2o_proc_read_ddm_identity, NULL}, {"user_info", S_IFREG|S_IRUGO, i2o_proc_read_uinfo, NULL}, + {"sgl_limits", S_IFREG|S_IRUGO, i2o_proc_read_sgl_limits, NULL}, + {"sensors", S_IFREG|S_IRUGO, i2o_proc_read_sensors, NULL}, {NULL, 0, NULL, NULL} }; @@ -187,22 +189,22 @@ static i2o_proc_entry rbs_dev_entries[] = }; #define SCSI_TABLE_SIZE 13 - static char *scsi_devices[] = - { - "Direct-Access Read/Write", - "Sequential-Access Storage", - "Printer", - "Processor", - "WORM Device", - "CD-ROM Device", - "Scanner Device", - "Optical Memory Device", - "Medium Changer Device", - "Communications Device", - "Graphics Art Pre-Press Device", - "Graphics Art Pre-Press Device", - "Array Controller Device" - }; +static char *scsi_devices[] = +{ + "Direct-Access Read/Write", + "Sequential-Access Storage", + "Printer", + "Processor", + "WORM Device", + "CD-ROM Device", + "Scanner Device", + "Optical Memory Device", + "Medium Changer Device", + "Communications Device", + "Graphics Art Pre-Press Device", + "Graphics Art Pre-Press Device", + "Array Controller Device" +}; /* private */ @@ -214,7 +216,6 @@ static i2o_proc_entry rbs_dev_entries[] = */ static i2o_proc_entry lan_entries[] = { - /* LAN param groups 0000h-0008h */ {"lan_dev_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_dev_info, NULL}, {"lan_mac_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_mac_addr, NULL}, {"lan_mcast_addr", S_IFREG|S_IRUGO|S_IWUSR, @@ -227,56 +228,30 @@ static i2o_proc_entry lan_entries[] = {"lan_alt_addr", S_IFREG|S_IRUGO, i2o_proc_read_lan_alt_addr, NULL}, {"lan_tx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_tx_info, NULL}, {"lan_rx_info", S_IFREG|S_IRUGO, i2o_proc_read_lan_rx_info, NULL}, - /* LAN param groups 0100h, 0180h, 0182h, 0183h */ - {"lan_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL}, - {"lan_supp_opt_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_supp_opt_stats, NULL}, - {"lan_opt_tx_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_opt_tx_hist_stats, NULL}, - {"lan_opt_rx_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_opt_rx_hist_stats, NULL}, - /* TODO: LAN param group 0184h */ + + {"lan_hist_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_hist_stats, NULL}, {NULL, 0, NULL, NULL} }; /* - * Ethernet specific LAN entries + * Port specific LAN entries * */ static i2o_proc_entry lan_eth_entries[] = { - /* LAN param groups 0200h, 0280h, 0281h */ - {"lan_eth_stat", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL}, - {"lan_supp_eth_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_supp_eth_stats, NULL}, - {"lan_opt_eth_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_opt_eth_stats, NULL}, + {"lan_eth_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_eth_stats, NULL}, {NULL, 0, NULL, NULL} }; -/* - * Token Ring specific LAN entries - * - */ static i2o_proc_entry lan_tr_entries[] = { - /* LAN param group 0300h */ - {"lan_tr_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_tr_stats, NULL}, - /* TODO: LAN param group 0380h, 0381h */ + {"lan_tr_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_tr_stats, NULL}, {NULL, 0, NULL, NULL} }; -/* - * FDDI specific LAN entries - * - */ static i2o_proc_entry lan_fddi_entries[] = { - /* LAN param group 0400h */ - {"lan_fddi_stats", S_IFREG|S_IRUGO, - i2o_proc_read_lan_fddi_stats, NULL}, - /* TODO: LAN param group 0480h, 0481h */ + {"lan_fddi_stats", S_IFREG|S_IRUGO, i2o_proc_read_lan_fddi_stats, NULL}, {NULL, 0, NULL, NULL} }; @@ -290,6 +265,22 @@ static char *chtostr(u8 *chars, int n) return strncat(tmp, (char *)chars, n); } +static int i2o_report_query_status(char *buf, int block_status, char *group) +{ + switch (block_status) + { + case -ETIMEDOUT: + return sprintf(buf, "Timeout reading group %s.\n",group); + case -ENOMEM: + return sprintf(buf, "No free memory to read the table.\n"); + case -I2O_PARAMS_STATUS_INVALID_GROUP_ID: + return sprintf(buf, "Group %s not supported.\n", group); + default: + return sprintf(buf, "Error reading group %s. BlockStatus 0x%02X\n", + group, -block_status); + } +} + static char* bus_strings[] = { "Local Bus", @@ -314,7 +305,7 @@ int i2o_proc_read_hrt(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_controller *c = (struct i2o_controller *)data; - pi2o_hrt hrt = (pi2o_hrt)c->hrt; + i2o_hrt *hrt = (i2o_hrt *)c->hrt; u32 bus; int count; int i; @@ -342,17 +333,15 @@ int i2o_proc_read_hrt(char *buf, char **start, off_t offset, int len, } len += sprintf(buf+len, "HRT has %d entries of %d bytes each.\n", - count, hrt->entry_len); + count, hrt->entry_len << 2); for(i = 0; i < count; i++) { len += sprintf(buf+len, "Entry %d:\n", i); len += sprintf(buf+len, " Adapter ID: %0#10x\n", hrt->hrt_entry[i].adapter_id); - len += sprintf(buf+len, " Controlled by: %0#6x\n", + len += sprintf(buf+len, " Controlling tid: %0#6x\n", hrt->hrt_entry[i].parent_tid); - len += sprintf(buf+len, " Bus#%d\n", - hrt->hrt_entry[i].bus_num); if(hrt->hrt_entry[i].bus_type != 0x80) { @@ -425,20 +414,19 @@ int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_controller *c = (struct i2o_controller*)data; - pi2o_lct lct = (pi2o_lct)c->lct; + i2o_lct *lct = (i2o_lct *)c->lct; int entries; int i; #define BUS_TABLE_SIZE 3 static char *bus_ports[] = - { - "Generic Bus", - "SCSI Bus", - "Fibre Channel Bus" - }; + { + "Generic Bus", + "SCSI Bus", + "Fibre Channel Bus" + }; spin_lock(&i2o_proc_lock); - len = 0; entries = (lct->table_size - 3)/9; @@ -451,8 +439,7 @@ int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, for(i = 0; i < entries; i++) { len += sprintf(buf+len, "Entry %d\n", i); - - len += sprintf(buf+len, " %s", i2o_get_class_name(lct->lct_entry[i].class_id)); + len += sprintf(buf+len, " Class, SubClass : %s", i2o_get_class_name(lct->lct_entry[i].class_id)); /* * Classes which we'll print subclass info for @@ -463,23 +450,23 @@ int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, switch(lct->lct_entry[i].sub_class) { case 0x00: - len += sprintf(buf+len, ": Direct-Access Read/Write"); + len += sprintf(buf+len, ", Direct-Access Read/Write"); break; case 0x04: - len += sprintf(buf+len, ": WORM Drive"); + len += sprintf(buf+len, ", WORM Drive"); break; case 0x05: - len += sprintf(buf+len, ": CD-ROM Drive"); + len += sprintf(buf+len, ", CD-ROM Drive"); break; case 0x07: - len += sprintf(buf+len, ": Optical Memory Device"); + len += sprintf(buf+len, ", Optical Memory Device"); break; default: - len += sprintf(buf+len, ": Unknown (0x%02x)", + len += sprintf(buf+len, ", Unknown (0x%02x)", lct->lct_entry[i].sub_class); break; } @@ -489,27 +476,27 @@ int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, switch(lct->lct_entry[i].sub_class & 0xFF) { case 0x30: - len += sprintf(buf+len, ": Ethernet"); + len += sprintf(buf+len, ", Ethernet"); break; case 0x40: - len += sprintf(buf+len, ": 100base VG"); + len += sprintf(buf+len, ", 100base VG"); break; case 0x50: - len += sprintf(buf+len, ": IEEE 802.5/Token-Ring"); + len += sprintf(buf+len, ", IEEE 802.5/Token-Ring"); break; case 0x60: - len += sprintf(buf+len, ": ANSI X3T9.5 FDDI"); + len += sprintf(buf+len, ", ANSI X3T9.5 FDDI"); break; case 0x70: - len += sprintf(buf+len, ": Fibre Channel"); + len += sprintf(buf+len, ", Fibre Channel"); break; default: - len += sprintf(buf+len, ": Unknown Sub-Class (0x%02x)", + len += sprintf(buf+len, ", Unknown Sub-Class (0x%02x)", lct->lct_entry[i].sub_class & 0xFF); break; } @@ -517,27 +504,27 @@ int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, case I2O_CLASS_SCSI_PERIPHERAL: if(lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE) - len += sprintf(buf+len, ": %s", + len += sprintf(buf+len, ", %s", scsi_devices[lct->lct_entry[i].sub_class]); else - len += sprintf(buf+len, ": Unknown Device Type"); + len += sprintf(buf+len, ", Unknown Device Type"); break; case I2O_CLASS_BUS_ADAPTER_PORT: if(lct->lct_entry[i].sub_class < BUS_TABLE_SIZE) - len += sprintf(buf+len, ": %s", + len += sprintf(buf+len, ", %s", bus_ports[lct->lct_entry[i].sub_class]); else - len += sprintf(buf+len, ": Unknown Bus Type"); + len += sprintf(buf+len, ", Unknown Bus Type"); break; } len += sprintf(buf+len, "\n"); - len += sprintf(buf+len, " Local TID: 0x%03x\n", lct->lct_entry[i].tid); - len += sprintf(buf+len, " User TID: 0x%03x\n", lct->lct_entry[i].user_tid); - len += sprintf(buf+len, " Parent TID: 0x%03x\n", + len += sprintf(buf+len, " Local TID : 0x%03x\n", lct->lct_entry[i].tid); + len += sprintf(buf+len, " User TID : 0x%03x\n", lct->lct_entry[i].user_tid); + len += sprintf(buf+len, " Parent TID : 0x%03x\n", lct->lct_entry[i].parent_tid); - len += sprintf(buf+len, " Identity Tag: 0x%x%x%x%x%x%x%x%x\n", + len += sprintf(buf+len, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n", lct->lct_entry[i].identity_tag[0], lct->lct_entry[i].identity_tag[1], lct->lct_entry[i].identity_tag[2], @@ -546,219 +533,211 @@ int i2o_proc_read_lct(char *buf, char **start, off_t offset, int len, lct->lct_entry[i].identity_tag[5], lct->lct_entry[i].identity_tag[6], lct->lct_entry[i].identity_tag[7]); - len += sprintf(buf+len, " Change Indicator: %0#10x\n", + len += sprintf(buf+len, " Change Indicator : %0#10x\n", lct->lct_entry[i].change_ind); - len += sprintf(buf+len, " Device Flags: %0#10x\n", + len += sprintf(buf+len, " Event Capab Mask : %0#10x\n", lct->lct_entry[i].device_flags); } spin_unlock(&i2o_proc_lock); - return len; } -int i2o_proc_read_stat(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +int i2o_proc_read_status(char *buf, char **start, off_t offset, int len, + int *eof, void *data) { struct i2o_controller *c = (struct i2o_controller*)data; - u32 *msg; - u32 m; - u8 *workspace; - u16 *work16; - u32 *work32; - long time; char prodstr[25]; int version; spin_lock(&i2o_proc_lock); - len = 0; - workspace = (u8*)kmalloc(88, GFP_KERNEL); - if(!workspace) - { - len += sprintf(buf, "No memory for status transfer\n"); - spin_unlock(&i2o_proc_lock); - return len; - } - - m = I2O_POST_READ32(c); - if(m == 0xFFFFFFFF) - { - len += sprintf(buf, "Could not get inbound message frame from IOP!\n"); - kfree(workspace); - spin_unlock(&i2o_proc_lock); - return len; - } - - msg = (u32 *)(m+c->mem_offset); - - memset(workspace, 0, 88); - work32 = (u32*)workspace; - work16 = (u16*)workspace; - - msg[0] = NINE_WORD_MSG_SIZE|SGL_OFFSET_0; - msg[1] = I2O_CMD_STATUS_GET<<24|HOST_TID<<12|ADAPTER_TID; - msg[2] = msg[3] = msg[4] = msg[5] = 0; - msg[6] = virt_to_phys(workspace); - msg[7] = 0; /* FIXME: 64-bit */ - msg[8] = 88; - - /* - * hmm...i2o_post_message should just take ptr to message, and - * determine offset on it's own...less work for OSM developers - */ - i2o_post_message(c, m); - - time = jiffies; - - while(workspace[87] != 0xFF) - { - if(jiffies-time >= 2*HZ) - { - len += sprintf(buf, "Timeout waiting for status reply\n"); - kfree(workspace); - spin_unlock(&i2o_proc_lock); - return len; - } - schedule(); - barrier(); - } + i2o_status_get(c); // reread the status block - len += sprintf(buf+len, "Organization ID: %0#6x\n", work16[0]); + len += sprintf(buf+len,"Organization ID : %0#6x\n", + c->status_block->org_id); - version = workspace[9]&0xF0>>4; - if(version == 0x02) { - len += sprintf(buf+len, "Lowest I2O version supported: "); + version = c->status_block->i2o_version; + +/* FIXME for Spec 2.0 + if (version == 0x02) { + len += sprintf(buf+len,"Lowest I2O version supported: "); switch(workspace[2]) { - case 0x00: - len += sprintf(buf+len, "1.0\n"); - break; - case 0x01: - len += sprintf(buf+len, "1.5\n"); - break; - case 0x02: - len += sprintf(buf+len, "2.0\n"); - break; + case 0x00: + len += sprintf(buf+len,"1.0\n"); + break; + case 0x01: + len += sprintf(buf+len,"1.5\n"); + break; + case 0x02: + len += sprintf(buf+len,"2.0\n"); + break; } len += sprintf(buf+len, "Highest I2O version supported: "); switch(workspace[3]) { + case 0x00: + len += sprintf(buf+len,"1.0\n"); + break; + case 0x01: + len += sprintf(buf+len,"1.5\n"); + break; + case 0x02: + len += sprintf(buf+len,"2.0\n"); + break; + } + } +*/ + len += sprintf(buf+len,"IOP ID : %0#5x\n", + c->status_block->iop_id); + len += sprintf(buf+len,"Host Unit ID : %0#6x\n", + c->status_block->host_unit_id); + len += sprintf(buf+len,"Segment Number : %0#5x\n", + c->status_block->segment_number); + + len += sprintf(buf+len, "I2O version : "); + switch (version) { case 0x00: - len += sprintf(buf+len, "1.0\n"); + len += sprintf(buf+len,"1.0\n"); break; case 0x01: - len += sprintf(buf+len, "1.5\n"); + len += sprintf(buf+len,"1.5\n"); break; case 0x02: - len += sprintf(buf+len, "2.0\n"); + len += sprintf(buf+len,"2.0\n"); break; - } - } - - len += sprintf(buf+len, "IOP ID: %0#5x\n", work16[2]&0xFFF); - len += sprintf(buf+len, "Host Unit ID: %0#6x\n", work16[3]); - len += sprintf(buf+len, "Segment Number: %0#5x\n", work16[4]&0XFFF); - - len += sprintf(buf+len, "I2O version: "); - switch(version) - { - case 0x00: - len += sprintf(buf+len, "1.0\n"); - break; - case 0x01: - len += sprintf(buf+len, "1.5\n"); - break; - case 0x02: - len += sprintf(buf+len, "2.0\n"); - break; - default: - len += sprintf(buf+len, "Unknown version\n"); + default: + len += sprintf(buf+len,"Unknown version\n"); } - len += sprintf(buf+len, "IOP State: "); - switch(workspace[10]) - { + len += sprintf(buf+len, "IOP State : "); + switch (c->status_block->iop_state) { case 0x01: - len += sprintf(buf+len, "Init\n"); + len += sprintf(buf+len,"INIT\n"); break; case 0x02: - len += sprintf(buf+len, "Reset\n"); + len += sprintf(buf+len,"RESET\n"); break; case 0x04: - len += sprintf(buf+len, "Hold\n"); + len += sprintf(buf+len,"HOLD\n"); break; case 0x05: - len += sprintf(buf+len, "Hold\n"); + len += sprintf(buf+len,"READY\n"); break; case 0x08: - len += sprintf(buf+len, "Operational\n"); + len += sprintf(buf+len,"OPERATIONAL\n"); break; case 0x10: - len += sprintf(buf+len, "FAILED\n"); + len += sprintf(buf+len,"FAILED\n"); break; case 0x11: - len += sprintf(buf+len, "FAULTED\n"); + len += sprintf(buf+len,"FAULTED\n"); break; default: - len += sprintf(buf+len, "Unknown\n"); + len += sprintf(buf+len,"Unknown\n"); break; } - /* 0x00 is the only type supported w/spec 1.5 */ - /* Added 2.0 types */ - len += sprintf(buf+len, "Messenger Type: "); - switch (workspace[11]) - { - case 0x00: - len += sprintf(buf+len, "Memory mapped\n"); - break; - case 0x01: - len += sprintf(buf+len, "Memory mapped only\n"); - break; - case 0x02: - len += sprintf(buf+len, "Remote only\n"); - break; - case 0x03: - len += sprintf(buf+len, "Memory mapped and remote\n"); - break; - default: - len += sprintf(buf+len, "Unknown\n"); - break; + len += sprintf(buf+len,"Messenger Type : "); + switch (c->status_block->msg_type) { + case 0x00: + len += sprintf(buf+len,"Memory mapped\n"); + break; + case 0x01: + len += sprintf(buf+len,"Memory mapped only\n"); + break; + case 0x02: + len += sprintf(buf+len,"Remote only\n"); + break; + case 0x03: + len += sprintf(buf+len,"Memory mapped and remote\n"); + break; + default: + len += sprintf(buf+len,"Unknown\n"); } - len += sprintf(buf+len, "Inbound Frame Size: %d bytes\n", work16[6]*4); - len += sprintf(buf+len, "Max Inbound Frames: %d\n", work32[4]); - len += sprintf(buf+len, "Current Inbound Frames: %d\n", work32[5]); - len += sprintf(buf+len, "Max Outbound Frames: %d\n", work32[6]); + + len += sprintf(buf+len,"Inbound Frame Size : %d bytes\n", + c->status_block->inbound_frame_size<<2); + len += sprintf(buf+len,"Max Inbound Frames : %d\n", + c->status_block->max_inbound_frames); + len += sprintf(buf+len,"Current Inbound Frames : %d\n", + c->status_block->cur_inbound_frames); + len += sprintf(buf+len,"Max Outbound Frames : %d\n", + c->status_block->max_outbound_frames); /* Spec doesn't say if NULL terminated or not... */ - memcpy(prodstr, work32+7, 24); + memcpy(prodstr, c->status_block->product_id, 24); prodstr[24] = '\0'; - len += sprintf(buf+len, "Product ID: %s\n", prodstr); - - len += sprintf(buf+len, "LCT Size: %d\n", work32[13]); - - len += sprintf(buf+len, "Desired private memory space: %d kB\n", - work32[15]>>10); - len += sprintf(buf+len, "Allocated private memory space: %d kB\n", - work32[16]>>10); - len += sprintf(buf+len, "Private memory base address: %0#10x\n", - work32[17]); - len += sprintf(buf+len, "Desired private I/O space: %d kB\n", - work32[18]>>10); - len += sprintf(buf+len, "Allocated private I/O space: %d kB\n", - work32[19]>>10); - len += sprintf(buf+len, "Private I/O base address: %0#10x\n", - work32[20]); - - kfree(workspace); + len += sprintf(buf+len,"Product ID : %s\n", prodstr); + len += sprintf(buf+len,"Expected LCT Size : %d bytes\n", + c->status_block->expected_lct_size); + + len += sprintf(buf+len,"IOP Capabilities\n"); + len += sprintf(buf+len," Context Field Size Support : "); + switch (c->status_block->iop_capabilities & 0x0000003) { + case 0: + len += sprintf(buf+len,"Supports only 32-bit context fields\n"); + break; + case 1: + len += sprintf(buf+len,"Supports only 64-bit context fields\n"); + break; + case 2: + len += sprintf(buf+len,"Supports 32-bit and 64-bit context fields, " + "but not concurrently\n"); + break; + case 3: + len += sprintf(buf+len,"Supports 32-bit and 64-bit context fields " + "concurrently\n"); + break; + default: + len += sprintf(buf+len,"0x%08x\n",c->status_block->iop_capabilities); + } + len += sprintf(buf+len," Current Context Field Size : "); + switch (c->status_block->iop_capabilities & 0x0000000C) { + case 0: + len += sprintf(buf+len,"not configured\n"); + break; + case 4: + len += sprintf(buf+len,"Supports only 32-bit context fields\n"); + break; + case 8: + len += sprintf(buf+len,"Supports only 64-bit context fields\n"); + break; + case 12: + len += sprintf(buf+len,"Supports both 32-bit or 64-bit context fields " + "concurrently\n"); + break; + default: + len += sprintf(buf+len,"\n"); + } + len += sprintf(buf+len," Inbound Peer Support : %s\n", + (c->status_block->iop_capabilities & 0x00000010) ? "Supported" : "Not supported"); + len += sprintf(buf+len," Outbound Peer Support : %s\n", + (c->status_block->iop_capabilities & 0x00000020) ? "Supported" : "Not supported"); + len += sprintf(buf+len," Peer to Peer Support : %s\n", + (c->status_block->iop_capabilities & 0x00000040) ? "Supported" : "Not supported"); + + len += sprintf(buf+len, "Desired private memory size : %d kB\n", + c->status_block->desired_mem_size>>10); + len += sprintf(buf+len, "Allocated private memory size : %d kB\n", + c->status_block->current_mem_size>>10); + len += sprintf(buf+len, "Private memory base address : %0#10x\n", + c->status_block->current_mem_base); + len += sprintf(buf+len, "Desired private I/O size : %d kB\n", + c->status_block->desired_io_size>>10); + len += sprintf(buf+len, "Allocated private I/O size : %d kB\n", + c->status_block->current_io_size>>10); + len += sprintf(buf+len, "Private I/O base address : %0#10x\n", + c->status_block->current_io_base); + spin_unlock(&i2o_proc_lock); return len; @@ -790,25 +769,25 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, len = 0; - token = i2o_query_scalar(c, ADAPTER_TID, - 0, // ParamGroup 0x0000h - -1, // all fields - &work32, - sizeof(work32)); + token = i2o_query_scalar(c, ADAPTER_TID, 0x0000, -1, &work32, sizeof(work32)); - if(token < 0) - { - len += sprintf(buf, "Error waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0000 IOP Hardware"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "IOP Hardware Information Table (group = 0x0000)\n"); - - len += sprintf(buf+len, "I2O Vendor ID : %0#6x\n", work16[0]); - len += sprintf(buf+len, "Product ID : %0#6x\n", work16[1]); - len += sprintf(buf+len, "RAM : %dkB\n", work32[1]>>10); - len += sprintf(buf+len, "Non-Volatile Storage : %dkB\n", work32[2]>>10); + len += sprintf(buf+len, "I2O Vendor ID : %0#6x\n", work16[0]); + len += sprintf(buf+len, "Product ID : %0#6x\n", work16[1]); + len += sprintf(buf+len, "CPU : "); + if(work8[16] > 8) + len += sprintf(buf+len, "Unknown\n"); + else + len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]); + /* Anyone using ProcessorVersion? */ + + len += sprintf(buf+len, "RAM : %dkB\n", work32[1]>>10); + len += sprintf(buf+len, "Non-Volatile Mem : %dkB\n", work32[2]>>10); hwcap = work32[3]; len += sprintf(buf+len, "Capabilities :\n"); @@ -823,13 +802,6 @@ int i2o_proc_read_hw(char *buf, char **start, off_t offset, int len, if(hwcap&0x00000010) len += sprintf(buf+len, " Battery-backed RAM\n"); - len += sprintf(buf+len, "CPU : "); - if(work8[16] > 8) - len += sprintf(buf+len, "Unknown\n"); - else - len += sprintf(buf+len, "%s\n", cpu_table[work8[16]]); - /* Anyone using ProcessorVersion? */ - spin_unlock(&i2o_proc_lock); return len; @@ -850,11 +822,10 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, u8 reserved; u16 i2o_vendor_id; u16 module_id; - u8 module_name[24]; - u8 module_version[4]; + u8 module_name_version[28]; u32 data_size; u32 code_size; - } i2o_exec_execute_ddm_table, *pi2o_exec_execute_ddm_table; + } i2o_exec_execute_ddm_table; struct { @@ -879,27 +850,13 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, NULL, 0, &result, sizeof(result)); - if (token<0) - switch (token) - { - case -ETIMEDOUT: - len += sprintf(buf, "Timeout reading table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - case -ENOMEM: - len += sprintf(buf, "No free memory to read the table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - default: - len += sprintf(buf, "Error reading group. BlockStatus %d\n", - token); - spin_unlock(&i2o_proc_lock); - return len; - } + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0003 Executing DDM List"); + spin_unlock(&i2o_proc_lock); + return len; + } - len += sprintf(buf+len, "Tid Type Vendor Id Name Vrs Data_size Code_size\n"); + len += sprintf(buf+len, "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n"); ddm_table=result.ddm_table[0]; for(i=0; i < result.row_count; ddm_table=result.ddm_table[++i]) @@ -918,11 +875,10 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, len += sprintf(buf+len, " "); } - len += sprintf(buf+len, "%0#7x", ddm_table.i2o_vendor_id); - len += sprintf(buf+len, "%0#7x", ddm_table.module_id); - len += sprintf(buf+len, "%-25s", chtostr(ddm_table.module_name, 24)); - len += sprintf(buf+len, "%-6s", chtostr(ddm_table.module_version,4)); - len += sprintf(buf+len, "%8d ", ddm_table.data_size); + len += sprintf(buf+len, "%-#7x", ddm_table.i2o_vendor_id); + len += sprintf(buf+len, "%-#8x", ddm_table.module_id); + len += sprintf(buf+len, "%-29s", chtostr(ddm_table.module_name_version, 28)); + len += sprintf(buf+len, "%9d ", ddm_table.data_size); len += sprintf(buf+len, "%8d", ddm_table.code_size); len += sprintf(buf+len, "\n"); @@ -935,20 +891,20 @@ int i2o_proc_read_ddm_table(char *buf, char **start, off_t offset, int len, /* Executive group 0004h - Driver Store (scalar) */ -int i2o_proc_read_ds(char *buf, char **start, off_t offset, int len, +int i2o_proc_read_driver_store(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_controller *c = (struct i2o_controller*)data; u32 work32[8]; + int token; spin_lock(&i2o_proc_lock); len = 0; - if(i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, - sizeof(work32)) < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + token = i2o_query_scalar(c, ADAPTER_TID, 0x0004, -1, &work32, sizeof(work32)); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0004 Driver Store"); spin_unlock(&i2o_proc_lock); return len; } @@ -966,8 +922,8 @@ int i2o_proc_read_ds(char *buf, char **start, off_t offset, int len, /* Executive group 0005h - Driver Store Table (table) */ -int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +int i2o_proc_read_drivers_stored(char *buf, char **start, off_t offset, + int len, int *eof, void *data) { typedef struct _i2o_driver_store { u16 stored_ddm_index; @@ -1005,33 +961,17 @@ int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, - 0x0005, -1, - NULL, 0, + c, ADAPTER_TID, 0x0005, -1, NULL, 0, &result, sizeof(result)); - if (token<0) - switch (token) - { - case -ETIMEDOUT: - len += sprintf(buf, "Timeout reading table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - case -ENOMEM: - len += sprintf(buf, "No free memory to read the table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - default: - len += sprintf(buf, "Error reading group. " - "BlockStatus %d\n",token); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf+len, "# Type Vendor Id Name Vrs Date Mod_size Par_size Flags\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0005 DRIVER STORE TABLE"); + spin_unlock(&i2o_proc_lock); + return len; + } + len += sprintf(buf+len, "# Module_type Vendor Mod_id Module_name Vrs" + "Date Mod_size Par_size Flags\n"); for(i=0, dst=result.dst[0]; i < result.row_count; dst=result.dst[++i]) { len += sprintf(buf+len, "%-3d", dst.stored_ddm_index); @@ -1052,8 +992,8 @@ int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len, len += sprintf(buf+len, "%-d", dst.module_state); #endif - len += sprintf(buf+len, "%#7x", dst.i2o_vendor_id); - len += sprintf(buf+len, "%#8x", dst.module_id); + len += sprintf(buf+len, "%-#7x", dst.i2o_vendor_id); + len += sprintf(buf+len, "%-#8x", dst.module_id); len += sprintf(buf+len, "%-29s", chtostr(dst.module_name_version,28)); len += sprintf(buf+len, "%-9s", chtostr(dst.date,8)); len += sprintf(buf+len, "%8d ", dst.module_size); @@ -1077,81 +1017,69 @@ int i2o_proc_read_dst(char *buf, char **start, off_t offset, int len, int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, int *eof, void *data) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_device *d = (struct i2o_device*)data; int token; int i; - int rows; - u16 work16[2048]; - u16 *group=work16; - int more; - + u8 properties; + + typedef struct _i2o_group_info + { + u16 group_number; + u16 field_count; + u16 row_count; + u8 properties; + u8 reserved; + } i2o_group_info; + + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_group_info group[256]; + } result; + spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, - 0xF000, -1, - NULL, 0, - &work16, sizeof(work16)); - - if (token<0) - switch (token) - { - case -ETIMEDOUT: - len += sprintf(buf, "Timeout reading table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - case -ENOMEM: - len += sprintf(buf, "No free memory to read the table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - default: - len += sprintf(buf, "Error reading table. BlockStatus %d\n", - token); - spin_unlock(&i2o_proc_lock); - return len; - } + d->controller, d->lct_data->tid, 0xF000, -1, NULL, 0, + &result, sizeof(result)); - rows=work16[4]; - more=work16[5]; + if (token < 0) { + len = i2o_report_query_status(buf+len, token, "0xF000 Params Descriptor"); + spin_unlock(&i2o_proc_lock); + return len; + } - len += sprintf(buf+len, "\nPARAMS DESCRIPTOR TABLE:\n\n"); len += sprintf(buf+len, "# Group FieldCount RowCount Type Add Del Clear\n"); - group+=64; - - for(i=0; i < rows; i++, group+=16) + for (i=0; i < result.row_count; i++) { len += sprintf(buf+len, "%-3d", i); - - len += sprintf(buf+len, "%#6x ", group[0]); - len += sprintf(buf+len, "%10d ", group[1]); - len += sprintf(buf+len, "%8d ", group[2]); - - if(group[3]&0x1) - len += sprintf(buf+len, "Table "); - else - len += sprintf(buf+len, "Scalar "); - if(group[3]&0x2) - len += sprintf(buf+len, "x "); - else - len += sprintf(buf+len, " "); - if(group[3]&0x4) - len += sprintf(buf+len, "x "); - else - len += sprintf(buf+len, " "); - if(group[3]&0x8) - len += sprintf(buf+len, "x "); - else - len += sprintf(buf+len, " "); + len += sprintf(buf+len, "0x%04X ", result.group[i].group_number); + len += sprintf(buf+len, "%10d ", result.group[i].field_count); + len += sprintf(buf+len, "%8d ", result.group[i].row_count); + + properties = result.group[i].properties; + if (properties & 0x1) len += sprintf(buf+len, "Table "); + else len += sprintf(buf+len, "Scalar "); + if (properties & 0x2) len += sprintf(buf+len, " + "); + else len += sprintf(buf+len, " - "); + if (properties & 0x4) len += sprintf(buf+len, " + "); + else len += sprintf(buf+len, " - "); + if (properties & 0x8) len += sprintf(buf+len, " + "); + else len += sprintf(buf+len, " - "); len += sprintf(buf+len, "\n"); } - if(more) + if (result.more_flag) len += sprintf(buf+len, "There is more...\n"); spin_unlock(&i2o_proc_lock); @@ -1160,74 +1088,283 @@ int i2o_proc_read_groups(char *buf, char **start, off_t offset, int len, } -/* Generic group F005h - Private message extensions (table) */ -int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +/* Generic group F001h - Physical Device Table (table) */ +int i2o_proc_read_phys_device(char *buf, char **start, off_t offset, int len, + int *eof, void *data) { - struct i2o_controller *c = (struct i2o_controller*)data; + struct i2o_device *d = (struct i2o_device*)data; int token; int i; - int rows; - int more; - u16 work16[1024]; - u16 *field=work16; - spin_lock(&i2o_proc_lock); + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u32 adapter_id[64]; + } result; + spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - c, ADAPTER_TID, - 0xF000, -1, - NULL, 0, - &work16, sizeof(work16)); + d->controller, d->lct_data->tid, + 0xF001, -1, NULL, 0, + &result, sizeof(result)); - if (token<0) - switch (token) - { - case -ETIMEDOUT: - len += sprintf(buf, "Timeout reading table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - case -ENOMEM: - len += sprintf(buf, "No free memory to read the table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - default: - len += sprintf(buf, "Error reading field. BlockStatus %d\n", - token); - spin_unlock(&i2o_proc_lock); - return len; - } + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF001 Physical Device Table"); + spin_unlock(&i2o_proc_lock); + return len; + } - rows=work16[4]; - more=work16[5]; - - len += sprintf(buf+len, "Instance# OrgId FunctionCode\n"); + if (result.row_count) + len += sprintf(buf+len, "# AdapterId\n"); - field+=64; - for(i=0; i < rows; i++, field+=16) + for (i=0; i < result.row_count; i++) { - len += sprintf(buf+len, "%0#9x ", field[0]); - len += sprintf(buf+len, "%0#6x ", work16[1]); - len += sprintf(buf+len, "%0#6x", work16[2]); - - len += sprintf(buf+len, "\n"); + len += sprintf(buf+len, "%-2d", i); + len += sprintf(buf+len, "%#7x\n", result.adapter_id[i]); } - if(more) + if (result.more_flag) len += sprintf(buf+len, "There is more...\n"); spin_unlock(&i2o_proc_lock); - return len; } - -int i2o_proc_read_dev(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +/* Generic group F002h - Claimed Table (table) */ +int i2o_proc_read_claimed(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + struct i2o_device *d = (struct i2o_device*)data; + int token; + int i; + + struct { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u16 claimed_tid[64]; + } result; + + spin_lock(&i2o_proc_lock); + len = 0; + + token = i2o_query_table(I2O_PARAMS_TABLE_GET, + d->controller, d->lct_data->tid, + 0xF002, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF002 Claimed Table"); + spin_unlock(&i2o_proc_lock); + return len; + } + + if (result.row_count) + len += sprintf(buf+len, "# ClaimedTid\n"); + + for (i=0; i < result.row_count; i++) + { + len += sprintf(buf+len, "%-2d", i); + len += sprintf(buf+len, "%#7x\n", result.claimed_tid[i]); + } + + if (result.more_flag) + len += sprintf(buf+len, "There is more...\n"); + + spin_unlock(&i2o_proc_lock); + return len; +} + +/* Generic group F003h - User Table (table) */ +int i2o_proc_read_users(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + struct i2o_device *d = (struct i2o_device*)data; + int token; + int i; + + typedef struct _i2o_user_table + { + u16 instance; + u16 user_tid; + u8 claim_type; + u8 reserved1; + u16 reserved2; + } i2o_user_table; + + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_user_table user[64]; + } result; + + spin_lock(&i2o_proc_lock); + len = 0; + + token = i2o_query_table(I2O_PARAMS_TABLE_GET, + d->controller, d->lct_data->tid, + 0xF003, -1, NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF003 User Table"); + spin_unlock(&i2o_proc_lock); + return len; + } + + len += sprintf(buf+len, "# Instance UserTid ClaimType\n"); + + for(i=0; i < result.row_count; i++) + { + len += sprintf(buf+len, "%-3d", i); + len += sprintf(buf+len, "%#8x ", result.user[i].instance); + len += sprintf(buf+len, "%#7x ", result.user[i].user_tid); + len += sprintf(buf+len, "%#9x\n", result.user[i].claim_type); + } + + if (result.more_flag) + len += sprintf(buf+len, "There is more...\n"); + + spin_unlock(&i2o_proc_lock); + return len; +} + +/* Generic group F005h - Private message extensions (table) (optional) */ +int i2o_proc_read_priv_msgs(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + struct i2o_device *d = (struct i2o_device*)data; + int token; + int i; + + typedef struct _i2o_private + { + u16 ext_instance; + u16 organization_id; + u16 x_function_code; + } i2o_private; + + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + i2o_private extension[64]; + } result; + + spin_lock(&i2o_proc_lock); + + len = 0; + + token = i2o_query_table(I2O_PARAMS_TABLE_GET, + d->controller, d->lct_data->tid, + 0xF000, -1, + NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF005 Private Message Extensions (optional)"); + spin_unlock(&i2o_proc_lock); + return len; + } + + len += sprintf(buf+len, "Instance# OrgId FunctionCode\n"); + + for(i=0; i < result.row_count; i++) + { + len += sprintf(buf+len, "%0#9x ", result.extension[i].ext_instance); + len += sprintf(buf+len, "%0#6x ", result.extension[i].organization_id); + len += sprintf(buf+len, "%0#6x", result.extension[i].x_function_code); + + len += sprintf(buf+len, "\n"); + } + + if(result.more_flag) + len += sprintf(buf+len, "There is more...\n"); + + spin_unlock(&i2o_proc_lock); + + return len; +} + + +/* Generic group F006h - Authorized User Table (table) */ +int i2o_proc_read_authorized_users(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + struct i2o_device *d = (struct i2o_device*)data; + int token; + int i; + + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u32 alternate_tid[64]; + } result; + + spin_lock(&i2o_proc_lock); + len = 0; + + token = i2o_query_table(I2O_PARAMS_TABLE_GET, + d->controller, d->lct_data->tid, + 0xF006, -1, + NULL, 0, + &result, sizeof(result)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF006 Autohorized User Table"); + spin_unlock(&i2o_proc_lock); + return len; + } + + if (result.row_count) + len += sprintf(buf+len, "# AlternateTid\n"); + + for(i=0; i < result.row_count; i++) + { + len += sprintf(buf+len, "%-2d", i); + len += sprintf(buf+len, "%#7x ", result.alternate_tid[i]); + } + + if (result.more_flag) + len += sprintf(buf+len, "There is more...\n"); + + spin_unlock(&i2o_proc_lock); + return len; +} + + +/* Generic group F100h - Device Identity (scalar) */ +int i2o_proc_read_dev_identity(char *buf, char **start, off_t offset, int len, + int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number @@ -1240,14 +1377,11 @@ int i2o_proc_read_dev(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0xF100, // ParamGroup F100h (Device Identity) - -1, // all fields - &work32, - sizeof(work32)); + 0xF100, -1, + &work32, sizeof(work32)); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token ,"0xF100 Device Identity"); spin_unlock(&i2o_proc_lock); return len; } @@ -1290,44 +1424,45 @@ int i2o_proc_read_dev_name(char *buf, char **start, off_t offset, int len, } - -int i2o_proc_read_ddm(char *buf, char **start, off_t offset, int len, - int *eof, void *data) +/* Generic group F101h - DDM Identity (scalar) */ +int i2o_proc_read_ddm_identity(char *buf, char **start, off_t offset, int len, + int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[128]; - static u16 *work16 = (u16*)work32; int token; + struct + { + u16 ddm_tid; + u8 module_name[24]; + u8 module_rev[8]; + u8 sn_format; + u8 serial_number[12]; + u8 pad[256]; // allow up to 256 byte (max) serial number + } result; + spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0xF101, // ParamGroup F101h (DDM Identity) - -1, // all fields - &work32, - sizeof(work32)); + 0xF101, -1, + &result, sizeof(result)); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF101 DDM Identity"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "Registering DDM TID : 0x%03x\n", work16[0]&0xFFF); - len += sprintf(buf+len, "Module name : %s\n", chtostr((u8 *)(work16+1), 24)); - len += sprintf(buf+len, "Module revision : %s\n", chtostr((u8 *)(work16+13), 8)); + len += sprintf(buf, "Registering DDM TID : 0x%03x\n", result.ddm_tid); + len += sprintf(buf+len, "Module name : %s\n", chtostr(result.module_name, 24)); + len += sprintf(buf+len, "Module revision : %s\n", chtostr(result.module_rev, 8)); len += sprintf(buf+len, "Serial number : "); - len = print_serial_number(buf, len, - (u8*)(work16+17), - /* allow for SNLen plus - * possible trailing '\0' - */ - sizeof(work32)-(17*sizeof(u16))-2 - ); + len = print_serial_number(buf, len, result.serial_number, sizeof(result)-36); + /* allow for SNLen plus possible trailing '\0' */ + len += sprintf(buf+len, "\n"); spin_unlock(&i2o_proc_lock); @@ -1335,41 +1470,44 @@ int i2o_proc_read_ddm(char *buf, char **start, off_t offset, int len, return len; } +/* Generic group F102h - User Information (scalar) */ int i2o_proc_read_uinfo(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[256]; int token; - + + struct + { + u8 device_name[64]; + u8 service_name[64]; + u8 physical_location[64]; + u8 instance_number[4]; + } result; + spin_lock(&i2o_proc_lock); - len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0xF102, // ParamGroup F102h (User Information) - -1, // all fields - &work32, - sizeof(work32)); + 0xF102, -1, + &result, sizeof(result)); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF102 User Information"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "Device name : %s\n", chtostr((u8 *)work32, 64)); - len += sprintf(buf+len, "Service name : %s\n", chtostr((u8 *)(work32+16), 64)); - len += sprintf(buf+len, "Physical name : %s\n", chtostr((u8 *)(work32+32), 64)); - len += sprintf(buf+len, "Instance number : %s\n", chtostr((u8 *)(work32+48), 4)); - - spin_unlock(&i2o_proc_lock); + len += sprintf(buf, "Device name : %s\n", chtostr(result.device_name, 64)); + len += sprintf(buf+len, "Service name : %s\n", chtostr(result.service_name, 64)); + len += sprintf(buf+len, "Physical name : %s\n", chtostr(result.physical_location, 64)); + len += sprintf(buf+len, "Instance number : %s\n", chtostr(result.instance_number, 4)); + spin_unlock(&i2o_proc_lock); return len; } - +/* Generic group F103h - SGL Operating Limits (scalar) */ int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, int *eof, void *data) { @@ -1384,14 +1522,11 @@ int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0xF103, // ParamGroup F103h (SGL Operating Limits) - -1, // all fields - &work32, - sizeof(work32)); + 0xF103, -1, + &work32, sizeof(work32)); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF103 SGL Operating Limits"); spin_unlock(&i2o_proc_lock); return len; } @@ -1424,6 +1559,164 @@ int i2o_proc_read_sgl_limits(char *buf, char **start, off_t offset, int len, return len; } +/* Generic group F200h - Sensors (scalar) */ +int i2o_proc_read_sensors(char *buf, char **start, off_t offset, int len, + int *eof, void *data) +{ + struct i2o_device *d = (struct i2o_device*)data; + int token; + + struct + { + u16 sensor_instance; + u8 component; + u16 component_instance; + u8 sensor_class; + u8 sensor_type; + u8 scaling_exponent; + u32 actual_reading; + u32 minimum_reading; + u32 low2lowcat_treshold; + u32 lowcat2low_treshold; + u32 lowwarn2low_treshold; + u32 low2lowwarn_treshold; + u32 norm2lowwarn_treshold; + u32 lowwarn2norm_treshold; + u32 nominal_reading; + u32 hiwarn2norm_treshold; + u32 norm2hiwarn_treshold; + u32 high2hiwarn_treshold; + u32 hiwarn2high_treshold; + u32 hicat2high_treshold; + u32 hi2hicat_treshold; + u32 maximum_reading; + u8 sensor_state; + u16 event_enable; + } result; + + spin_lock(&i2o_proc_lock); + len = 0; + + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0xF200, -1, + &result, sizeof(result)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0xF200 Sensors (optional)"); + spin_unlock(&i2o_proc_lock); + return len; + } + + len += sprintf(buf+len, "Sensor instance : %d\n", result.sensor_instance); + + len += sprintf(buf+len, "Component : %d = ", result.component); + switch (result.component) + { + case 0: len += sprintf(buf+len, "Other"); + break; + case 1: len += sprintf(buf+len, "Planar logic Board"); + break; + case 2: len += sprintf(buf+len, "CPU"); + break; + case 3: len += sprintf(buf+len, "Chassis"); + break; + case 4: len += sprintf(buf+len, "Power Supply"); + break; + case 5: len += sprintf(buf+len, "Storage"); + break; + case 6: len += sprintf(buf+len, "External"); + break; + } + len += sprintf(buf+len,"\n"); + + len += sprintf(buf+len, "Component instance : %d\n", result.component_instance); + len += sprintf(buf+len, "Sensor class : %s\n", + result.sensor_class ? "Analog" : "Digital"); + + len += sprintf(buf+len, "Sensor type : %d = ",result.sensor_type); + switch (result.sensor_type) + { + case 0: len += sprintf(buf+len, "Other\n"); + break; + case 1: len += sprintf(buf+len, "Thermal\n"); + break; + case 2: len += sprintf(buf+len, "DC voltage (DC volts)\n"); + break; + case 3: len += sprintf(buf+len, "AC voltage (AC volts)\n"); + break; + case 4: len += sprintf(buf+len, "DC current (DC amps)\n"); + break; + case 5: len += sprintf(buf+len, "AC current (AC volts)\n"); + break; + case 6: len += sprintf(buf+len, "Door open\n"); + break; + case 7: len += sprintf(buf+len, "Fan operational\n"); + break; + } + + len += sprintf(buf+len, "Scaling exponent : %d\n", result.scaling_exponent); + len += sprintf(buf+len, "Actual reading : %d\n", result.actual_reading); + len += sprintf(buf+len, "Minimum reading : %d\n", result.minimum_reading); + len += sprintf(buf+len, "Low2LowCat treshold : %d\n", result.low2lowcat_treshold); + len += sprintf(buf+len, "LowCat2Low treshold : %d\n", result.lowcat2low_treshold); + len += sprintf(buf+len, "LowWarn2Low treshold : %d\n", result.lowwarn2low_treshold); + len += sprintf(buf+len, "Low2LowWarn treshold : %d\n", result.low2lowwarn_treshold); + len += sprintf(buf+len, "Norm2LowWarn treshold : %d\n", result.norm2lowwarn_treshold); + len += sprintf(buf+len, "LowWarn2Norm treshold : %d\n", result.lowwarn2norm_treshold); + len += sprintf(buf+len, "Nominal reading : %d\n", result.nominal_reading); + len += sprintf(buf+len, "HiWarn2Norm treshold : %d\n", result.hiwarn2norm_treshold); + len += sprintf(buf+len, "Norm2HiWarn treshold : %d\n", result.norm2hiwarn_treshold); + len += sprintf(buf+len, "High2HiWarn treshold : %d\n", result.high2hiwarn_treshold); + len += sprintf(buf+len, "HiWarn2High treshold : %d\n", result.hiwarn2high_treshold); + len += sprintf(buf+len, "HiCat2High treshold : %d\n", result.hicat2high_treshold); + len += sprintf(buf+len, "High2HiCat treshold : %d\n", result.hi2hicat_treshold); + len += sprintf(buf+len, "Maximum reading : %d\n", result.maximum_reading); + + len += sprintf(buf+len, "Sensor state : %d = ", result.sensor_state); + switch (result.sensor_state) + { + case 0: len += sprintf(buf+len, "Normal\n"); + break; + case 1: len += sprintf(buf+len, "Abnormal\n"); + break; + case 2: len += sprintf(buf+len, "Unknown\n"); + break; + case 3: len += sprintf(buf+len, "Low Catastrophic (LoCat)\n"); + break; + case 4: len += sprintf(buf+len, "Low (Low)\n"); + break; + case 5: len += sprintf(buf+len, "Low Warning (LoWarn)\n"); + break; + case 6: len += sprintf(buf+len, "High Warning (HiWarn)\n"); + break; + case 7: len += sprintf(buf+len, "High (High)\n"); + break; + case 8: len += sprintf(buf+len, "High Catastrophic (HiCat)\n"); + break; + } + + len += sprintf(buf+len, "Event_enable : 0x%02X\n", result.event_enable); + if (result.event_enable & 0x01) + len += sprintf(buf+len, "\tOperational state change. \n"); + if (result.event_enable & 0x02) + len += sprintf(buf+len, "\tLow catastrophic. \n"); + if (result.event_enable & 0x04) + len += sprintf(buf+len, "\tLow reading. \n"); + if (result.event_enable & 0x08) + len += sprintf(buf+len, "\tLow warning. \n"); + if (result.event_enable & 0x10) + len += sprintf(buf+len, "\tChange back to normal from out of range state. \n"); + if (result.event_enable & 0x20) + len += sprintf(buf+len, "\tHigh warning. \n"); + if (result.event_enable & 0x40) + len += sprintf(buf+len, "\tHigh reading. \n"); + if (result.event_enable & 0x80) + len += sprintf(buf+len, "\tHigh catastrophic. \n"); + + spin_unlock(&i2o_proc_lock); + return len; +} + static int print_serial_number(char *buff, int pos, u8 *serialno, int max_len) { @@ -1749,14 +2042,12 @@ int i2o_proc_read_lan_dev_info(char *buf, char **start, off_t offset, int len, int token; spin_lock(&i2o_proc_lock); - len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, 0x0000, -1, &work32, 56*4); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token, "0x0000 LAN Device Info"); spin_unlock(&i2o_proc_lock); return len; } @@ -1877,9 +2168,8 @@ int i2o_proc_read_lan_mac_addr(char *buf, char **start, off_t offset, int len, token = i2o_query_scalar(d->controller, d->lct_data->tid, 0x0001, -1, &work32, 48*4); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0001 LAN MAC Address"); spin_unlock(&i2o_proc_lock); return len; } @@ -1955,51 +2245,44 @@ int i2o_proc_read_lan_mcast_addr(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u32 field32[64]; - static u8 *field8 = (u8 *)field32; - static u16 *field16 = (u16 *)field32; int token; int i; + u8 mc_addr[8]; + + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u8 mc_addr[256][8]; + } result; spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data->tid, 0x0002, -1, - NULL, 0, &field32, sizeof(field32)); - - if (token<0) - switch (token) { - case -ETIMEDOUT: - len += sprintf(buf, "Timeout reading table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - case -ENOMEM: - len += sprintf(buf, "No free memory to read the table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - default: - len += sprintf(buf, "Error reading field. BlockStatus %d\n", - token); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf, "RowCount=%d, MoreFlag=%d\n", - field16[0], field16[1]); + d->controller, d->lct_data->tid, 0x0002, -1, + NULL, 0, &result, sizeof(result)); - field8=(u8 *)&field16[2]; + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x002 LAN Multicast MAC Address"); + spin_unlock(&i2o_proc_lock); + return len; + } - for(i=0; icontroller, d->lct_data->tid, 0x0003, -1, &work32, 9*4); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0003 LAN Batch Control"); spin_unlock(&i2o_proc_lock); return len; } @@ -2050,8 +2332,8 @@ int i2o_proc_read_lan_batch_control(char *buf, char **start, off_t offset, work32[4]/10); } - len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]); - len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]); + len += sprintf(buf+len, "Max Rx batch count : %d\n", work32[5]); + len += sprintf(buf+len, "Max Rx batch delay : %d\n", work32[6]); if(d->i2oversion == 0x00) { len += sprintf(buf+len, @@ -2079,9 +2361,8 @@ int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len, token = i2o_query_scalar(d->controller, d->lct_data->tid, 0x0004, -1, &work32, 20); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0004 LAN Operation"); spin_unlock(&i2o_proc_lock); return len; } @@ -2090,7 +2371,7 @@ int i2o_proc_read_lan_operation(char *buf, char **start, off_t offset, int len, len += sprintf(buf+len, "Transmission error reporting : %s\n", (work32[1]&1)?"on":"off"); len += sprintf(buf+len, "Bad packet handling : %s\n", - (work32[1]&0x2)?"by host":"by DDM"); + (work32[1]&0x2)?"by host":"by DDM"); len += sprintf(buf+len, "Packet orphan limit : %d\n", work32[2]); len += sprintf(buf+len, "Tx modes :\n"); @@ -2134,52 +2415,72 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u32 work32[9]; - static u8 *work8 = (u8*)work32; - static u64 *work64 = (u64*)work32; int token; + struct + { + u32 connector_type; + u32 connection_type; + u64 current_tx_wire_speed; + u64 current_rx_wire_speed; + u8 duplex_mode; + u8 link_status; + u8 reserved; + u8 duplex_mode_target; + u32 connector_type_target; + u32 connection_type_target; + } result; + spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0005, -1, &work32, 36); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + 0x0005, -1, &result, sizeof(result)); + if (token < 0) { + len += i2o_report_query_status(buf+len, token, "0x0005 LAN Media Operation"); spin_unlock(&i2o_proc_lock); return len; } len += sprintf(buf, "Connector type : %s\n", - i2o_get_connector_type(work32[0])); + i2o_get_connector_type(result.connector_type)); len += sprintf(buf+len, "Connection type : %s\n", - i2o_get_connection_type(work32[1])); - - len += sprintf(buf+len, "Current Tx wire speed : %d bps\n", (int)work64[1]); - len += sprintf(buf+len, "Current Rx wire speed : %d bps\n", (int)work64[2]); + i2o_get_connection_type(result.connection_type)); - len += sprintf(buf+len, "Duplex mode : %s duplex\n", - (work8[24]&1)?"Full":"Half"); + len += sprintf(buf+len, "Current Tx wire speed : %d bps\n", (int)result.current_tx_wire_speed); + len += sprintf(buf+len, "Current Rx wire speed : %d bps\n", (int)result.current_rx_wire_speed); + len += sprintf(buf+len, "Duplex mode : %s duplex\n", + (result.duplex_mode)?"Full":"Half"); + len += sprintf(buf+len, "Link status : "); - if(work8[25] == 0x00) + switch (result.link_status) + { + case 0x00: len += sprintf(buf+len, "Unknown\n"); - else if(work8[25] == 0x01) + break; + case 0x01: len += sprintf(buf+len, "Normal\n"); - else if(work8[25] == 0x02) + break; + case 0x02: len += sprintf(buf+len, "Failure\n"); - else if(work8[25] == 0x03) + break; + case 0x03: len += sprintf(buf+len, "Reset\n"); - else + break; + default: len += sprintf(buf+len, "Unspecified\n"); - - if (d->i2oversion == 0x00) { /* Reserved in 1.53 and 2.0 */ + } + + if (d->i2oversion == 0x00) /* Reserved in 1.53 and 2.0 */ + { len += sprintf(buf+len, "Bad packets handled by : %s\n", - (work8[26] == 0xFF)?"host":"DDM"); + (result.reserved == 0xFF)?"host":"DDM"); } - if (d->i2oversion != 0x00) { + else + { len += sprintf(buf+len, "Duplex mode target : "); - switch (work8[27]) { + switch (result.duplex_mode_target) + { case 0: len += sprintf(buf+len, "Half duplex\n"); break; @@ -2188,69 +2489,59 @@ int i2o_proc_read_lan_media_operation(char *buf, char **start, off_t offset, break; default: len += sprintf(buf+len, "\n"); - break; } len += sprintf(buf+len, "Connector type target : %s\n", - i2o_get_connector_type(work32[7])); + i2o_get_connector_type(result.connector_type_target)); len += sprintf(buf+len, "Connection type target : %s\n", - i2o_get_connection_type(work32[8])); + i2o_get_connection_type(result.connection_type_target)); } spin_unlock(&i2o_proc_lock); return len; } -/* LAN group 0006h - Alternate address (table) */ +/* LAN group 0006h - Alternate address (table) (optional) */ int i2o_proc_read_lan_alt_addr(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u32 field32[64]; - static u8 *field8 = (u8 *)field32; - static u16 *field16 = (u16 *)field32; int token; int i; + u8 alt_addr[8]; + struct + { + u16 result_count; + u16 pad; + u16 block_size; + u8 block_status; + u8 error_info_size; + u16 row_count; + u16 more_flag; + u8 alt_addr[256][8]; + } result; spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_table(I2O_PARAMS_TABLE_GET, - d->controller, d->lct_data->tid, 0x0006, -1, - NULL, 0, &field32, sizeof(field32)); + d->controller, d->lct_data->tid, + 0x0006, -1, NULL, 0, &result, sizeof(result)); - if (token<0) - switch (token) { - case -ETIMEDOUT: - len += sprintf(buf, "Timeout reading table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - case -ENOMEM: - len += sprintf(buf, "No free memory to read the table.\n"); - spin_unlock(&i2o_proc_lock); - return len; - break; - default: - len += sprintf(buf, "Error reading field. BlockStatus %d\n", - token); - spin_unlock(&i2o_proc_lock); - return len; - } - - len += sprintf(buf,"RowCount=%d, MoreFlag=%d\n", field16[0], - field16[1]); - - field8=(u8 *)&field16[2]; + if (token < 0) { + len += i2o_report_query_status(buf+len, token, "0x0006 LAN Alternate Address (optional)"); + spin_unlock(&i2o_proc_lock); + return len; + } - for(i=0; icontroller, d->lct_data->tid, 0x0007, -1, &work32, 8*4); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0007 LAN Transmit Info"); spin_unlock(&i2o_proc_lock); return len; } @@ -2304,12 +2594,15 @@ int i2o_proc_read_lan_tx_info(char *buf, char **start, off_t offset, int len, len += sprintf(buf+len, " RSVP checksum\n"); if(work32[4]&0x00001000) len += sprintf(buf+len, " ICMP checksum\n"); - if (d->i2oversion == 0x00) { + if (d->i2oversion == 0x00) + { if(work32[4]&0x00008000) len += sprintf(buf+len, " Loopback enabled\n"); if(work32[4]&0x00010000) len += sprintf(buf+len, " Loopback suppression enabled\n"); - } else { + } + else + { if(work32[4]&0x00010000) len += sprintf(buf+len, " Loopback enabled\n"); if(work32[4]&0x00020000) @@ -2333,9 +2626,8 @@ int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len, token = i2o_query_scalar(d->controller, d->lct_data->tid, 0x0008, -1, &work32, 8*4); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0008 LAN Receive Info"); spin_unlock(&i2o_proc_lock); return len; } @@ -2354,288 +2646,345 @@ int i2o_proc_read_lan_rx_info(char *buf, char **start, off_t offset, int len, return len; } +static int i2o_report_opt_field(char *buf, char *field_name, + int field_nbr, int supp_fields, u64 *value) +{ + if (supp_fields & (1 << field_nbr)) + return sprintf(buf, "%-24s : " FMT_U64_HEX "\n", field_name, U64_VAL(value)); + else + return sprintf(buf, "%-24s : Not supported\n", field_name); +} /* LAN group 0100h - LAN Historical statistics (scalar) */ +/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */ +/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics (scalar) */ +/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics (scalar) */ + int i2o_proc_read_lan_hist_stats(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[9]; int token; + struct + { + u64 tx_packets; + u64 tx_bytes; + u64 rx_packets; + u64 rx_bytes; + u64 tx_errors; + u64 rx_errors; + u64 rx_dropped; + u64 adapter_resets; + u64 adapter_suspends; + } stats; // 0x0100 + + static u64 supp_groups[4]; // 0x0180 + + struct + { + u64 tx_retries; + u64 tx_directed_bytes; + u64 tx_directed_packets; + u64 tx_multicast_bytes; + u64 tx_multicast_packets; + u64 tx_broadcast_bytes; + u64 tx_broadcast_packets; + u64 tx_group_addr_packets; + u64 tx_short_packets; + } tx_stats; // 0x0182 + + struct + { + u64 rx_crc_errors; + u64 rx_directed_bytes; + u64 rx_directed_packets; + u64 rx_multicast_bytes; + u64 rx_multicast_packets; + u64 rx_broadcast_bytes; + u64 rx_broadcast_packets; + u64 rx_group_addr_packets; + u64 rx_short_packets; + u64 rx_long_packets; + u64 rx_runt_packets; + } rx_stats; // 0x0183 + + struct + { + u64 ipv4_generate; + u64 ipv4_validate_success; + u64 ipv4_validate_errors; + u64 tcp_generate; + u64 tcp_validate_success; + u64 tcp_validate_errors; + u64 udp_generate; + u64 udp_validate_success; + u64 udp_validate_errors; + u64 rsvp_generate; + u64 rsvp_validate_success; + u64 rsvp_validate_errors; + u64 icmp_generate; + u64 icmp_validate_success; + u64 icmp_validate_errors; + } chksum_stats; // 0x0184 + spin_lock(&i2o_proc_lock); len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0100, -1, &work64, 9*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + 0x0100, -1, &stats, sizeof(stats)); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x100 LAN Statistics"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "Tx packets : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); + len += sprintf(buf+len, "Tx packets : " FMT_U64_HEX "\n", + U64_VAL(&stats.tx_packets)); len += sprintf(buf+len, "Tx bytes : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); + U64_VAL(&stats.tx_bytes)); len += sprintf(buf+len, "Rx packets : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); + U64_VAL(&stats.rx_packets)); len += sprintf(buf+len, "Rx bytes : " FMT_U64_HEX "\n", - U64_VAL(&work64[3])); + U64_VAL(&stats.rx_bytes)); len += sprintf(buf+len, "Tx errors : " FMT_U64_HEX "\n", - U64_VAL(&work64[4])); + U64_VAL(&stats.tx_errors)); len += sprintf(buf+len, "Rx errors : " FMT_U64_HEX "\n", - U64_VAL(&work64[5])); + U64_VAL(&stats.rx_errors)); len += sprintf(buf+len, "Rx dropped : " FMT_U64_HEX "\n", - U64_VAL(&work64[6])); + U64_VAL(&stats.rx_dropped)); len += sprintf(buf+len, "Adapter resets : " FMT_U64_HEX "\n", - U64_VAL(&work64[7])); + U64_VAL(&stats.adapter_resets)); len += sprintf(buf+len, "Adapter suspends : " FMT_U64_HEX "\n", - U64_VAL(&work64[8])); - - spin_unlock(&i2o_proc_lock); - return len; -} - - -/* LAN group 0180h - Supported Optional Historical Statistics (scalar) */ -int i2o_proc_read_lan_supp_opt_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[4]; - int token; + U64_VAL(&stats.adapter_suspends)); - spin_lock(&i2o_proc_lock); - - len = 0; + /* Optional statistics follows */ + /* Get 0x0180 to see which optional groups/fields are supported */ token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0180, -1, &work64, 4*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + 0x0180, -1, &supp_groups, sizeof(supp_groups)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token, "0x180 LAN Supported Optional Statistics"); spin_unlock(&i2o_proc_lock); return len; } - if (d->i2oversion == 0x00) - len += sprintf(buf, "Supported stats : " FMT_U64_HEX " \n", - U64_VAL(&work64[0])); - else + if (supp_groups[1]) /* 0x0182 */ { - len += sprintf(buf, "Supported stats (0182h) : " FMT_U64_HEX " \n", - U64_VAL(&work64[1])); - len += sprintf(buf, "Supported stats (0183h) : " FMT_U64_HEX " \n", - U64_VAL(&work64[2])); - len += sprintf(buf, "Supported stats (0184h) : " FMT_U64_HEX " \n", - U64_VAL(&work64[3])); - } - - spin_unlock(&i2o_proc_lock); - return len; -} - - -/* LAN group 0182h - Optional Non Media Specific Transmit Historical Statistics - * (scalar) */ -int i2o_proc_read_lan_opt_tx_hist_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[9]; - int token; - - spin_lock(&i2o_proc_lock); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0182, -1, &tx_stats, sizeof(tx_stats)); - len = 0; + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x182 LAN Optional Tx Historical Statistics"); + spin_unlock(&i2o_proc_lock); + return len; + } - token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0182, -1, &work64, 9*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); - spin_unlock(&i2o_proc_lock); - return len; + len += sprintf(buf+len, "==== Optional TX statistics (group 0182h)\n"); + + len += i2o_report_opt_field(buf+len, "Tx RetryCount", + 0, supp_groups[1], &tx_stats.tx_retries); + len += i2o_report_opt_field(buf+len, "Tx DirectedBytes", + 1, supp_groups[1], &tx_stats.tx_directed_bytes); + len += i2o_report_opt_field(buf+len, "Tx DirectedPackets", + 2, supp_groups[1], &tx_stats.tx_directed_packets); + len += i2o_report_opt_field(buf+len, "Tx MulticastBytes", + 3, supp_groups[1], &tx_stats.tx_multicast_bytes); + len += i2o_report_opt_field(buf+len, "Tx MulticastPackets", + 4, supp_groups[1], &tx_stats.tx_multicast_packets); + len += i2o_report_opt_field(buf+len, "Tx BroadcastBytes", + 5, supp_groups[1], &tx_stats.tx_broadcast_bytes); + len += i2o_report_opt_field(buf+len, "Tx BroadcastPackets", + 6, supp_groups[1], &tx_stats.tx_broadcast_packets); + len += i2o_report_opt_field(buf+len, "Tx TotalGroupAddrPackets", + 7, supp_groups[1], &tx_stats.tx_group_addr_packets); + len += i2o_report_opt_field(buf+len, "Tx TotalPacketsTooShort", + 8, supp_groups[1], &tx_stats.tx_short_packets); } - len += sprintf(buf, "TxRetryCount : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); - len += sprintf(buf+len, "DirectedBytesTx : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); - len += sprintf(buf+len, "DirectedPacketsTx : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); - len += sprintf(buf+len, "MulticastBytesTx : " FMT_U64_HEX "\n", - U64_VAL(&work64[3])); - len += sprintf(buf+len, "MulticastPacketsTx : " FMT_U64_HEX "\n", - U64_VAL(&work64[4])); - len += sprintf(buf+len, "BroadcastBytesTx : " FMT_U64_HEX "\n", - U64_VAL(&work64[5])); - len += sprintf(buf+len, "BroadcastPacketsTx : " FMT_U64_HEX "\n", - U64_VAL(&work64[6])); - len += sprintf(buf+len, "TotalGroupAddrTxCount : " FMT_U64_HEX "\n", - U64_VAL(&work64[7])); - len += sprintf(buf+len, "TotalTxPacketsTooShort : " FMT_U64_HEX "\n", - U64_VAL(&work64[8])); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0183h - Optional Non Media Specific Receive Historical Statistics - * (scalar) */ -int i2o_proc_read_lan_opt_rx_hist_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[11]; - int token; + if (supp_groups[2]) /* 0x0183 */ + { + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0183, -1, &rx_stats, sizeof(rx_stats)); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x183 LAN Optional Rx Historical Stats"); + spin_unlock(&i2o_proc_lock); + return len; + } - spin_lock(&i2o_proc_lock); + len += sprintf(buf+len, "==== Optional RX statistics (group 0183h)\n"); + + len += i2o_report_opt_field(buf+len, "Rx CRCErrorCount", + 0, supp_groups[2], &rx_stats.rx_crc_errors); + len += i2o_report_opt_field(buf+len, "Rx DirectedBytes", + 1, supp_groups[2], &rx_stats.rx_directed_bytes); + len += i2o_report_opt_field(buf+len, "Rx DirectedPackets", + 2, supp_groups[2], &rx_stats.rx_directed_packets); + len += i2o_report_opt_field(buf+len, "Rx MulticastBytes", + 3, supp_groups[2], &rx_stats.rx_multicast_bytes); + len += i2o_report_opt_field(buf+len, "Rx MulticastPackets", + 4, supp_groups[2], &rx_stats.rx_multicast_packets); + len += i2o_report_opt_field(buf+len, "Rx BroadcastBytes", + 5, supp_groups[2], &rx_stats.rx_broadcast_bytes); + len += i2o_report_opt_field(buf+len, "Rx BroadcastPackets", + 6, supp_groups[2], &rx_stats.rx_broadcast_packets); + len += i2o_report_opt_field(buf+len, "Rx TotalGroupAddrPackets", + 7, supp_groups[2], &rx_stats.rx_group_addr_packets); + len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooShort", + 8, supp_groups[2], &rx_stats.rx_short_packets); + len += i2o_report_opt_field(buf+len, "Rx TotalPacketsTooLong", + 9, supp_groups[2], &rx_stats.rx_long_packets); + len += i2o_report_opt_field(buf+len, "Rx TotalPacketsRunt", + 10, supp_groups[2], &rx_stats.rx_runt_packets); + } + + if (supp_groups[3]) /* 0x0184 */ + { + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0184, -1, &chksum_stats, sizeof(chksum_stats)); - len = 0; + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x184 LAN Optional Chksum Historical Stats"); + spin_unlock(&i2o_proc_lock); + return len; + } - token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0183, -1, &work64, 11*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); - spin_unlock(&i2o_proc_lock); - return len; + len += sprintf(buf+len, "==== Optional CHKSUM statistics (group 0x0184)\n"); + + len += i2o_report_opt_field(buf+len, "IPv4 Generate", + 0, supp_groups[3], &chksum_stats.ipv4_generate); + len += i2o_report_opt_field(buf+len, "IPv4 ValidateSuccess", + 1, supp_groups[3], &chksum_stats.ipv4_validate_success); + len += i2o_report_opt_field(buf+len, "IPv4 ValidateError", + 2, supp_groups[3], &chksum_stats.ipv4_validate_errors); + len += i2o_report_opt_field(buf+len, "TCP Generate", + 3, supp_groups[3], &chksum_stats.tcp_generate); + len += i2o_report_opt_field(buf+len, "TCP ValidateSuccess", + 4, supp_groups[3], &chksum_stats.tcp_validate_success); + len += i2o_report_opt_field(buf+len, "TCP ValidateError", + 5, supp_groups[3], &chksum_stats.tcp_validate_errors); + len += i2o_report_opt_field(buf+len, "UDP Generate", + 6, supp_groups[3], &chksum_stats.udp_generate); + len += i2o_report_opt_field(buf+len, "UDP ValidateSuccess", + 7, supp_groups[3], &chksum_stats.udp_validate_success); + len += i2o_report_opt_field(buf+len, "UDP ValidateError", + 8, supp_groups[3], &chksum_stats.udp_validate_errors); + len += i2o_report_opt_field(buf+len, "RSVP Generate", + 9, supp_groups[3], &chksum_stats.rsvp_generate); + len += i2o_report_opt_field(buf+len, "RSVP ValidateSuccess", + 10, supp_groups[3], &chksum_stats.rsvp_validate_success); + len += i2o_report_opt_field(buf+len, "RSVP ValidateError", + 11, supp_groups[3], &chksum_stats.rsvp_validate_errors); + len += i2o_report_opt_field(buf+len, "ICMP Generate", + 12, supp_groups[3], &chksum_stats.icmp_generate); + len += i2o_report_opt_field(buf+len, "ICMP ValidateSuccess", + 13, supp_groups[3], &chksum_stats.icmp_validate_success); + len += i2o_report_opt_field(buf+len, "ICMP ValidateError", + 14, supp_groups[3], &chksum_stats.icmp_validate_errors); } - len += sprintf(buf, "ReceiveCRCErrorCount : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); - len += sprintf(buf+len, "DirectedBytesRx : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); - len += sprintf(buf+len, "DirectedPacketsRx : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); - len += sprintf(buf+len, "MulticastBytesRx : " FMT_U64_HEX "\n", - U64_VAL(&work64[3])); - len += sprintf(buf+len, "MulticastPacketsRx : " FMT_U64_HEX "\n", - U64_VAL(&work64[4])); - len += sprintf(buf+len, "BroadcastBytesRx : " FMT_U64_HEX "\n", - U64_VAL(&work64[5])); - len += sprintf(buf+len, "BroadcastPacketsRx : " FMT_U64_HEX "\n", - U64_VAL(&work64[6])); - len += sprintf(buf+len, "TotalGroupAddrRxCount : " FMT_U64_HEX "\n", - U64_VAL(&work64[7])); - len += sprintf(buf+len, "TotalRxPacketsTooShort : " FMT_U64_HEX "\n", - U64_VAL(&work64[8])); - len += sprintf(buf+len, "TotalRxPacketsTooLong : " FMT_U64_HEX "\n", - U64_VAL(&work64[9])); - len += sprintf(buf+len, "TotalRuntPacketsReceived : " FMT_U64_HEX "\n", - U64_VAL(&work64[10])); - spin_unlock(&i2o_proc_lock); return len; } /* LAN group 0200h - Required Ethernet Statistics (scalar) */ +/* LAN group 0280h - Optional Ethernet Statistics Supported (scalar) */ +/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */ int i2o_proc_read_lan_eth_stats(char *buf, char **start, off_t offset, int len, int *eof, void *data) { struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[8]; int token; + struct + { + u64 rx_align_errors; + u64 tx_one_collisions; + u64 tx_multiple_collisions; + u64 tx_deferred; + u64 tx_late_collisions; + u64 tx_max_collisions; + u64 tx_carrier_lost; + u64 tx_excessive_deferrals; + } stats; + + static u64 supp_fields; + struct + { + u64 rx_overrun; + u64 tx_underrun; + u64 tx_heartbeat_failure; + } hist_stats; - spin_lock(&i2o_proc_lock); - + spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0200, -1, &work64, 8*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0200, -1, &stats, sizeof(stats)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0200 LAN Ethernet Statistics"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "Rx alignment errors : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); + len += sprintf(buf+len, "Rx alignment errors : " FMT_U64_HEX "\n", + U64_VAL(&stats.rx_align_errors)); len += sprintf(buf+len, "Tx one collisions : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); + U64_VAL(&stats.tx_one_collisions)); len += sprintf(buf+len, "Tx multicollisions : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); + U64_VAL(&stats.tx_multiple_collisions)); len += sprintf(buf+len, "Tx deferred : " FMT_U64_HEX "\n", - U64_VAL(&work64[3])); + U64_VAL(&stats.tx_deferred)); len += sprintf(buf+len, "Tx late collisions : " FMT_U64_HEX "\n", - U64_VAL(&work64[4])); + U64_VAL(&stats.tx_late_collisions)); len += sprintf(buf+len, "Tx max collisions : " FMT_U64_HEX "\n", - U64_VAL(&work64[5])); + U64_VAL(&stats.tx_max_collisions)); len += sprintf(buf+len, "Tx carrier lost : " FMT_U64_HEX "\n", - U64_VAL(&work64[6])); + U64_VAL(&stats.tx_carrier_lost)); len += sprintf(buf+len, "Tx excessive deferrals : " FMT_U64_HEX "\n", - U64_VAL(&work64[7])); + U64_VAL(&stats.tx_excessive_deferrals)); - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0280h - Supported Ethernet Historical Statistics (scalar) */ -int i2o_proc_read_lan_supp_eth_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[1]; - int token; - - spin_lock(&i2o_proc_lock); + /* Optional Ethernet statistics follows */ + /* Get 0x0280 to see which optional fields are supported */ - len = 0; + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0280, -1, &supp_fields, sizeof(supp_fields)); - token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0280, -1, &work64, 8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0280 LAN Supported Optional Ethernet Statistics"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "Supported stats : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); - - spin_unlock(&i2o_proc_lock); - return len; -} - -/* LAN group 0281h - Optional Ethernet Historical Statistics (scalar) */ -int i2o_proc_read_lan_opt_eth_stats(char *buf, char **start, off_t offset, - int len, int *eof, void *data) -{ - struct i2o_device *d = (struct i2o_device*)data; - static u64 work64[3]; - int token; + if (supp_fields) /* 0x0281 */ + { + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0281, -1, &stats, sizeof(stats)); - spin_lock(&i2o_proc_lock); + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0281 LAN Optional Ethernet Statistics"); + spin_unlock(&i2o_proc_lock); + return len; + } - len = 0; + len += sprintf(buf+len, "==== Optional ETHERNET statistics (group 0x0281)\n"); - token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0281, -1, &work64, 3*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); - spin_unlock(&i2o_proc_lock); - return len; + len += i2o_report_opt_field(buf+len, "Rx Overrun", + 0, supp_fields, &hist_stats.rx_overrun); + len += i2o_report_opt_field(buf+len, "Tx Underrun", + 1, supp_fields, &hist_stats.tx_underrun); + len += i2o_report_opt_field(buf+len, "Tx HeartbeatFailure", + 2, supp_fields, &hist_stats.tx_heartbeat_failure); } - len += sprintf(buf, "Rx overrun : " FMT_U64_HEX "\n", - U64_VAL(&work64[0])); - len += sprintf(buf, "Tx underrun : " FMT_U64_HEX "\n", - U64_VAL(&work64[1])); - len += sprintf(buf, "Tx heartbeat failure : " FMT_U64_HEX "\n", - U64_VAL(&work64[2])); - spin_unlock(&i2o_proc_lock); return len; } /* LAN group 0300h - Required Token Ring Statistics (scalar) */ +/* LAN group 0380h, 0381h - Optional Statistics not yet defined (TODO) */ int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset, int len, int *eof, void *data) { @@ -2663,15 +3012,14 @@ int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset, "Signal Loss" }; - spin_lock(&i2o_proc_lock); - + spin_lock(&i2o_proc_lock); len = 0; - token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0300, -1, &work64, 13*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + token = i2o_query_scalar(d->controller, d->lct_data->tid, + 0x0300, -1, &work64, sizeof(work64)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0300 Token Ring Statistics"); spin_unlock(&i2o_proc_lock); return len; } @@ -2707,6 +3055,7 @@ int i2o_proc_read_lan_tr_stats(char *buf, char **start, off_t offset, } /* LAN group 0400h - Required FDDI Statistics (scalar) */ +/* LAN group 0480h, 0481h - Optional Statistics, not yet defined (TODO) */ int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset, int len, int *eof, void *data) { @@ -2758,19 +3107,18 @@ int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset, }; spin_lock(&i2o_proc_lock); - len = 0; token = i2o_query_scalar(d->controller, d->lct_data->tid, - 0x0400, -1, &work64, 11*8); - if(token < 0) - { - len += sprintf(buf, "Timeout waiting for reply from IOP\n"); + 0x0400, -1, &work64, sizeof(work64)); + + if (token < 0) { + len += i2o_report_query_status(buf+len, token,"0x0400 FDDI Required Statistics"); spin_unlock(&i2o_proc_lock); return len; } - len += sprintf(buf, "ConfigurationState : %s\n", conf_state[work64[0]]); + len += sprintf(buf+len, "ConfigurationState : %s\n", conf_state[work64[0]]); len += sprintf(buf+len, "UpstreamNode : " FMT_U64_HEX "\n", U64_VAL(&work64[1])); len += sprintf(buf+len, "DownStreamNode : " FMT_U64_HEX "\n", @@ -2780,7 +3128,7 @@ int i2o_proc_read_lan_fddi_stats(char *buf, char **start, off_t offset, len += sprintf(buf+len, "FramesLost : " FMT_U64_HEX "\n", U64_VAL(&work64[4])); len += sprintf(buf+len, "RingMgmtState : %s\n", ring_state[work64[5]]); - len += sprintf(buf+len, "LCTFailures: " FMT_U64_HEX "\n", + len += sprintf(buf+len, "LCTFailures : " FMT_U64_HEX "\n", U64_VAL(&work64[6])); len += sprintf(buf+len, "LEMRejects : " FMT_U64_HEX "\n", U64_VAL(&work64[7])); diff --git a/drivers/i2o/i2o_proc.h b/drivers/i2o/i2o_proc.h deleted file mode 100644 index f2fe7185465f..000000000000 --- a/drivers/i2o/i2o_proc.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef i2oproc_h -#define i2oproc_h - -/* - * Fixme: make this dependent on architecture - * The official header files to this already...but we can't use them - */ -#define I2O_64BIT_CONTEXT 0 - -typedef struct _i2o_msg { - u8 ver_offset; - u8 msg_flags; - u16 msg_size; - u32 target_addr:12; - u32 initiator_addr:12; - u32 function:8; - u32 init_context; /* FIXME: 64-bit support! */ -} i2o_msg, *pi2o_msg; - -typedef struct _i2o_reply_message { - i2o_msg msg_frame; - u32 tctx; /* FIXME: 64-bit */ - u16 detailed_status_code; - u8 reserved; - u8 req_status; -} i2o_reply_msg, *pi2o_reply_msg; - -typedef struct _i2o_mult_reply_message { - i2o_msg msg_frame; - u32 tctx; /* FIXME: 64-bit */ - u16 detailed_status_code; - u8 reserved; - u8 req_status; -} i2o_mult_reply_msg, *pi2o_mult_reply_msg; - -#endif /* i2oproc_h */ diff --git a/drivers/i2o/i2o_scsi.c b/drivers/i2o/i2o_scsi.c index 3d4e7aaff34a..e383dbb4d3b5 100644 --- a/drivers/i2o/i2o_scsi.c +++ b/drivers/i2o/i2o_scsi.c @@ -587,7 +587,7 @@ int i2o_scsi_queuecommand(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) m = I2O_POST_READ32(c); } while(m==0xFFFFFFFF); - msg = c->mem_offset + m; + msg = (u32 *)(c->mem_offset + m); /* * Put together a scsi execscb message diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index a9125785d57a..15959e697555 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c @@ -781,7 +781,7 @@ static void hardware_send_packet(struct net_device *dev, void *buf, short length isa_memcpy_toio(write_ptr+2, buf, length); /* Set the old command link pointing to this send packet. */ - isa_isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link); + isa_writew(tx_block,dev->mem_start + lp->tx_cmd_link); lp->tx_cmd_link = tx_block + 20; /* Set the next free tx region. */ diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 490c0f381886..a68c55dfb7c0 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -3,8 +3,20 @@ # Makefile for the Linux network (ethercard) device drivers. # +O_OBJS := +M_OBJS := +MX_OBJS := + +# Object file lists. + +obj-y := +obj-m := +obj-n := +obj- := + SUB_DIRS := -MOD_SUB_DIRS := $(SUB_DIRS) +MOD_SUB_DIRS := +MOD_IN_SUB_DIRS := ALL_SUB_DIRS := $(SUB_DIRS) fc hamradio irda pcmcia tokenring wan L_TARGET := net.a @@ -12,18 +24,11 @@ L_OBJS := auto_irq.o M_OBJS := MOD_LIST_NAME := NET_MODULES -# Need these to keep track of whether the 7990 (LANCE), 8390, PPP and SLHC -# modules should really go in the kernel or a module. -CONFIG_8390_BUILTIN := -CONFIG_8390_MODULE := -CONFIG_SLHC_BUILTIN := -CONFIG_SLHC_MODULE := -CONFIG_PPPDEF_BUILTIN := -CONFIG_PPPDEF_MODULE := -CONFIG_7990_BUILTIN := -CONFIG_7990_MODULE := -CONFIG_82596_BUILTIN := -CONFIG_82596_MODULE := +# All of the (potential) objects that export symbols. +# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. + +export-objs := 8390.o arcnet.o arlan.o ppp_async.o \ + ppp_generic.o slhc.o ifeq ($(CONFIG_PCMCIA),y) SUB_DIRS += pcmcia @@ -34,1077 +39,238 @@ else endif endif -ifeq ($(CONFIG_ISDN),y) - ifeq ($(CONFIG_ISDN_PPP),y) - CONFIG_SLHC_BUILTIN = y - CONFIG_PPPDEF_BUILTIN = y - endif -else - ifeq ($(CONFIG_ISDN),m) - ifeq ($(CONFIG_ISDN_PPP),y) - CONFIG_SLHC_MODULE = y - CONFIG_PPPDEF_MODULE = y - endif - endif -endif - -ifeq ($(CONFIG_NET),y) -L_OBJS += Space.o setup.o net_init.o loopback.o -endif - -ifeq ($(CONFIG_SEEQ8005),y) -L_OBJS += seeq8005.o -endif - -ifeq ($(CONFIG_ETHERTAP),y) -L_OBJS += ethertap.o -else - ifeq ($(CONFIG_ETHERTAP),m) - M_OBJS += ethertap.o - endif -endif - -ifeq ($(CONFIG_NET_SB1000),y) -L_OBJS += sb1000.o -else - ifeq ($(CONFIG_NET_SB1000),m) - M_OBJS += sb1000.o - endif -endif - -ifeq ($(CONFIG_DAYNAPORT), y) -L_OBJS += daynaport.o -CONFIG_8390_BUILTIN = y -endif - -ifeq ($(CONFIG_APNE),y) -L_OBJS += apne.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_APNE),m) - M_OBJS += apne.o - CONFIG_8390_MODULE = y - endif -endif - -ifeq ($(CONFIG_PCMCIA_PCNET),y) -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_PCMCIA_PCNET),m) - CONFIG_8390_MODULE = y - endif -endif - -ifeq ($(CONFIG_SHAPER),y) -L_OBJS += shaper.o -else - ifeq ($(CONFIG_SHAPER),m) - M_OBJS += shaper.o - endif -endif - -ifeq ($(CONFIG_SK_G16),y) -L_OBJS += sk_g16.o -endif - -ifeq ($(CONFIG_HP100),y) -L_OBJS += hp100.o -else - ifeq ($(CONFIG_HP100),m) - M_OBJS += hp100.o - endif -endif - -ifeq ($(CONFIG_SMC9194),y) -L_OBJS += smc9194.o -else - ifeq ($(CONFIG_SMC9194),m) - M_OBJS += smc9194.o - endif -endif - -ifeq ($(CONFIG_ARM_AM79C961A),y) -L_OBJS += am79c961a.o -else - ifeq ($(CONFIG_ARM_AM79C961A),m) - M_OBJS += am79c961a.o - endif -endif - -ifeq ($(CONFIG_ARM_ETHERH),y) -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_ARM_ETHERH),m) - CONFIG_8390_MODULE = y - endif -endif - -ifeq ($(CONFIG_WD80x3),y) -L_OBJS += wd.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_WD80x3),m) - CONFIG_8390_MODULE = y - M_OBJS += wd.o - endif -endif - -ifeq ($(CONFIG_EL2),y) -L_OBJS += 3c503.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_EL2),m) - CONFIG_8390_MODULE = y - M_OBJS += 3c503.o - endif -endif - -ifeq ($(CONFIG_NE2K_PCI),y) -L_OBJS += ne2k-pci.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_NE2K_PCI),m) - CONFIG_8390_MODULE = y - M_OBJS += ne2k-pci.o - endif -endif - -ifeq ($(CONFIG_NE2000),y) -L_OBJS += ne.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_NE2000),m) - CONFIG_8390_MODULE = y - M_OBJS += ne.o - endif -endif - -ifeq ($(CONFIG_NE2_MCA),y) -L_OBJS += ne2.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_NE2_MCA),m) - CONFIG_8390_MODULE = y - M_OBJS += ne2.o - endif -endif - -ifeq ($(CONFIG_HPLAN),y) -L_OBJS += hp.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_HPLAN),m) - CONFIG_8390_MODULE = y - M_OBJS += hp.o - endif -endif - -ifeq ($(CONFIG_HPLAN_PLUS),y) -L_OBJS += hp-plus.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_HPLAN_PLUS),m) - CONFIG_8390_MODULE = y - M_OBJS += hp-plus.o - endif -endif - -ifeq ($(CONFIG_ULTRA),y) -L_OBJS += smc-ultra.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_ULTRA),m) - CONFIG_8390_MODULE = y - M_OBJS += smc-ultra.o - endif -endif - -ifeq ($(CONFIG_ULTRAMCA),y) -L_OBJS += smc-mca.o -CONFIG_8390_BUILTIN = y +ifeq ($(CONFIG_IRDA),y) +SUB_DIRS += irda +MOD_IN_SUB_DIRS += irda else - ifeq ($(CONFIG_ULTRAMCA),m) - CONFIG_8390_MODULE = y - M_OBJS += smc-mca.o + ifeq ($(CONFIG_IRDA),m) + MOD_IN_SUB_DIRS += irda endif endif -ifeq ($(CONFIG_ULTRA32),y) -L_OBJS += smc-ultra32.o -CONFIG_8390_BUILTIN = y +ifeq ($(CONFIG_TR),y) +SUB_DIRS += tokenring +MOD_IN_SUB_DIRS += tokenring else - ifeq ($(CONFIG_ULTRA32),m) - CONFIG_8390_MODULE = y - M_OBJS += smc-ultra32.o + ifeq ($(CONFIG_TR),m) + MOD_IN_SUB_DIRS += tokenring endif endif -ifeq ($(CONFIG_E2100),y) -L_OBJS += e2100.o -CONFIG_8390_BUILTIN = y +ifeq ($(CONFIG_WAN),y) +SUB_DIRS += wan +MOD_IN_SUB_DIRS += wan else - ifeq ($(CONFIG_E2100),m) - CONFIG_8390_MODULE = y - M_OBJS += e2100.o + ifeq ($(CONFIG_WAN),m) + MOD_IN_SUB_DIRS += wan endif endif -ifeq ($(CONFIG_ES3210),y) -L_OBJS += es3210.o -CONFIG_8390_BUILTIN = y +ifeq ($(CONFIG_NET_FC),y) +SUB_DIRS += fc +MOD_IN_SUB_DIRS += fc else - ifeq ($(CONFIG_ES3210),m) - CONFIG_8390_MODULE = y - M_OBJS += es3210.o + ifeq ($(CONFIG_NET_FC),m) + MOD_IN_SUB_DIRS += fc endif endif -ifeq ($(CONFIG_LNE390),y) -L_OBJS += lne390.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_LNE390),m) - CONFIG_8390_MODULE = y - M_OBJS += lne390.o +ifeq ($(CONFIG_ISDN),y) + ifeq ($(CONFIG_ISDN_PPP),y) + obj-y += slhc.o ppp_deflate.o endif -endif - -ifeq ($(CONFIG_NE3210),y) -L_OBJS += ne3210.o -CONFIG_8390_BUILTIN = y else - ifeq ($(CONFIG_NE3210),m) - CONFIG_8390_MODULE = y - M_OBJS += ne3210.o + ifeq ($(CONFIG_ISDN),m) + ifeq ($(CONFIG_ISDN_PPP),y) + obj-m += slhc.o ppp_deflate.o + endif endif endif -ifeq ($(CONFIG_PLIP),y) -L_OBJS += plip.o -else - ifeq ($(CONFIG_PLIP),m) - M_OBJS += plip.o - endif -endif +obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o +obj-$(CONFIG_SEEQ8005) += seeq8005.o +obj-$(CONFIG_ETHERTAP) += ethertap.o +obj-$(CONFIG_NET_SB1000) += sb1000.o +obj-$(CONFIG_DAYNAPORT) += daynaport.o 8390.o +obj-$(CONFIG_APNE) += apne.o 8390.o +obj-$(CONFIG_PCMCIA_PCNET) += 8390.o +obj-$(CONFIG_SHAPER) += shaper.o +obj-$(CONFIG_SK_G16) += sk_g16.o +obj-$(CONFIG_HP100) += hp100.o +obj-$(CONFIG_SMC9194) += smc9194.o +obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o +obj-$(CONFIG_ARM_ETHERH) += 8390.o +obj-$(CONFIG_WD80x3) += wd.o 8390.o +obj-$(CONFIG_EL2) += 3c503.o 8390.o +obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o +obj-$(CONFIG_NE2000) += ne.o 8390.o +obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o +obj-$(CONFIG_HPLAN) += hp.o 8390.o +obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o +obj-$(CONFIG_ULTRA) += smc-ultra.o 8390.o +obj-$(CONFIG_ULTRAMCA) += smc-mca.o 8390.o +obj-$(CONFIG_ULTRA32) += smc-ultra32.o 8390.o +obj-$(CONFIG_E2100) += e2100.o 8390.o +obj-$(CONFIG_ES3210) += es3210.o 8390.o +obj-$(CONFIG_LNE390) += lne390.o 8390.o +obj-$(CONFIG_NE3210) += ne3210.o 8390.o +obj-$(CONFIG_PLIP) += plip.o # bsd_comp.o is *always* a module, for some documented reason # (licensing). ifeq ($(CONFIG_PPP),y) -LX_OBJS += ppp_generic.o -CONFIG_SLHC_BUILTIN = y - ifeq ($(CONFIG_PPP_ASYNC),y) - LX_OBJS += ppp_async.o - else - ifeq ($(CONFIG_PPP_ASYNC),m) - MX_OBJS += ppp_async.o - endif - endif - ifeq ($(CONFIG_PPP_SYNC_TTY),y) - LX_OBJS += ppp_synctty.o - else - ifeq ($(CONFIG_PPP_SYNC_TTY),m) - MX_OBJS += ppp_synctty.o - endif - endif - ifeq ($(CONFIG_PPP_DEFLATE),y) - CONFIG_PPPDEF_BUILTIN = y - else - ifeq ($(CONFIG_PPP_DEFLATE),m) - CONFIG_PPPDEF_MODULE = y - endif - endif + obj-y += ppp_generic.o slhc.o + obj-$(CONFIG_PPP_ASYNC) += ppp_async.o + obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o + obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o ifeq ($(CONFIG_PPP_BSDCOMP),m) - M_OBJS += bsd_comp.o + obj-m += bsd_comp.o endif else ifeq ($(CONFIG_PPP),m) - MX_OBJS += ppp_generic.o - CONFIG_SLHC_MODULE = y - ifeq ($(CONFIG_PPP_ASYNC),m) - MX_OBJS += ppp_async.o - endif - ifeq ($(CONFIG_PPP_SYNC_TTY),m) - MX_OBJS += ppp_synctty.o - endif - ifeq ($(CONFIG_PPP_DEFLATE),m) - CONFIG_PPPDEF_MODULE = y - endif + obj-m += ppp_generic.o slhc.o + obj-$(CONFIG_PPP_ASYNC) += ppp_async.o + obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o + obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o ifeq ($(CONFIG_PPP_BSDCOMP),m) - M_OBJS += bsd_comp.o + obj-m += bsd_comp.o endif endif endif +obj-$(CONFIG_SLIP) += slip.o ifeq ($(CONFIG_SLIP),y) -L_OBJS += slip.o - ifeq ($(CONFIG_SLIP_COMPRESSED),y) - CONFIG_SLHC_BUILTIN = y - endif + obj-$(CONFIG_SLIP_COMPRESSED) += slhc.o else ifeq ($(CONFIG_SLIP),m) - ifeq ($(CONFIG_SLIP_COMPRESSED),y) - CONFIG_SLHC_MODULE = y - endif - M_OBJS += slip.o - endif -endif - -ifeq ($(CONFIG_STRIP),y) -L_OBJS += strip.o -else - ifeq ($(CONFIG_STRIP),m) - M_OBJS += strip.o - endif -endif - -ifeq ($(CONFIG_DE650),y) -ETDRV_OBJS := $(L_OBJS) de650.o -CONFIG_8390_BUILTIN = y -endif - -ifeq ($(CONFIG_3C589),y) -L_OBJS += 3c589.o -endif - -ifeq ($(CONFIG_DUMMY),y) -L_OBJS += dummy.o -else - ifeq ($(CONFIG_DUMMY),m) - M_OBJS += dummy.o - endif -endif - -ifeq ($(CONFIG_DE600),y) -L_OBJS += de600.o -else - ifeq ($(CONFIG_DE600),m) - M_OBJS += de600.o - endif -endif - -ifeq ($(CONFIG_DE620),y) -L_OBJS += de620.o -else - ifeq ($(CONFIG_DE620),m) - M_OBJS += de620.o - endif -endif - -ifeq ($(CONFIG_AT1500),y) -L_OBJS += lance.o -endif - -ifeq ($(CONFIG_LANCE),y) -L_OBJS += lance.o -else - ifeq ($(CONFIG_LANCE),m) - M_OBJS += lance.o - endif -endif - -ifeq ($(CONFIG_SUN3LANCE),y) -L_OBJS += sun3lance.o -endif - -ifeq ($(CONFIG_PCNET32),y) -L_OBJS += pcnet32.o -else - ifeq ($(CONFIG_PCNET32),m) - M_OBJS += pcnet32.o - endif -endif - -ifeq ($(CONFIG_DEFXX),y) -L_OBJS += defxx.o -endif - -ifeq ($(CONFIG_SUNLANCE),y) -L_OBJS += sunlance.o -else - ifeq ($(CONFIG_SUNLANCE),m) - M_OBJS += sunlance.o - endif -endif - -ifeq ($(CONFIG_SGISEEQ), y) -L_OBJS += sgiseeq.o -endif - -ifeq ($(CONFIG_HAPPYMEAL),y) -L_OBJS += sunhme.o -else - ifeq ($(CONFIG_HAPPYMEAL),m) - M_OBJS += sunhme.o - endif -endif - -ifeq ($(CONFIG_SUNQE),y) -L_OBJS += sunqe.o -else - ifeq ($(CONFIG_SUNQE),m) - M_OBJS += sunqe.o - endif -endif - -ifeq ($(CONFIG_SUNBMAC),y) -L_OBJS += sunbmac.o -else - ifeq ($(CONFIG_SUNBMAC),m) - M_OBJS += sunbmac.o - endif -endif - -ifeq ($(CONFIG_SUNBMAC),y) -L_OBJS += sunbmac.o -else - ifeq ($(CONFIG_SUNBMAC),m) - M_OBJS += sunbmac.o - endif -endif - -ifeq ($(CONFIG_MYRI_SBUS),y) -L_OBJS += myri_sbus.o -else - ifeq ($(CONFIG_MYRI_SBUS),m) - M_OBJS += myri_sbus.o - endif -endif - -ifeq ($(CONFIG_AT1700),y) -L_OBJS += at1700.o -else - ifeq ($(CONFIG_AT1700),m) - M_OBJS += at1700.o - endif -endif - -ifeq ($(CONFIG_FMV18X),y) -L_OBJS += fmv18x.o -else - ifeq ($(CONFIG_FMV18X),m) - M_OBJS += fmv18x.o - endif -endif - -ifeq ($(CONFIG_EL1),y) -L_OBJS += 3c501.o -else - ifeq ($(CONFIG_EL1),m) - M_OBJS += 3c501.o - endif -endif + obj-$(CONFIG_SLIP_COMPRESSED) += slhc.o + endif +endif + +obj-$(CONFIG_STRIP) += strip.o +obj-$(CONFIG_DE650) += de650.o 8390.o +obj-$(CONFIG_3C589) += 3c589.o +obj-$(CONFIG_DUMMY) += dummy.o +obj-$(CONFIG_DE600) += de600.o +obj-$(CONFIG_DE620) += de620.o +obj-$(CONFIG_AT1500) += lance.o +obj-$(CONFIG_LANCE) += lance.o +obj-$(CONFIG_SUN3LANCE) += sun3lance.o +obj-$(CONFIG_PCNET32) += pcnet32.o +obj-$(CONFIG_DEFXX) += defxx.o +obj-$(CONFIG_SUNLANCE) += sunlance.o +obj-$(CONFIG_SGISEEQ) += sgiseeq.o +obj-$(CONFIG_HAPPYMEAL) += sunhme.o +obj-$(CONFIG_SUNQE) += sunqe.o +obj-$(CONFIG_SUNBMAC) += sunbmac.o +obj-$(CONFIG_SUNBMAC) += sunbmac.o +obj-$(CONFIG_MYRI_SBUS) += myri_sbus.o +obj-$(CONFIG_AT1700) += at1700.o +obj-$(CONFIG_FMV18X) += fmv18x.o +obj-$(CONFIG_EL1) += 3c501.o +obj-$(CONFIG_EL16) += 3c507.o +obj-$(CONFIG_ELMC) += 3c523.o +obj-$(CONFIG_SKMC) += sk_mca.o +obj-$(CONFIG_ELMC_II) += 3c527.o +obj-$(CONFIG_EL3) += 3c509.o +obj-$(CONFIG_3C515) += 3c515.o +obj-$(CONFIG_VORTEX) += 3c59x.o +obj-$(CONFIG_EEXPRESS) += eexpress.o +obj-$(CONFIG_EEXPRESS_PRO) += eepro.o +obj-$(CONFIG_EEXPRESS_PRO100) += eepro100.o +obj-$(CONFIG_RTL8139) += rtl8139.o +obj-$(CONFIG_SIS900) += sis900.o +obj-$(CONFIG_DM9102) += dmfe.o +obj-$(CONFIG_YELLOWFIN) += yellowfin.o +obj-$(CONFIG_ACENIC) += acenic.o +obj-$(CONFIG_WAVELAN) += wavelan.o +obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o +obj-$(CONFIG_TLAN) += tlan.o +obj-$(CONFIG_VIA_RHINE) += via-rhine.o +obj-$(CONFIG_ZNET) += znet.o +obj-$(CONFIG_DEPCA) += depca.o +obj-$(CONFIG_EWRK3) += ewrk3.o +obj-$(CONFIG_ATP) += atp.o +obj-$(CONFIG_DE4X5) += de4x5.o +obj-$(CONFIG_NI5010) += ni5010.o +obj-$(CONFIG_NI52) += ni52.o +obj-$(CONFIG_NI65) += ni65.o +obj-$(CONFIG_ELPLUS) += 3c505.o +obj-$(CONFIG_AC3200) += ac3200.o 8390.o +obj-$(CONFIG_APRICOT) += 82596.o +obj-$(CONFIG_MVME16x_NET) += 82596.o +obj-$(CONFIG_BVME6000_NET) += 82596.o +obj-$(CONFIG_DEC_ELCP) += tulip.o +obj-$(CONFIG_ARCNET) += arcnet.o +obj-$(CONFIG_ARCNET_COM90xx) += com90xx.o +obj-$(CONFIG_ARCNET_COM90xxIO) += com90io.o +obj-$(CONFIG_ARCNET_RIM_I) += arc-rimi.o +obj-$(CONFIG_ARCNET_COM20020) += com20020.o +obj-$(CONFIG_ETH16I) += eth16i.o +obj-$(CONFIG_EPIC100) += epic100.o +obj-$(CONFIG_ARIADNE2) += ariadne2.o 8390.o +obj-$(CONFIG_HPLANCE) += hplance.o 7990.o +obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o +obj-$(CONFIG_EQUALIZER) += eql.o +obj-$(CONFIG_MIPS_JAZZ_SONIC) += jazzsonic.o +obj-$(CONFIG_BAGETLANCE) += bagetlance.o +obj-$(CONFIG_DECLANCE) += declance.o +obj-$(CONFIG_ATARILANCE) += atarilance.o +obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o +obj-$(CONFIG_ATARI_PAMSNET) += atari_pamsnet.o +obj-$(CONFIG_A2065) += a2065.o +obj-$(CONFIG_HYDRA) += hydra.o +obj-$(CONFIG_ARIADNE) += ariadne.o +obj-$(CONFIG_DGRS) += dgrs.o +obj-$(CONFIG_CS89x0) += cs89x0.o +obj-$(CONFIG_LTPC) += ltpc.o +obj-$(CONFIG_COPS) += cops.o +obj-$(CONFIG_IPDDP) += ipddp.o +obj-$(CONFIG_RCPCI) += rcpci.o +obj-$(CONFIG_MACE) += mace.o +obj-$(CONFIG_MACSONIC) += macsonic.o +obj-$(CONFIG_BMAC) += bmac.o +obj-$(CONFIG_NCR885E) += ncr885e.o +obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o -ifeq ($(CONFIG_EL16),y) -L_OBJS += 3c507.o -else - ifeq ($(CONFIG_EL16),m) - M_OBJS += 3c507.o - endif -endif +# +# HIPPI adapters +# -ifeq ($(CONFIG_ELMC),y) -L_OBJS += 3c523.o -else - ifeq ($(CONFIG_ELMC),m) - M_OBJS += 3c523.o - endif -endif +obj-$(CONFIG_ROADRUNNER) += rrunner.o -ifeq ($(CONFIG_SKMC),y) -L_OBJS += sk_mca.o -else - ifeq ($(CONFIG_SKMC),m) - M_OBJS += sk_mca.o - endif -endif +# Extract lists of the multi-part drivers. +# The 'int-*' lists are the intermediate files used to build the multi's. -ifeq ($(CONFIG_ELMC_II),y) -L_OBJS += 3c527.o -else - ifeq ($(CONFIG_ELMC_II),m) - M_OBJS += 3c527.o - endif -endif +multi-y := $(filter $(list-multi), $(obj-y)) +multi-m := $(filter $(list-multi), $(obj-m)) +int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs))) +int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs))) -ifeq ($(CONFIG_EL3),y) -L_OBJS += 3c509.o -else - ifeq ($(CONFIG_EL3),m) - M_OBJS += 3c509.o - endif -endif +# Files that are both resident and modular: remove from modular. -ifeq ($(CONFIG_3C515),y) -L_OBJS += 3c515.o -else - ifeq ($(CONFIG_3C515),m) - M_OBJS += 3c515.o - endif -endif +obj-m := $(filter-out $(obj-y), $(obj-m)) +int-m := $(filter-out $(int-y), $(int-m)) -ifeq ($(CONFIG_VORTEX),y) -L_OBJS += 3c59x.o -else - ifeq ($(CONFIG_VORTEX),m) - M_OBJS += 3c59x.o - endif -endif +# Take multi-part drivers out of obj-y and put components in. -ifeq ($(CONFIG_EEXPRESS),y) -L_OBJS += eexpress.o -else - ifeq ($(CONFIG_EEXPRESS),m) - M_OBJS += eexpress.o - endif -endif +obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y) -ifeq ($(CONFIG_EEXPRESS_PRO),y) -L_OBJS += eepro.o -else - ifeq ($(CONFIG_EEXPRESS_PRO),m) - M_OBJS += eepro.o - endif -endif +# Translate to Rules.make lists. -ifeq ($(CONFIG_EEXPRESS_PRO100),y) -L_OBJS += eepro100.o -else - ifeq ($(CONFIG_EEXPRESS_PRO100),m) - M_OBJS += eepro100.o - endif -endif +O_OBJS := $(filter-out $(export-objs), $(obj-y)) +OX_OBJS := $(filter $(export-objs), $(obj-y)) +M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m))) +MX_OBJS := $(sort $(filter $(export-objs), $(obj-m))) -ifeq ($(CONFIG_RTL8139),y) -L_OBJS += rtl8139.o -else - ifeq ($(CONFIG_RTL8139),m) - M_OBJS += rtl8139.o - endif -endif +L_OBJS += $(O_OBJS) +L_OBJS += $(OX_OBJS) -ifeq ($(CONFIG_SIS900),y) -L_OBJS += sis900.o -else - ifeq ($(CONFIG_SIS900),m) - M_OBJS += sis900.o - endif -endif +include $(TOPDIR)/Rules.make -ifeq ($(CONFIG_DM9102),y) -L_OBJS += dmfe.o -else - ifeq ($(CONFIG_DM9102),m) - M_OBJS += dmfe.o - endif -endif +clean: + rm -f core *.o *.a *.s +rcpci.o: rcpci45.o rclanmtl.o + $(LD) -r -o rcpci.o rcpci45.o rclanmtl.o -ifeq ($(CONFIG_YELLOWFIN),y) -L_OBJS += yellowfin.o -else - ifeq ($(CONFIG_YELLOWFIN),m) - M_OBJS += yellowfin.o - endif -endif - -ifeq ($(CONFIG_ACENIC),y) -L_OBJS += acenic.o -else - ifeq ($(CONFIG_ACENIC),m) - M_OBJS += acenic.o - endif -endif - -ifeq ($(CONFIG_WAVELAN),y) -L_OBJS += wavelan.o -else - ifeq ($(CONFIG_WAVELAN),m) - M_OBJS += wavelan.o - endif -endif - -ifeq ($(CONFIG_ARLAN),y) -LX_OBJS += arlan.o arlan-proc.o -else - ifeq ($(CONFIG_ARLAN),m) - MX_OBJS += arlan.o arlan-proc.o - endif -endif - -ifeq ($(CONFIG_TLAN),y) -L_OBJS += tlan.o -else - ifeq ($(CONFIG_TLAN),m) - M_OBJS += tlan.o - endif -endif - -ifeq ($(CONFIG_VIA_RHINE),y) -L_OBJS += via-rhine.o -else - ifeq ($(CONFIG_VIA_RHINE),m) - M_OBJS += via-rhine.o - endif -endif - -ifeq ($(CONFIG_ZNET),y) -L_OBJS += znet.o -endif - -ifeq ($(CONFIG_DEPCA),y) -L_OBJS += depca.o -else - ifeq ($(CONFIG_DEPCA),m) - M_OBJS += depca.o - endif -endif - -ifeq ($(CONFIG_EWRK3),y) -L_OBJS += ewrk3.o -else - ifeq ($(CONFIG_EWRK3),m) - M_OBJS += ewrk3.o - endif -endif - -ifeq ($(CONFIG_ATP),y) -L_OBJS += atp.o -endif - -ifeq ($(CONFIG_DE4X5),y) -L_OBJS += de4x5.o -else - ifeq ($(CONFIG_DE4X5),m) - M_OBJS += de4x5.o - endif -endif - -ifeq ($(CONFIG_NI5010),y) -L_OBJS += ni5010.o -else - ifeq ($(CONFIG_NI5010),m) - M_OBJS += ni5010.o - endif -endif - -ifeq ($(CONFIG_NI52),y) -L_OBJS += ni52.o -else - ifeq ($(CONFIG_NI52),m) - M_OBJS += ni52.o - endif -endif - -ifeq ($(CONFIG_NI65),y) -L_OBJS += ni65.o -else - ifeq ($(CONFIG_NI65),m) - M_OBJS += ni65.o - endif -endif - -ifeq ($(CONFIG_ELPLUS),y) -L_OBJS += 3c505.o -else - ifeq ($(CONFIG_ELPLUS),m) - M_OBJS += 3c505.o - endif -endif - -ifeq ($(CONFIG_AC3200),y) -L_OBJS += ac3200.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_AC3200),m) - CONFIG_8390_MODULE = y - M_OBJS += ac3200.o - endif -endif - -ifeq ($(CONFIG_APRICOT),y) -CONFIG_82596_BUILTIN = y -else - ifeq ($(CONFIG_APRICOT),m) - CONFIG_82596_MODULE = y - endif -endif - -ifeq ($(CONFIG_MVME16x_NET),y) -CONFIG_82596_BUILTIN = y -else - ifeq ($(CONFIG_MVME16x_NET),m) - CONFIG_82596_MODULE = y - endif -endif - -ifeq ($(CONFIG_BVME6000_NET),y) -CONFIG_82596_BUILTIN = y -else - ifeq ($(CONFIG_BVME6000_NET),m) - CONFIG_82596_MODULE = y - endif -endif - -ifeq ($(CONFIG_DEC_ELCP),y) -L_OBJS += tulip.o -else - ifeq ($(CONFIG_DEC_ELCP),m) - M_OBJS += tulip.o - endif -endif - -ifeq ($(CONFIG_ARCNET),y) -LX_OBJS += arcnet.o -else - ifeq ($(CONFIG_ARCNET),m) - MX_OBJS += arcnet.o - endif -endif - -ifeq ($(CONFIG_ARCNET_COM90xx),y) -L_OBJS += com90xx.o -else - ifeq ($(CONFIG_ARCNET_COM90xx),m) - M_OBJS += com90xx.o - endif -endif - -ifeq ($(CONFIG_ARCNET_COM90xxIO),y) -L_OBJS += com90io.o -else - ifeq ($(CONFIG_ARCNET_COM90xxIO),m) - M_OBJS += com90io.o - endif -endif - -ifeq ($(CONFIG_ARCNET_RIM_I),y) -L_OBJS += arc-rimi.o -else - ifeq ($(CONFIG_ARCNET_RIM_I),m) - M_OBJS += arc-rimi.o - endif -endif - -ifeq ($(CONFIG_ARCNET_COM20020),y) -L_OBJS += com20020.o -else - ifeq ($(CONFIG_ARCNET_COM20020),m) - M_OBJS += com20020.o - endif -endif - -ifeq ($(CONFIG_ETH16I),y) -L_OBJS += eth16i.o -else - ifeq ($(CONFIG_ETH16I),m) - M_OBJS += eth16i.o - endif -endif - -ifeq ($(CONFIG_EPIC100),y) -L_OBJS += epic100.o -else - ifeq ($(CONFIG_EPIC100),m) - M_OBJS += epic100.o - endif -endif - -# If anything built-in uses slhc, then build it into the kernel also. -# If not, but a module uses it, build as a module. -ifdef CONFIG_SLHC_BUILTIN -LX_OBJS += slhc.o -else - ifdef CONFIG_SLHC_MODULE - MX_OBJS += slhc.o - endif -endif - -# if anything built-in uses ppp_deflate, then build it into the kernel also. -# If not, but a module uses it, build as a module. -ifdef CONFIG_PPPDEF_BUILTIN -L_OBJS += ppp_deflate.o -else - ifdef CONFIG_PPPDEF_MODULE - M_OBJS += ppp_deflate.o - endif -endif - -ifeq ($(CONFIG_ARIADNE2),y) -L_OBJS += ariadne2.o -CONFIG_8390_BUILTIN = y -else - ifeq ($(CONFIG_ARIADNE2),m) - M_OBJS += ariadne2.o - CONFIG_8390_MODULE = y - endif -endif - -# If anything built-in uses the 8390, then build it into the kernel also. -# If not, but a module uses it, build as a module. -ifdef CONFIG_8390_BUILTIN -L_OBJS += 8390.o -else - ifdef CONFIG_8390_MODULE - MX_OBJS += 8390.o - endif -endif - -ifeq ($(CONFIG_HPLANCE),y) -L_OBJS += hplance.o -CONFIG_7990_BUILTIN = y -else - ifeq ($(CONFIG_HPLANCE),m) - CONFIG_7990_MODULE = y - M_OBJS += hplance.o - endif -endif - -ifeq ($(CONFIG_MVME147_NET),y) -L_OBJS += mvme147.o -CONFIG_7990_BUILTIN = y -else - ifeq ($(CONFIG_MVME147_NET),m) - CONFIG_7990_MODULE = y - M_OBJS += mvme147.o - endif -endif - -# If we need generic LANCE support, either in the kernel or as a module, -# build it in the appropriate way. -ifdef CONFIG_7990_BUILTIN -L_OBJS += 7990.o -else - ifdef CONFIG_7990_MODULE - M_OBJS += 7990.o - endif -endif - -# If anything built-in uses the 82596, then build it into the kernel also. -# If not, but a module uses it, build as a module. -ifdef CONFIG_82596_BUILTIN -L_OBJS += 82596.o -else - ifdef CONFIG_82596_MODULE - M_OBJS += 82596.o - endif -endif - -ifeq ($(CONFIG_EQUALIZER),y) -L_OBJS += eql.o -else - ifeq ($(CONFIG_EQUALIZER),m) - M_OBJS += eql.o - endif -endif - -ifeq ($(CONFIG_MIPS_JAZZ_SONIC),y) -L_OBJS += jazzsonic.o -else - ifeq ($(CONFIG_MIPS_JAZZ_SONIC),m) - M_OBJS += jazzsonic.o - endif -endif - -ifeq ($(CONFIG_BAGETLANCE),y) -L_OBJS += bagetlance.o -else - ifeq ($(CONFIG_BAGETLANCE),m) - M_OBJS += bagetlance.o - endif -endif - -ifeq ($(CONFIG_DECLANCE),y) -L_OBJS += declance.o -else - ifeq ($(CONFIG_DECLANCE),m) - M_OBJS += declance.o - endif -endif - -ifeq ($(CONFIG_ATARILANCE),y) -L_OBJS += atarilance.o -else - ifeq ($(CONFIG_ATARILANCE),m) - M_OBJS += atarilance.o - endif -endif - -ifeq ($(CONFIG_ATARI_BIONET),y) -L_OBJS += atari_bionet.o -else - ifeq ($(CONFIG_ATARI_BIONET),m) - M_OBJS += atari_bionet.o - endif -endif - -ifeq ($(CONFIG_ATARI_PAMSNET),y) -L_OBJS += atari_pamsnet.o -else - ifeq ($(CONFIG_ATARI_PAMSNET),m) - M_OBJS += atari_pamsnet.o - endif -endif - -ifeq ($(CONFIG_A2065),y) -L_OBJS += a2065.o -else - ifeq ($(CONFIG_A2065),m) - M_OBJS += a2065.o - endif -endif - -ifeq ($(CONFIG_HYDRA),y) -L_OBJS += hydra.o -else - ifeq ($(CONFIG_HYDRA),m) - M_OBJS += hydra.o - endif -endif - -ifeq ($(CONFIG_ARIADNE),y) -L_OBJS += ariadne.o -else - ifeq ($(CONFIG_ARIADNE),m) - M_OBJS += ariadne.o - endif -endif - -ifeq ($(CONFIG_DGRS),y) -L_OBJS += dgrs.o -else - ifeq ($(CONFIG_DGRS),m) - M_OBJS += dgrs.o - endif -endif - -ifeq ($(CONFIG_CS89x0),y) -L_OBJS += cs89x0.o -else - ifeq ($(CONFIG_CS89x0),m) - M_OBJS += cs89x0.o - endif -endif - -ifeq ($(CONFIG_LTPC),y) -L_OBJS += ltpc.o -else - ifeq ($(CONFIG_LTPC),m) - M_OBJS += ltpc.o - endif -endif - -ifeq ($(CONFIG_COPS),y) -L_OBJS += cops.o -else - ifeq ($(CONFIG_COPS),m) - M_OBJS += cops.o - endif -endif - -ifeq ($(CONFIG_IPDDP),y) -L_OBJS += ipddp.o -else - ifeq ($(CONFIG_IPDDP),m) - M_OBJS += ipddp.o - endif -endif - -ifeq ($(CONFIG_RCPCI),y) -L_OBJS += rcpci.o -else - ifeq ($(CONFIG_RCPCI),m) - M_OBJS += rcpci.o - endif -endif - -ifeq ($(CONFIG_MACE),y) -L_OBJS += mace.o -else - ifeq ($(CONFIG_MACE),m) - M_OBJS += mace.o - endif -endif - -ifeq ($(CONFIG_MACSONIC),y) -L_OBJS += macsonic.o -endif - -ifeq ($(CONFIG_BMAC),y) -L_OBJS += bmac.o -else - ifeq ($(CONFIG_BMAC),m) - M_OBJS += bmac.o - endif -endif - -ifeq ($(CONFIG_NCR885E),y) -L_OBJS += ncr885e.o -else - ifeq ($(CONFIG_NCR885E),m) - M_OBJS += ncr885e.o - endif -endif - -ifeq ($(CONFIG_ADAPTEC_STARFIRE),y) -L_OBJS += starfire.o -else - ifeq ($(CONFIG_ADAPTEC_STARFIRE),m) - M_OBJS += starfire.o - endif -endif - -# -# HIPPI adapters -# - -ifeq ($(CONFIG_ROADRUNNER),y) -L_OBJS += rrunner.o -else - ifeq ($(CONFIG_ROADRUNNER),m) - M_OBJS += rrunner.o - endif -endif - -ifeq ($(CONFIG_IRDA),y) -SUB_DIRS += irda -MOD_IN_SUB_DIRS += irda -else - ifeq ($(CONFIG_IRDA),m) - MOD_IN_SUB_DIRS += irda - endif -endif - -ifeq ($(CONFIG_TR),y) -SUB_DIRS += tokenring -MOD_IN_SUB_DIRS += tokenring -else - ifeq ($(CONFIG_TR),m) - MOD_IN_SUB_DIRS += tokenring - endif -endif - -ifeq ($(CONFIG_WAN),y) -SUB_DIRS += wan -MOD_IN_SUB_DIRS += wan -else - ifeq ($(CONFIG_WAN),m) - MOD_IN_SUB_DIRS += wan - endif -endif - -ifeq ($(CONFIG_NET_FC),y) -SUB_DIRS += fc -MOD_IN_SUB_DIRS += fc -else - ifeq ($(CONFIG_NET_FC),m) - MOD_IN_SUB_DIRS += fc - endif -endif - -include $(TOPDIR)/Rules.make - -clean: - rm -f core *.o *.a *.s - -rcpci.o: rcpci45.o rclanmtl.o - $(LD) -r -o rcpci.o rcpci45.o rclanmtl.o diff --git a/drivers/net/dmfe.c b/drivers/net/dmfe.c index 43032d95d213..fbd75ca052aa 100644 --- a/drivers/net/dmfe.c +++ b/drivers/net/dmfe.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c index 6f7eda2ed794..a9b0f16c08a9 100644 --- a/drivers/net/es3210.c +++ b/drivers/net/es3210.c @@ -344,7 +344,7 @@ static void es_block_input(struct net_device *dev, int count, struct sk_buff *sk isa_memcpy_fromio(skb->data + semi_count, dev->rmem_start, count); } else { /* Packet is in one chunk. */ - isa_eth_io_copy_and_csum(skb, xfer_start, count, 0); + isa_eth_io_copy_and_sum(skb, xfer_start, count, 0); } } diff --git a/drivers/net/ncr885e.c b/drivers/net/ncr885e.c index f5e403e3e17d..d7c7fb23900e 100644 --- a/drivers/net/ncr885e.c +++ b/drivers/net/ncr885e.c @@ -33,7 +33,6 @@ static const char *version = #include #include #include -#include #include #include #include diff --git a/drivers/net/pcmcia/ray_cs.c b/drivers/net/pcmcia/ray_cs.c index 4467b8af60fd..b147dfef9d5f 100644 --- a/drivers/net/pcmcia/ray_cs.c +++ b/drivers/net/pcmcia/ray_cs.c @@ -2683,7 +2683,7 @@ static int __init init_ray_cs(void) DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc); #ifdef CONFIG_PROC_FS /* [proc-namespace][fixme] It shouldn't be under root, damnit! */ - create_proc_info_entry("ray_cs", 0, proc_root, ray_cs_proc_read); + create_proc_info_entry("ray_cs", 0, &proc_root, ray_cs_proc_read); #endif if (translate != 0) translate = 1; return 0; @@ -2714,7 +2714,7 @@ static void __exit exit_ray_cs(void) ray_detach(dev_list); } #ifdef CONFIG_PROC_FS - remove_proc_entry("ray_cs", proc_root); + remove_proc_entry("ray_cs", &proc_root); #endif } /* exit_ray_cs */ diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c index 17a33841ecf7..9026441624bc 100644 --- a/drivers/net/sk_mca.c +++ b/drivers/net/sk_mca.c @@ -71,7 +71,6 @@ History: #include #include -#include #include #include #include diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 2056501c2b20..ed78f8cf9340 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -58,7 +58,7 @@ else endif ifeq ($(CONFIG_BLK_DEV_SD),y) -L_OBJS += sd.o sd_ioctl.o +L_OBJS += sd.o else ifeq ($(CONFIG_BLK_DEV_SD),m) M_OBJS += sd_mod.o @@ -729,5 +729,5 @@ scsi_mod.o: $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \ sr_mod.o: sr.o sr_ioctl.o sr_vendor.o $(LD) $(LD_RFLAG) -r -o $@ sr.o sr_ioctl.o sr_vendor.o -sd_mod.o: sd.o sd_ioctl.o - $(LD) $(LD_RFLAG) -r -o $@ sd.o sd_ioctl.o +sd_mod.o: sd.o + $(LD) $(LD_RFLAG) -r -o $@ sd.o diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 93d084cbfe93..59a6bee98f9e 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -107,7 +107,7 @@ #include "atari_scsi.h" #endif -#ifdef CONFIG_MAC_SCSI_OLD +#if defined(CONFIG_MAC_SCSI) || defined(CONFIG_MAC_SCSI_OLD) #include "mac_scsi.h" #endif @@ -115,10 +115,6 @@ #include "sun3_scsi.h" #endif -#ifdef CONFIG_MAC_SCSI -#include "mac_scsi.h" -#endif - #ifdef CONFIG_SCSI_MAC_ESP #include "mac_esp.h" #endif diff --git a/drivers/scsi/inia100.c b/drivers/scsi/inia100.c index eab18bad12d7..5203b6e36923 100644 --- a/drivers/scsi/inia100.c +++ b/drivers/scsi/inia100.c @@ -73,19 +73,13 @@ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0) #include -#include #include -#include #include -#include -#include #include -#include #if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92) #include #endif #include -#include #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23) #include #endif @@ -93,34 +87,28 @@ #if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) #include #endif -#include "sd.h" -#include "scsi.h" -#include "hosts.h" -#include "inia100.h" #include -#include #include - #else -#include #include #include +#include +#include "../block/blk.h" +#endif + +#include #include #include - #include #include -#include #include -#include "../block/blk.h" #include "scsi.h" #include "sd.h" #include "hosts.h" #include #include "inia100.h" -#endif #ifdef MODULE Scsi_Host_Template driver_template = INIA100; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a2876d17cdb1..9b4de06f3faf 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -36,21 +36,25 @@ #include #include #include +#include #include #include #include +#include #include #include #define MAJOR_NR SCSI_DISK0_MAJOR #include +#include #include "scsi.h" #include "hosts.h" #include "sd.h" #include #include "constants.h" +#include /* must follow "hosts.h" */ #include @@ -87,8 +91,6 @@ static int *sd_sizes; static int *sd_blocksizes; static int *sd_hardsizes; /* Hardware sector size */ -extern int sd_ioctl(struct inode *, struct file *, unsigned int, unsigned long); - static int check_scsidisk_media_change(kdev_t); static int fop_revalidate_scsidisk(kdev_t); @@ -102,6 +104,83 @@ static int sd_attach(Scsi_Device *); static int sd_detect(Scsi_Device *); static void sd_detach(Scsi_Device *); +static int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) +{ + kdev_t dev = inode->i_rdev; + int error; + struct Scsi_Host * host; + Scsi_Device * SDev; + int diskinfo[4]; + struct hd_geometry *loc = (struct hd_geometry *) arg; + + SDev = rscsi_disks[DEVICE_NR(dev)].device; + /* + * If we are in the middle of error recovery, don't let anyone + * else try and use this device. Also, if error recovery fails, it + * may try and take the device offline, in which case all further + * access to the device is prohibited. + */ + if( !scsi_block_when_processing_errors(SDev) ) + { + return -ENODEV; + } + + switch (cmd) { + case HDIO_GETGEO: /* Return BIOS disk parameters */ + if (!loc) return -EINVAL; + error = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); + if (error) + return error; + 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]); + + put_user(diskinfo[0], &loc->heads); + put_user(diskinfo[1], &loc->sectors); + put_user(diskinfo[2], &loc->cylinders); + put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start); + return 0; + case BLKGETSIZE: /* Return device size */ + if (!arg) return -EINVAL; + error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); + if (error) + return error; + put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, + (long *) arg); + return 0; + + case BLKROSET: + case BLKROGET: + case BLKRASET: + case BLKRAGET: + case BLKFLSBUF: + case BLKSSZGET: + case BLKPG: + return blk_ioctl(inode->i_rdev, cmd, arg); + + case BLKRRPART: /* Re-read partition tables */ + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + return revalidate_scsidisk(dev, 1); + + default: + return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg); + } +} + static void sd_devname(unsigned int disknum, char *buffer) { if (disknum < 26) diff --git a/drivers/scsi/sd_ioctl.c b/drivers/scsi/sd_ioctl.c deleted file mode 100644 index 486d911be8df..000000000000 --- a/drivers/scsi/sd_ioctl.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * drivers/scsi/sd_ioctl.c - * - * ioctl handling for SCSI disks - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define MAJOR_NR SCSI_DISK0_MAJOR -#include -#include -#include "scsi.h" -#include -#include "hosts.h" -#include "sd.h" -#include /* must follow "hosts.h" */ - -int sd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) -{ - kdev_t dev = inode->i_rdev; - int error; - struct Scsi_Host * host; - Scsi_Device * SDev; - int diskinfo[4]; - struct hd_geometry *loc = (struct hd_geometry *) arg; - - SDev = rscsi_disks[DEVICE_NR(dev)].device; - /* - * If we are in the middle of error recovery, don't let anyone - * else try and use this device. Also, if error recovery fails, it - * may try and take the device offline, in which case all further - * access to the device is prohibited. - */ - if( !scsi_block_when_processing_errors(SDev) ) - { - return -ENODEV; - } - - switch (cmd) { - case HDIO_GETGEO: /* Return BIOS disk parameters */ - if (!loc) return -EINVAL; - error = verify_area(VERIFY_WRITE, loc, sizeof(*loc)); - if (error) - return error; - 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]); - - put_user(diskinfo[0], &loc->heads); - put_user(diskinfo[1], &loc->sectors); - put_user(diskinfo[2], &loc->cylinders); - put_user(sd[SD_PARTITION(inode->i_rdev)].start_sect, &loc->start); - return 0; - case BLKGETSIZE: /* Return device size */ - if (!arg) return -EINVAL; - error = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long)); - if (error) - return error; - put_user(sd[SD_PARTITION(inode->i_rdev)].nr_sects, - (long *) arg); - return 0; - - case BLKROSET: - case BLKROGET: - case BLKRASET: - case BLKRAGET: - case BLKFLSBUF: - case BLKSSZGET: - case BLKPG: - return blk_ioctl(inode->i_rdev, cmd, arg); - - case BLKRRPART: /* Re-read partition tables */ - if (!capable(CAP_SYS_ADMIN)) - return -EACCES; - return revalidate_scsidisk(dev, 1); - - default: - return scsi_ioctl(rscsi_disks[DEVICE_NR(dev)].device , cmd, (void *) arg); - } -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-indent-level: 4 - * c-brace-imaginary-offset: 0 - * c-brace-offset: -4 - * c-argdecl-indent: 4 - * c-label-offset: -4 - * c-continued-statement-offset: 4 - * c-continued-brace-offset: 0 - * indent-tabs-mode: nil - * tab-width: 8 - * End: - */ diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 15fcf29ec9eb..20dca257180f 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -37,7 +37,7 @@ endif ifeq ($(CONFIG_USB_UHCI),m) M_OBJS += usb-uhci.o - MIX_OBJS += uhci.o uhci-debug.o + MI_OBJS += uhci.o uhci-debug.o endif ifeq ($(CONFIG_USB_OHCI),y) @@ -45,7 +45,7 @@ ifeq ($(CONFIG_USB_OHCI),y) endif ifeq ($(CONFIG_USB_OHCI),m) M_OBJS += usb-ohci.o - MIX_OBJS += ohci.o ohci-debug.o + MI_OBJS += ohci.o ohci-debug.o endif ifeq ($(CONFIG_USB_OHCI_HCD),y) @@ -53,7 +53,7 @@ ifeq ($(CONFIG_USB_OHCI_HCD),y) endif ifeq ($(CONFIG_USB_OHCI_HCD),m) M_OBJS += usb-ohci-hcd.o - MIX_OBJS += ohci-hcd.o ohci-root-hub.o + MI_OBJS += ohci-hcd.o ohci-root-hub.o endif ifeq ($(CONFIG_USB_MOUSE),y) @@ -61,7 +61,7 @@ ifeq ($(CONFIG_USB_MOUSE),y) endif ifeq ($(CONFIG_USB_MOUSE),m) M_OBJS += mouse.o - MIX_OBJS += mouse.o + MI_OBJS += mouse.o endif ifeq ($(CONFIG_USB_HP_SCANNER),y) @@ -69,7 +69,7 @@ ifeq ($(CONFIG_USB_HP_SCANNER),y) endif ifeq ($(CONFIG_USB_HP_SCANNER),m) M_OBJS +=hp_scanner.o - MIX_OBJS +=hp_scanner.o + MI_OBJS +=hp_scanner.o endif ifeq ($(CONFIG_USB_HUB),y) @@ -77,7 +77,7 @@ ifeq ($(CONFIG_USB_HUB),y) endif ifeq ($(CONFIG_USB_HUB),m) M_OBJS += hub.o - MIX_OBJS += hub.o + MI_OBJS += hub.o endif ifeq ($(CONFIG_USB_ACM),y) @@ -85,7 +85,7 @@ ifeq ($(CONFIG_USB_ACM),y) endif ifeq ($(CONFIG_USB_ACM),m) M_OBJS += acm.o - MIX_OBJS += acm.o + MI_OBJS += acm.o endif ifeq ($(CONFIG_USB_PRINTER),y) @@ -94,7 +94,7 @@ endif ifeq ($(CONFIG_USB_PRINTER),m) M_OBJS += printer.o - MIX_OBJS += printer.o + MI_OBJS += printer.o endif ifeq ($(CONFIG_USB_SERIAL),y) @@ -103,7 +103,7 @@ endif ifeq ($(CONFIG_USB_SERIAL),m) M_OBJS += usb-serial.o - MIX_OBJS += usb-serial.o + MI_OBJS += usb-serial.o endif ifneq ($(CONFIG_ADB_KEYBOARD),y) @@ -118,7 +118,7 @@ endif ifeq ($(CONFIG_USB_KBD),m) M_OBJS += usb-keyboard.o - MIX_OBJS += keyboard.o $(KEYMAP).o + MI_OBJS += keyboard.o $(KEYMAP).o endif ifeq ($(CONFIG_USB_AUDIO),y) @@ -127,7 +127,7 @@ endif ifeq ($(CONFIG_USB_AUDIO),m) M_OBJS += audio.o - MIX_OBJS += audio.o + MI_OBJS += audio.o endif ifeq ($(CONFIG_USB_CPIA),y) @@ -136,7 +136,7 @@ endif ifeq ($(CONFIG_USB_CPIA),m) M_OBJS += cpia.o - MIX_OBJS += cpia.o + MI_OBJS += cpia.o endif ifeq ($(CONFIG_USB_DC2XX),y) @@ -144,7 +144,7 @@ ifeq ($(CONFIG_USB_DC2XX),y) endif ifeq ($(CONFIG_USB_DC2XX),m) M_OBJS += dc2xx.o - MIX_OBJS += dc2xx.o + MI_OBJS += dc2xx.o endif ifeq ($(CONFIG_USB_SCSI),y) @@ -156,9 +156,9 @@ endif ifeq ($(CONFIG_USB_SCSI),m) M_OBJS += usb-scsi.o - MIX_OBJS += usb_scsi.o + MI_OBJS += usb_scsi.o ifeq ($(CONFIG_USB_SCSI_DEBUG),y) - MIX_OBJS += usb_scsi_debug.o + MI_OBJS += usb_scsi_debug.o endif endif @@ -168,7 +168,7 @@ endif ifeq ($(CONFIG_USB_EZUSB),m) M_OBJS += ezusb.o - MIX_OBJS += ezusb.o + MI_OBJS += ezusb.o endif ifeq ($(CONFIG_USB_USS720),y) @@ -177,7 +177,7 @@ endif ifeq ($(CONFIG_USB_USS720),m) M_OBJS += uss720.o - MIX_OBJS += uss720.o + MI_OBJS += uss720.o endif include $(TOPDIR)/Rules.make diff --git a/drivers/usb/README.serial b/drivers/usb/README.serial index e67fb748a853..0b59e0d1bb3b 100644 --- a/drivers/usb/README.serial +++ b/drivers/usb/README.serial @@ -3,15 +3,24 @@ Serial devices. It should also work for the Etek converter, but I do not know the vendor id, and device id of that device (if anyone does, please let me know.) +If your device is not compatible with the above models, you can try +out the "generic" interface. This interface does not provide any type +of control messages sent to the device, and does not support any kind +of device flow control. All that is required of your device is that +it has at least one bulk in endpoint, or one bulk out endpoint. +To enable the driver to recognize your device, build the driver as +a module and load it by the following invocation: + insmod usb-serial.o vendor=0x#### product=0x#### +where the #### is replaced with the hex representation of your device's +vendor id and product id. + The driver can handle enumerating the device, and sending and receiving -data from the converter. However, since I do not have a spec for this -device, and the raw dumps from the Win98 driver are confusing, no control -signals are handled, and the data will most likely come through on a baud +data from the converter. However, since I do not have a spec for the Belkin, +Peracom, and eTek devices, and the raw dumps from the Win98 driver are +confusing, and eTek keeps giving me the run around, no control signals are +currently handled, and the data will most likely come through on a baud rate that you are not expecting. -But I am working on figuring the control settings out. This release is to -let others try it out, and give some feedback. - The major number that the driver uses is 240 (in the local/experimental range.) It will stay there until some agreements are reached on how to handle the configuration problem that USB provides. diff --git a/drivers/usb/usb-serial.c b/drivers/usb/usb-serial.c index 534b369caba3..368f0bf47a26 100644 --- a/drivers/usb/usb-serial.c +++ b/drivers/usb/usb-serial.c @@ -1,32 +1,41 @@ /* * USB Serial Converter driver * - * Greg Kroah-Hartman (greg@kroah.com) + * (C) Copyright (C) 1999 + * Greg Kroah-Hartman (greg@kroah.com) * - * This was based on the ACM driver by Armin Fuerst (which was based - * on a driver by Brad Keryan) + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * Currently only works for the Belkin and Peracom Serial converters. - * Should also work on the Etek serial converter, if anyone knows the - * vendor and device ids for that device. + * This driver was originally based on the ACM driver by Armin Fuerst (which was + * based on a driver by Brad Keryan) * + * See README.serial for more information on using this driver. * + * version 0.2.0 (11/10/99) gkh + * Split up internals to make it easier to add different types of serial + * converters to the code. + * Added a "generic" driver that gets it's vendor and product id + * from when the module is loaded. Thanks to David E. Nelson (dnelson@jump.net) + * for the idea and sample code (from the usb scanner driver.) + * Cleared up any licensing questions by releasing it under the GNU GPL. + * * version 0.1.2 (10/25/99) gkh - * Fixed bug in detecting device. + * Fixed bug in detecting device. * * version 0.1.1 (10/05/99) gkh - * Changed the major number to not conflict with anything else. + * Changed the major number to not conflict with anything else. * * version 0.1 (09/28/99) gkh - * Can recognize the two different devices and start up a read from - * device when asked to. Writes also work. No control signals yet, this - * all is vendor specific data (i.e. no spec), also no control for - * different baud rates or other bit settings. - * Currently we are using the same devid as the acm driver. This needs - * to change. + * Can recognize the two different devices and start up a read from + * device when asked to. Writes also work. No control signals yet, this + * all is vendor specific data (i.e. no spec), also no control for + * different baud rates or other bit settings. + * Currently we are using the same devid as the acm driver. This needs + * to change. * - * (C) Copyright 1999 Greg Kroah-Hartman (greg@kroah.com) - * */ #include @@ -43,8 +52,8 @@ #include #include - #include "usb.h" + /*#define SERIAL_DEBUG 1*/ #ifdef SERIAL_DEBUG @@ -54,6 +63,19 @@ #endif +/* Module information */ +MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/"); +MODULE_DESCRIPTION("USB Serial Driver"); + +static __u16 vendor = 0; +static __u16 product = 0; +MODULE_PARM(vendor, "i"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); + +MODULE_PARM(product, "i"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); + + /* USB Serial devices vendor ids and device ids that this driver supports */ #define BELKIN_VENDOR_ID 0x056c #define BELKIN_SERIAL_CONVERTER 0x8007 @@ -70,41 +92,171 @@ static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum); static void usb_serial_disconnect(struct usb_device *dev, void *ptr); -typedef enum { - unknown = 0, - Belkin = 1, - Peracom = 2 - } SERIAL_TYPE; + +#define MUST_HAVE_NOT 0x01 +#define MUST_HAVE 0x02 +#define DONT_CARE 0x03 + +#define HAS 0x02 +#define HAS_NOT 0x01 + + +/* local function prototypes */ +static int serial_open (struct tty_struct *tty, struct file * filp); +static void serial_close (struct tty_struct *tty, struct file * filp); +static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); +static void serial_put_char (struct tty_struct *tty, unsigned char ch); +static int serial_write_room (struct tty_struct *tty); +static int serial_chars_in_buffer (struct tty_struct *tty); +static void serial_throttle (struct tty_struct * tty); +static void serial_unthrottle (struct tty_struct * tty); + + +/* function prototypes for the eTek type converters (this included Belkin and Peracom) */ +static int etek_serial_open (struct tty_struct *tty, struct file * filp); +static void etek_serial_close (struct tty_struct *tty, struct file * filp); +static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); +static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch); +static int etek_write_room (struct tty_struct *tty); +static int etek_chars_in_buffer (struct tty_struct *tty); +static void etek_throttle (struct tty_struct * tty); +static void etek_unthrottle (struct tty_struct * tty); + + +/* function prototypes for a "generic" type serial converter (no flow control, not all endpoints needed) */ +static int generic_serial_open (struct tty_struct *tty, struct file * filp); +static void generic_serial_close (struct tty_struct *tty, struct file * filp); +static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count); +static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch); +static int generic_write_room (struct tty_struct *tty); +static int generic_chars_in_buffer (struct tty_struct *tty); + + +/* This structure defines the individual serial converter. */ +struct usb_serial_device_type { + char *name; + __u16 *idVendor; + __u16 *idProduct; + char needs_interrupt_in; + char needs_bulk_in; + char needs_bulk_out; + // add function calls + + int (*open)(struct tty_struct * tty, struct file * filp); + void (*close)(struct tty_struct * tty, struct file * filp); + int (*write)(struct tty_struct * tty, int from_user,const unsigned char *buf, int count); + void (*put_char)(struct tty_struct *tty, unsigned char ch); + int (*write_room)(struct tty_struct *tty); + int (*chars_in_buffer)(struct tty_struct *tty); + void (*throttle)(struct tty_struct * tty); + void (*unthrottle)(struct tty_struct * tty); + +}; + + +/* All of the device info needed for the Belkin Serial Converter */ +static __u16 belkin_vendor_id = BELKIN_VENDOR_ID; +static __u16 belkin_product_id = BELKIN_SERIAL_CONVERTER; +static struct usb_serial_device_type belkin_device = { + "Belkin", + &belkin_vendor_id, /* the Belkin vendor id */ + &belkin_product_id, /* the Belkin serial converter product id */ + MUST_HAVE, /* this device must have an interrupt in endpoint */ + MUST_HAVE, /* this device must have a bulk in endpoint */ + MUST_HAVE, /* this device must have a bulk out endpoint */ + etek_serial_open, + etek_serial_close, + etek_serial_write, + etek_serial_put_char, + etek_write_room, + etek_chars_in_buffer, + etek_throttle, + etek_unthrottle +}; + +/* All of the device info needed for the Peracom Serial Converter */ +static __u16 peracom_vendor_id = PERACOM_VENDOR_ID; +static __u16 peracom_product_id = PERACOM_SERIAL_CONVERTER; +static struct usb_serial_device_type peracom_device = { + "Peracom", + &peracom_vendor_id, /* the Peracom vendor id */ + &peracom_product_id, /* the Peracom serial converter product id */ + MUST_HAVE, /* this device must have an interrupt in endpoint */ + MUST_HAVE, /* this device must have a bulk in endpoint */ + MUST_HAVE, /* this device must have a bulk out endpoint */ + etek_serial_open, + etek_serial_close, + etek_serial_write, + etek_serial_put_char, + etek_write_room, + etek_chars_in_buffer, + etek_throttle, + etek_unthrottle +}; + +/* All of the device info needed for the Generic Serial Converter */ +static struct usb_serial_device_type generic_device = { + "Generic", + &vendor, /* use the user specified vendor id */ + &product, /* use the user specified product id */ + DONT_CARE, /* don't have to have an interrupt in endpoint */ + DONT_CARE, /* don't have to have a bulk in endpoint */ + DONT_CARE, /* don't have to have a bulk out endpoint */ + generic_serial_open, + generic_serial_close, + generic_serial_write, + generic_serial_put_char, + generic_write_room, + generic_chars_in_buffer, + NULL, /* generic driver does not implement any flow control */ + NULL /* generic driver does not implement any flow control */ +}; + + +/* To add support for another serial converter, create a usb_serial_device_type + structure for that device, and add it to this list, making sure that the last + entry is NULL. */ +static struct usb_serial_device_type *usb_serial_devices[] = { + &generic_device, + &belkin_device, + &peracom_device, + NULL +}; + + struct usb_serial_state { - struct usb_device * dev; - SERIAL_TYPE type; /* what manufacturer's type of converter */ - void * irq_handle; - unsigned int irqpipe; - struct tty_struct *tty; /* the coresponding tty for this device */ - char present; - char active; - - char interrupt_in_inuse; + struct usb_device * dev; + struct usb_serial_device_type * type; + void * irq_handle; + unsigned int irqpipe; + struct tty_struct * tty; /* the coresponding tty for this device */ + char present; + char active; + + char has_interrupt_in; /* if this device has an interrupt in pipe or not */ + char interrupt_in_inuse; /* if the interrupt in endpoint is in use */ __u8 interrupt_in_endpoint; __u8 interrupt_in_interval; - __u16 interrupt_in_size; + __u16 interrupt_in_size; /* the size of the interrupt in endpoint */ unsigned int interrupt_in_pipe; unsigned char * interrupt_in_buffer; void * interrupt_in_transfer; - char bulk_in_inuse; + char has_bulk_in; /* if thie device has a bulk in pipe or not */ + char bulk_in_inuse; /* if the bulk in endpoint is in use */ __u8 bulk_in_endpoint; __u8 bulk_in_interval; - __u16 bulk_in_size; + __u16 bulk_in_size; /* the size of the bulk in endpoint */ unsigned int bulk_in_pipe; unsigned char * bulk_in_buffer; void * bulk_in_transfer; - char bulk_out_inuse; + char has_bulk_out; /* if this device has a bulk out pipe or not */ + char bulk_out_inuse; /* if the bulk out endpoint is in use */ __u8 bulk_out_endpoint; __u8 bulk_out_interval; - __u16 bulk_out_size; + __u16 bulk_out_size; /* the size of the bulk out endpoint */ unsigned int bulk_out_pipe; unsigned char * bulk_out_buffer; void * bulk_out_transfer; @@ -197,36 +349,25 @@ static int usb_serial_irq (int state, void *buffer, int len, void *dev_id) - -/* tty interface functions */ +/***************************************************************************** + * Driver tty interface functions + *****************************************************************************/ static int serial_open (struct tty_struct *tty, struct file * filp) { struct usb_serial_state *serial; debug_info("USB: serial_open\n"); + /* assign a serial object to the tty pointer */ serial = &serial_state_table [MINOR(tty->device)-tty->driver.minor_start]; tty->driver_data = serial; serial->tty = tty; - if (!serial->present) { - debug_info("USB Serial: no device registered\n"); - return -EINVAL; + /* pass on to the driver specific version of this function */ + if (serial->type->open) { + return (serial->type->open(tty, filp)); } - - if (serial->active) { - debug_info ("USB Serial: device already open\n"); - return -EINVAL; - } - serial->active = 1; - - /*Start reading from the device*/ - serial->bulk_in_inuse = 1; - serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); - - /* Need to do device specific setup here (control lines, baud rate, etc.) */ - /* FIXME!!! */ - + return (0); } @@ -246,28 +387,16 @@ static void serial_close(struct tty_struct *tty, struct file * filp) return; } - /* Need to change the control lines here */ - /* FIXME */ - - if (serial->bulk_out_inuse){ - usb_terminate_bulk (serial->dev, serial->bulk_out_transfer); - serial->bulk_out_inuse = 0; + /* pass on to the driver specific version of this function */ + if (serial->type->close) { + serial->type->close(tty, filp); } - if (serial->bulk_in_inuse){ - usb_terminate_bulk (serial->dev, serial->bulk_in_transfer); - serial->bulk_in_inuse = 0; - } - - /* release the irq? */ - - serial->active = 0; -} +} static int serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; - int written; debug_info("USB Serial: serial_write\n"); @@ -281,26 +410,14 @@ static int serial_write (struct tty_struct * tty, int from_user, const unsigned return (-EINVAL); } - if (serial->bulk_out_inuse) { - debug_info ("USB Serial: already writing\n"); - return (0); - } - - written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count; - - if (from_user) { - copy_from_user(serial->bulk_out_buffer, buf, written); + /* pass on to the driver specific version of this function */ + if (serial->type->write) { + return (serial->type->write(tty, from_user, buf, count)); } - else { - memcpy (serial->bulk_out_buffer, buf, written); - } - /* send the data out the bulk port */ - serial->bulk_out_inuse = 1; - serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial); - - return (written); -} + /* no specific driver, so return that we didn't write anything */ + return (0); +} static void serial_put_char (struct tty_struct *tty, unsigned char ch) @@ -319,18 +436,13 @@ static void serial_put_char (struct tty_struct *tty, unsigned char ch) return; } - if (serial->bulk_out_inuse) { - debug_info ("USB Serial: already writing\n"); - return; + /* pass on to the driver specific version of this function */ + if (serial->type->put_char) { + serial->type->put_char(tty, ch); } - /* send the single character out the bulk port */ - serial->bulk_out_buffer[0] = ch; - serial->bulk_out_inuse = 1; - serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial); - return; -} +} static int serial_write_room (struct tty_struct *tty) @@ -349,11 +461,12 @@ static int serial_write_room (struct tty_struct *tty) return (-EINVAL); } - if (serial->bulk_out_inuse) { - return (0); + /* pass on to the driver specific version of this function */ + if (serial->type->write_room) { + return (serial->type->write_room(tty)); } - return serial->bulk_out_size; + return (0); } @@ -373,8 +486,9 @@ static int serial_chars_in_buffer (struct tty_struct *tty) return (-EINVAL); } - if (serial->bulk_out_inuse) { - return (serial->bulk_out_size); + /* pass on to the driver specific version of this function */ + if (serial->type->chars_in_buffer) { + return (serial->type->chars_in_buffer(tty)); } return (0); @@ -397,9 +511,10 @@ static void serial_throttle (struct tty_struct * tty) return; } - - /* Change the control signals */ - /* FIXME!!! */ + /* pass on to the driver specific version of this function */ + if (serial->type->throttle) { + serial->type->throttle(tty); + } return; } @@ -422,6 +537,153 @@ static void serial_unthrottle (struct tty_struct * tty) } + /* pass on to the driver specific version of this function */ + if (serial->type->unthrottle) { + serial->type->unthrottle(tty); + } + + return; +} + + +/***************************************************************************** + * eTek specific driver functions + *****************************************************************************/ +static int etek_serial_open (struct tty_struct *tty, struct file *filp) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + + debug_info("USB: etek_serial_open\n"); + + if (!serial->present) { + debug_info("USB Serial: no device registered\n"); + return -EINVAL; + } + + if (serial->active) { + debug_info ("USB Serial: device already open\n"); + return -EINVAL; + } + serial->active = 1; + + /*Start reading from the device*/ + serial->bulk_in_inuse = 1; + serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); + + /* Need to do device specific setup here (control lines, baud rate, etc.) */ + /* FIXME!!! */ + + return (0); +} + + +static void etek_serial_close(struct tty_struct *tty, struct file * filp) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + debug_info("USB: etek_serial_close\n"); + + /* Need to change the control lines here */ + /* FIXME */ + + /* shutdown our bulk reads and writes */ + if (serial->bulk_out_inuse){ + usb_terminate_bulk (serial->dev, serial->bulk_out_transfer); + serial->bulk_out_inuse = 0; + } + if (serial->bulk_in_inuse){ + usb_terminate_bulk (serial->dev, serial->bulk_in_transfer); + serial->bulk_in_inuse = 0; + } + + /* release the irq? */ + + serial->active = 0; +} + + +static int etek_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + int written; + + debug_info("USB Serial: etek_serial_write\n"); + + if (serial->bulk_out_inuse) { + debug_info ("USB Serial: already writing\n"); + return (0); + } + + written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count; + + if (from_user) { + copy_from_user(serial->bulk_out_buffer, buf, written); + } + else { + memcpy (serial->bulk_out_buffer, buf, written); + } + + /* send the data out the bulk port */ + serial->bulk_out_inuse = 1; + serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial); + + return (written); +} + + +static void etek_serial_put_char (struct tty_struct *tty, unsigned char ch) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: etek_serial_put_char\n"); + + if (serial->bulk_out_inuse) { + debug_info ("USB Serial: already writing\n"); + return; + } + + /* send the single character out the bulk port */ + serial->bulk_out_buffer[0] = ch; + serial->bulk_out_inuse = 1; + serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial); + + return; +} + + +static int etek_write_room (struct tty_struct *tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: etek_write_room\n"); + + if (serial->bulk_out_inuse) { + return (0); + } + + return (serial->bulk_out_size); +} + + +static int etek_chars_in_buffer (struct tty_struct *tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: etek_chars_in_buffer\n"); + + if (serial->bulk_out_inuse) { + return (serial->bulk_out_size); + } + + return (0); +} + + +static void etek_throttle (struct tty_struct * tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + + debug_info("USB Serial: etek_throttle\n"); + /* Change the control signals */ /* FIXME!!! */ @@ -429,6 +691,160 @@ static void serial_unthrottle (struct tty_struct * tty) } +static void etek_unthrottle (struct tty_struct * tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + + debug_info("USB Serial: etek_unthrottle\n"); + + /* Change the control signals */ + /* FIXME!!! */ + + return; +} + + +/***************************************************************************** + * generic devices specific driver functions + *****************************************************************************/ +static int generic_serial_open (struct tty_struct *tty, struct file *filp) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + + debug_info("USB: generic_serial_open\n"); + + if (!serial->present) { + debug_info("USB Serial: no device registered\n"); + return -EINVAL; + } + + if (serial->active) { + debug_info ("USB Serial: device already open\n"); + return -EINVAL; + } + serial->active = 1; + + /* if we have a bulk interrupt, start reading from it */ + if (serial->has_bulk_in) { + /*Start reading from the device*/ + serial->bulk_in_inuse = 1; + serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); + } + + return (0); +} + + +static void generic_serial_close(struct tty_struct *tty, struct file * filp) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + debug_info("USB: generic_serial_close\n"); + + /* shutdown any bulk reads that might be going on */ + if (serial->bulk_out_inuse){ + usb_terminate_bulk (serial->dev, serial->bulk_out_transfer); + serial->bulk_out_inuse = 0; + } + if (serial->bulk_in_inuse){ + usb_terminate_bulk (serial->dev, serial->bulk_in_transfer); + serial->bulk_in_inuse = 0; + } + + serial->active = 0; +} + + +static int generic_serial_write (struct tty_struct * tty, int from_user, const unsigned char *buf, int count) +{ + struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; + int written; + + debug_info("USB Serial: generic_serial_write\n"); + + /* only do something if we have a bulk out endpoint */ + if (serial->has_bulk_out) { + if (serial->bulk_out_inuse) { + debug_info ("USB Serial: already writing\n"); + return (0); + } + + written = (count > serial->bulk_out_size) ? serial->bulk_out_size : count; + + if (from_user) { + copy_from_user(serial->bulk_out_buffer, buf, written); + } + else { + memcpy (serial->bulk_out_buffer, buf, written); + } + + /* send the data out the bulk port */ + serial->bulk_out_inuse = 1; + serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, written, serial); + + return (written); + } + + /* no bulk out, so return 0 bytes written */ + return (0); +} + + +static void generic_serial_put_char (struct tty_struct *tty, unsigned char ch) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: generic_serial_put_char\n"); + + /* if we have a bulk out endpoint, then shove a character out it */ + if (serial->has_bulk_out) { + if (serial->bulk_out_inuse) { + debug_info ("USB Serial: already writing\n"); + return; + } + + /* send the single character out the bulk port */ + serial->bulk_out_buffer[0] = ch; + serial->bulk_out_inuse = 1; + serial->bulk_out_transfer = usb_request_bulk (serial->dev, serial->bulk_out_pipe, serial_write_irq, serial->bulk_out_buffer, 1, serial); + } + + return; +} + + +static int generic_write_room (struct tty_struct *tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: generic_write_room\n"); + + if (serial->has_bulk_out) { + if (serial->bulk_out_inuse) { + return (0); + } + return (serial->bulk_out_size); + } + + return (0); +} + + +static int generic_chars_in_buffer (struct tty_struct *tty) +{ + struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data; + + debug_info("USB Serial: generic_chars_in_buffer\n"); + + if (serial->has_bulk_out) { + if (serial->bulk_out_inuse) { + return (serial->bulk_out_size); + } + } + + return (0); +} + + static int Get_Free_Serial (void) { int i; @@ -443,122 +859,172 @@ static int Get_Free_Serial (void) static void * usb_serial_probe(struct usb_device *dev, unsigned int ifnum) { - struct usb_serial_state *serial; + struct usb_serial_state *serial = NULL; struct usb_interface_descriptor *interface; struct usb_endpoint_descriptor *endpoint; - SERIAL_TYPE type; + struct usb_endpoint_descriptor *interrupt_in_endpoint = NULL; + struct usb_endpoint_descriptor *bulk_in_endpoint = NULL; + struct usb_endpoint_descriptor *bulk_out_endpoint = NULL; +// SERIAL_TYPE type; + struct usb_serial_device_type *type; + int device_num; int serial_num; // int ret; int i; + char interrupt_pipe; + char bulk_in_pipe; + char bulk_out_pipe; - /* look at the device descriptor to see if it is a type that we recognize */ - type = unknown; - if ((dev->descriptor.idVendor == BELKIN_VENDOR_ID) && - (dev->descriptor.idProduct == BELKIN_SERIAL_CONVERTER)) { - /* This is the Belkin serial convertor */ - type = Belkin; - } - - if ((dev->descriptor.idVendor == PERACOM_VENDOR_ID) && - (dev->descriptor.idProduct == PERACOM_SERIAL_CONVERTER)) { - /* This is the Peracom serial convertor */ - type = Peracom; - } - - if (type == unknown) - return NULL; - - printk (KERN_INFO "USB serial converter detected.\n"); - - if (0>(serial_num = Get_Free_Serial())) { - debug_info("USB Serial: Too many devices connected\n"); - return NULL; - } - - serial = &serial_state_table[serial_num]; - - memset(serial, 0, sizeof(serial)); - serial->dev = dev; - serial->type = type; - - /* we should have 1 bulk in, 1 bulk out, and 1 interrupt in endpoints */ - interface = &dev->actconfig->interface[ifnum].altsetting[0]; - for (i = 0; i < interface->bNumEndpoints; ++i) { - endpoint = &interface->endpoint[i]; + /* loop through our list of known serial converters, and see if this device matches */ + device_num = 0; + while (usb_serial_devices[device_num] != NULL) { + type = usb_serial_devices[device_num]; + #ifdef SERIAL_DEBUG + printk ("Looking at %s\nVendor id=%.4x\nProduct id=%.4x", type->name, *(type->idVendor), *(type->idProduct)); + #endif + + /* look at the device descriptor */ + if ((dev->descriptor.idVendor == *(type->idVendor)) && + (dev->descriptor.idProduct == *(type->idProduct))) { + + debug_info("descriptor matches...looking at the endpoints\n") + + /* descriptor matches, let's try to find the endpoints needed */ + interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT; + + /* check out the endpoints */ + interface = &dev->actconfig->interface[ifnum].altsetting[0]; + for (i = 0; i < interface->bNumEndpoints; ++i) { + endpoint = &interface->endpoint[i]; - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found the bulk in endpoint */ - serial->bulk_in_inuse = 0; - serial->bulk_in_endpoint = endpoint->bEndpointAddress; - serial->bulk_in_size = endpoint->wMaxPacketSize; - serial->bulk_in_interval = endpoint->bInterval; - serial->bulk_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); - serial->bulk_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL); - if (!serial->bulk_in_buffer) { - printk("USB Serial: Couldn't allocate bulk_in_buffer\n"); - goto probe_error; - } - } + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk in endpoint */ + debug_info("found bulk in\n"); + if (bulk_in_pipe == HAS) { + printk("USB Serial: can't have more than one bulk in endpoint\n"); + goto probe_error; + } + bulk_in_pipe = HAS; + bulk_in_endpoint = endpoint; + } + + if (((endpoint->bEndpointAddress & 0x80) == 0x00) && + ((endpoint->bmAttributes & 3) == 0x02)) { + /* we found a bulk out endpoint */ + debug_info("found bulk out\n"); + if (bulk_out_pipe == HAS) { + printk("USB Serial: can't have more than one bulk out endpoint\n"); + goto probe_error; + } + bulk_out_pipe = HAS; + bulk_out_endpoint = endpoint; + } + + if ((endpoint->bEndpointAddress & 0x80) && + ((endpoint->bmAttributes & 3) == 0x03)) { + /* we found a interrupt in endpoint */ + debug_info("found interrupt in\n"); + if (interrupt_pipe == HAS) { + printk("USB Serial: can't have more than one interrupt in endpoint\n"); + goto probe_error; + } + interrupt_pipe = HAS; + interrupt_in_endpoint = endpoint; + } - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x02)) { - /* we found the bulk out endpoint */ - serial->bulk_out_inuse = 0; - serial->bulk_out_endpoint = endpoint->bEndpointAddress; - serial->bulk_out_size = endpoint->wMaxPacketSize; - serial->bulk_out_interval = endpoint->bInterval; - serial->bulk_out_pipe = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint); - serial->bulk_out_buffer = kmalloc (serial->bulk_out_size, GFP_KERNEL); - if (!serial->bulk_out_buffer) { - printk("USB Serial: Couldn't allocate bulk_out_buffer\n"); - goto probe_error; } - } - - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x03)) { - /* we found the interrupt in endpoint */ - serial->interrupt_in_inuse = 0; - serial->interrupt_in_endpoint = endpoint->bEndpointAddress; - serial->interrupt_in_size = endpoint->wMaxPacketSize; - serial->interrupt_in_interval = endpoint->bInterval; - /* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */ - serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL); - if (!serial->interrupt_in_buffer) { - printk("USB Serial: Couldn't allocate interrupt_in_buffer\n"); - goto probe_error; + + /* verify that we found all of the endpoints that we need */ + if ((interrupt_pipe & type->needs_interrupt_in) && + (bulk_in_pipe & type->needs_bulk_in) && + (bulk_out_pipe & type->needs_bulk_out)) { + /* found all that we need */ + printk (KERN_INFO "USB serial converter detected.\n"); + + if (0>(serial_num = Get_Free_Serial())) { + debug_info("USB Serial: Too many devices connected\n"); + return NULL; + } + + serial = &serial_state_table[serial_num]; + + memset(serial, 0, sizeof(struct usb_serial_state)); + serial->dev = dev; + serial->type = type; + + /* set up the endpoint information */ + if (bulk_in_endpoint) { + serial->has_bulk_in = 1; + serial->bulk_in_inuse = 0; + serial->bulk_in_endpoint = bulk_in_endpoint->bEndpointAddress; + serial->bulk_in_size = bulk_in_endpoint->wMaxPacketSize; + serial->bulk_in_interval = bulk_in_endpoint->bInterval; + serial->bulk_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); + serial->bulk_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL); + if (!serial->bulk_in_buffer) { + printk("USB Serial: Couldn't allocate bulk_in_buffer\n"); + goto probe_error; + } + } + + if (bulk_out_endpoint) { + serial->has_bulk_out = 1; + serial->bulk_out_inuse = 0; + serial->bulk_out_endpoint = bulk_out_endpoint->bEndpointAddress; + serial->bulk_out_size = bulk_out_endpoint->wMaxPacketSize; + serial->bulk_out_interval = bulk_out_endpoint->bInterval; + serial->bulk_out_pipe = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint); + serial->bulk_out_buffer = kmalloc (serial->bulk_out_size, GFP_KERNEL); + if (!serial->bulk_out_buffer) { + printk("USB Serial: Couldn't allocate bulk_out_buffer\n"); + goto probe_error; + } + } + + if (interrupt_in_endpoint) { + serial->has_interrupt_in = 1; + serial->interrupt_in_inuse = 0; + serial->interrupt_in_endpoint = interrupt_in_endpoint->bEndpointAddress; + serial->interrupt_in_size = interrupt_in_endpoint->wMaxPacketSize; + serial->interrupt_in_interval = interrupt_in_endpoint->bInterval; + /* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */ + serial->interrupt_in_buffer = kmalloc (serial->bulk_in_size, GFP_KERNEL); + if (!serial->interrupt_in_buffer) { + printk("USB Serial: Couldn't allocate interrupt_in_buffer\n"); + goto probe_error; + } + } + + #if 0 + /* set up an interrupt for out bulk in pipe */ + /* ask for a bulk read */ + serial->bulk_in_inuse = 1; + serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); + + /* set up our interrupt to be the time for the bulk in read */ + ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle); + if (ret) { + printk(KERN_INFO "USB Serial failed usb_request_irq (0x%x)\n", ret); + goto probe_error; + } + #endif + + serial->present = 1; + MOD_INC_USE_COUNT; + + return serial; + } else { + printk(KERN_INFO "USB Serial, descriptors matched, but endpoints did not\n"); } } + /* look at the next type in our list */ + ++device_num; } - - /* verify that we found all of the endpoints that we need */ - if ((!serial->bulk_in_buffer) || - (!serial->bulk_out_buffer) || - (!serial->interrupt_in_buffer)) { - printk("USB Serial: did not find all of the required endpoints\n"); - goto probe_error; - } - - /* set up an interrupt for out bulk in pipe */ - /* ask for a bulk read */ -// serial->bulk_in_inuse = 1; -// serial->bulk_in_transfer = usb_request_bulk (serial->dev, serial->bulk_in_pipe, serial_read_irq, serial->bulk_in_buffer, serial->bulk_in_size, serial); - - /* set up our interrupt to be the time for the bulk in read */ -// ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle); -// if (ret) { -// printk(KERN_INFO "USB Serial failed usb_request_irq (0x%x)\n", ret); -// goto probe_error; -// } - - serial->present = 1; - MOD_INC_USE_COUNT; - return serial; probe_error: if (serial) { @@ -636,6 +1102,8 @@ int usb_serial_init(void) serial_tty_driver.flags = TTY_DRIVER_REAL_RAW; serial_tty_driver.refcount = &serial_refcount; serial_tty_driver.table = serial_tty; + serial_tty_driver.proc_entry = NULL; + serial_tty_driver.other = NULL; serial_tty_driver.termios = serial_termios; serial_tty_driver.termios_locked = serial_termios_locked; diff --git a/fs/buffer.c b/fs/buffer.c index cf0f89722826..befe7bcecab3 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -823,7 +823,7 @@ static int balance_dirty_state(kdev_t dev) unsigned long dirty, tot, hard_dirty_limit, soft_dirty_limit; dirty = size_buffers_type[BUF_DIRTY] >> PAGE_SHIFT; - tot = nr_lru_pages + nr_free_pages - nr_free_highpages; + tot = nr_free_buffer_pages(); hard_dirty_limit = tot * bdf_prm.b_un.nfract / 100; soft_dirty_limit = hard_dirty_limit >> 1; diff --git a/fs/exec.c b/fs/exec.c index d94f55e5f4b9..8dda57102ac4 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -225,14 +225,16 @@ int copy_strings(int argc,char ** argv, struct linux_binprm *bprm) page = bprm->page[i]; new = 0; if (!page) { + unsigned long pageaddr; /* * Cannot yet use highmem page because * we cannot sleep with a kmap held. */ - page = __get_pages(GFP_USER, 0); - bprm->page[i] = page; - if (!page) + pageaddr = __get_free_page(GFP_USER); + if (!pageaddr) return -ENOMEM; + page = mem_map + MAP_NR(pageaddr); + bprm->page[i] = page; new = 1; } kaddr = (char *)kmap(page, KM_WRITE); diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index 1db720ca6957..c006ee6bca66 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -16,7 +16,8 @@ #include #include #include -#include +#include + #include #ifdef CONFIG_KCORE_AOUT @@ -211,7 +212,7 @@ static void elf_kcore_store_hdr(char *bufp) #ifdef CONFIG_MODULES { struct module *m; - read_lock(&modlist_lock); + lock_kernel(); for (m=module_list; m; m=m->next) { dhdr = (struct elf_phdr *) bufp; bufp += sizeof(struct elf_phdr); @@ -227,7 +228,7 @@ static void elf_kcore_store_hdr(char *bufp) dhdr->p_align = 0; elf->e_phnum++; } - read_unlock(&modlist_lock); + lock_kernel(); } #endif diff --git a/fs/proc/procfs_syms.c b/fs/proc/procfs_syms.c index fa2ee362ee0c..7a1732ae4d0a 100644 --- a/fs/proc/procfs_syms.c +++ b/fs/proc/procfs_syms.c @@ -18,6 +18,8 @@ EXPORT_SYMBOL(proc_get_inode); EXPORT_SYMBOL(proc_dir_inode_operations); EXPORT_SYMBOL(proc_net); EXPORT_SYMBOL(proc_bus); +EXPORT_SYMBOL(proc_lookup); +EXPORT_SYMBOL(proc_readdir); #if defined(CONFIG_SUN_OPENPROMFS_MODULE) EXPORT_SYMBOL(proc_openprom_register); diff --git a/fs/udf/misc.c b/fs/udf/misc.c index f5b36dc7fe23..74b2c3965786 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c @@ -24,11 +24,10 @@ * 04/19/99 blf partial support for reading/writing specific EA's */ +#include "udfdecl.h" #if defined(__linux__) && defined(__KERNEL__) -#include "udfdecl.h" - #include "udf_sb.h" #include "udf_i.h" @@ -38,7 +37,6 @@ #else -#include "udfdecl.h" #include #include #include diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 037a3d2f599b..8802360fee7d 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -6,7 +6,6 @@ #ifdef __KERNEL__ #include -#include #include #include @@ -18,16 +17,14 @@ #error "The UDF Module Current Requires Kernel Version 2.3.7 or greater" #endif +#include /* if we're not defined, we must be compiling outside of the kernel tree */ #if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE) /* ... so override config */ #define CONFIG_UDF_FS_MODULE -#include /* explicitly include udf_fs_sb.h and udf_fs_i.h */ #include #include -#else -#include /* also gets udf_fs_i.h and udf_fs_sb.h */ #endif struct dentry; @@ -113,10 +110,10 @@ extern int udf_sync_file(struct file *, struct dentry *); #else #include -#include #endif /* __KERNEL__ */ +#include #include "udfend.h" /* structures */ diff --git a/include/asm-ppc/div64.h b/include/asm-ppc/div64.h new file mode 100644 index 000000000000..114e6ab34147 --- /dev/null +++ b/include/asm-ppc/div64.h @@ -0,0 +1,10 @@ +#ifndef __PPC_DIV64 +#define __PPC_DIV64 + +#define do_div(n,base) ({ \ +int __res; \ +__res = ((unsigned long) n) % (unsigned) base; \ +n = ((unsigned long) n) / (unsigned) base; \ +__res; }) + +#endif diff --git a/include/asm-ppc/fcntl.h b/include/asm-ppc/fcntl.h index a1f3aa7f797a..6fe5596e378d 100644 --- a/include/asm-ppc/fcntl.h +++ b/include/asm-ppc/fcntl.h @@ -16,8 +16,10 @@ #define O_NDELAY O_NONBLOCK #define O_SYNC 010000 #define FASYNC 020000 /* fcntl, for BSD compatibility */ -#define O_DIRECTORY 040000 /* must be a directory */ -#define O_NOFOLLOW 0100000 /* don't follow links */ +#define O_DIRECTORY 040000 /* must be a directory */ +#define O_NOFOLLOW 100000 /* don't follow links */ +#define O_LARGEFILE 200000 +#define O_DIRECT 400000 /* direct disk access hint - currently ignored */ #define F_DUPFD 0 /* dup */ #define F_GETFD 1 /* get f_flags */ diff --git a/include/asm-ppc/processor.h b/include/asm-ppc/processor.h index 7030d2cf9373..a78c75b4ebc1 100644 --- a/include/asm-ppc/processor.h +++ b/include/asm-ppc/processor.h @@ -318,8 +318,8 @@ static inline unsigned long thread_saved_pc(struct thread_struct *t) unsigned long get_wchan(struct task_struct *p); -#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip) -#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1]) +#define KSTK_EIP(tsk) ((tsk)->thread.regs->nip) +#define KSTK_ESP(tsk) ((tsk)->thread.regs->gpr[1]) /* * NOTE! The task struct and the stack go together diff --git a/include/linux/highmem.h b/include/linux/highmem.h index ac5170e83eb3..48e87859b0e2 100644 --- a/include/linux/highmem.h +++ b/include/linux/highmem.h @@ -13,18 +13,18 @@ extern struct page *highmem_start_page; /* declarations for linux/mm/highmem.c */ extern unsigned long highmem_mapnr; -extern unsigned long nr_free_highpages; +FASTCALL(unsigned int nr_free_highpages(void)); extern struct page * prepare_highmem_swapout(struct page *); extern struct page * replace_with_highmem(struct page *); #else /* CONFIG_HIGHMEM */ +extern inline unsigned int nr_free_highpages(void) { return 0; } #define prepare_highmem_swapout(page) page #define replace_with_highmem(page) page #define kmap(page, type) page_address(page) #define kunmap(vaddr, type) do { } while (0) -#define nr_free_highpages 0UL #endif /* CONFIG_HIGHMEM */ diff --git a/include/linux/i2o.h b/include/linux/i2o.h index aafe8d3a5e24..01140c30a79d 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -100,40 +100,40 @@ typedef struct _i2o_pci_bus { u8 reserved; u16 PciVendorID; u16 PciDeviceID; -} i2o_pci_bus, *pi2o_pci_bus; +} i2o_pci_bus; typedef struct _i2o_local_bus { u16 LbBaseIOPort; u16 reserved; u32 LbBaseMemoryAddress; -} i2o_local_bus, *pi2o_local_bus; +} i2o_local_bus; typedef struct _i2o_isa_bus { u16 IsaBaseIOPort; u8 CSN; u8 reserved; u32 IsaBaseMemoryAddress; -} i2o_isa_bus, *pi2o_isa_bus; +} i2o_isa_bus; typedef struct _i2o_eisa_bus_info { u16 EisaBaseIOPort; u8 reserved; u8 EisaSlotNumber; u32 EisaBaseMemoryAddress; -} i2o_eisa_bus, *pi2o_eisa_bus; +} i2o_eisa_bus; typedef struct _i2o_mca_bus { u16 McaBaseIOPort; u8 reserved; u8 McaSlotNumber; u32 McaBaseMemoryAddress; -} i2o_mca_bus, *pi2o_mca_bus; +} i2o_mca_bus; typedef struct _i2o_other_bus { u16 BaseIOPort; u16 reserved; u32 BaseMemoryAddress; -} i2o_other_bus, *pi2o_other_bus; +} i2o_other_bus; typedef struct _i2o_hrt_entry { u32 adapter_id; @@ -149,7 +149,7 @@ typedef struct _i2o_hrt_entry { i2o_mca_bus mca_bus; i2o_other_bus other_bus; } bus; -} i2o_hrt_entry, *pi2o_hrt_entry; +} i2o_hrt_entry; typedef struct _i2o_hrt { u16 num_entries; @@ -157,7 +157,7 @@ typedef struct _i2o_hrt { u8 hrt_version; u32 change_ind; i2o_hrt_entry hrt_entry[1]; -} i2o_hrt, *pi2o_hrt; +} i2o_hrt; typedef struct _i2o_lct_entry { u32 entry_size:16; @@ -174,7 +174,7 @@ typedef struct _i2o_lct_entry { u32 bios_info:8; u8 identity_tag[8]; u32 event_capabilities; -} i2o_lct_entry, *pi2o_lct_entry; +} i2o_lct_entry; typedef struct _i2o_lct { u32 table_size:16; @@ -183,7 +183,7 @@ typedef struct _i2o_lct { u32 iop_flags; u32 current_change_ind; i2o_lct_entry lct_entry[1]; -} i2o_lct, *pi2o_lct; +} i2o_lct; typedef struct _i2o_status_block { u16 org_id; @@ -199,6 +199,7 @@ typedef struct _i2o_status_block { u8 init_code; u8 reserved2; u32 max_inbound_frames; + u32 cur_inbound_frames; u32 max_outbound_frames; char product_id[24]; u32 expected_lct_size; @@ -211,9 +212,38 @@ typedef struct _i2o_status_block { u32 current_io_base; u32 reserved3:24; u32 cmd_status:8; -} i2o_status_block, *pi2o_status_block; +} i2o_status_block; - +/* Event indicator mask flags */ +#define I2O_EVT_IND_STATE_CHANGE 0x80000000 +#define I2O_EVT_IND_GENERAL_WARNING 0x40000000 +#define I2O_EVT_IND_CONFIGURATION_FLAG 0x20000000 +#define I2O_EVT_IND_LOCK_RELEASE 0x10000000 +#define I2O_EVT_IND_CAPABILITY_CHANGE 0x08000000 +#define I2O_EVT_IND_DEVICE_RESET 0x04000000 +#define I2O_EVT_IND_EVT_MASK_MODIFIED 0x02000000 +#define I2O_EVT_IND_FIELD_MODIFIED 0x01000000 +#define I2O_EVT_IND_VENDOR_EVT 0x00800000 +#define I2O_EVT_IND_DEVICE_STATE 0x00400000 + +/* Event data for generic events */ +#define I2O_EVT_STATE_CHANGE_NORMAL 0x00 +#define I2O_EVT_STATE_CHANGE_SUSPENDED 0x01 +#define I2O_EVT_STATE_CHANGE_RESTART 0x02 +#define I2O_EVT_STATE_CHANGE_NA_RECOVER 0x03 +#define I2O_EVT_STATE_CHANGE_NA_NO_RECOVER 0x04 +#define I2O_EVT_STATE_CHANGE_QUIESCE_REQUEST 0x05 +#define I2O_EVT_STATE_CHANGE_FAILED 0x10 +#define I2O_EVT_STATE_CHANGE_FAULTED 0x11 + +#define I2O_EVT_GEN_WARNING_NORMAL 0x00 +#define I2O_EVT_GEN_WARNING_ERROR_THRESHOLD 0x01 +#define I2O_EVT_GEN_WARNING_MEDIA_FAULT 0x02 + +#define I2O_EVT_CAPABILITY_OTHER 0x01 +#define I2O_EVT_CAPABILITY_CHANGED 0x02 + +#define I2O_EVT_SENSOR_STATE_CHANGED 0x01 #ifdef __KERNEL__ /* ioctl stuff only thing exported to users */ @@ -246,7 +276,7 @@ struct i2o_message struct i2o_device { - pi2o_lct_entry lct_data;/* Device LCT information */ + i2o_lct_entry *lct_data;/* Device LCT information */ u32 flags; int i2oversion; /* I2O version supported. Actually there * should be high and low version */ @@ -286,7 +316,7 @@ struct i2o_controller char name[16]; int unit; int type; - int enabled; /* Bus level enable */ + int enabled; #define I2O_TYPE_PCI 0x01 /* PCI I2O controller */ @@ -298,9 +328,9 @@ struct i2o_controller volatile u32 *reply_port; volatile u32 *irq_mask; /* Interrupt port */ - pi2o_status_block status_block; /* IOP status block */ - pi2o_lct lct; - pi2o_hrt hrt; + i2o_status_block *status_block; /* IOP status block */ + i2o_lct *lct; + i2o_hrt *hrt; u32 mem_offset; /* MFA offset */ u32 mem_phys; /* MFA physical */ @@ -464,22 +494,22 @@ extern int i2o_release_device(struct i2o_device *, struct i2o_handler *, u32); extern int i2o_post_this(struct i2o_controller *, u32 *, int); extern int i2o_post_wait(struct i2o_controller *, u32 *, int, int); -extern int i2o_issue_claim(struct i2o_controller *, int, int, int, int *, u32); extern int i2o_issue_params(int, struct i2o_controller *, int, void *, int, void *, int); -extern int i2o_query_scalar(struct i2o_controller *, int, int, int, - void *, int); -extern int i2o_set_scalar(struct i2o_controller *, int, int, int, - void *, int); +extern int i2o_query_scalar(struct i2o_controller *, int, int, int, void *, int); +extern int i2o_set_scalar(struct i2o_controller *, int, int, int, void *, int); -extern int i2o_query_table(int, struct i2o_controller *, int, int, int, - void *, int, void *, int); +extern int i2o_query_table(int, struct i2o_controller *, int, int, int, void *, + int, void *, int); extern int i2o_clear_table(struct i2o_controller *, int, int); -extern int i2o_row_add_table(struct i2o_controller *, int, int, int, - void *, int); -extern int i2o_row_delete_table(struct i2o_controller *, int, int, int, - void *, int); +extern int i2o_row_add_table(struct i2o_controller *, int, int, int, void *, + int); +extern int i2o_row_delete_table(struct i2o_controller *, int, int, int, void *, + int); + +extern int i2o_event_register(struct i2o_controller *, int, int, u32); +extern int i2o_event_ack(struct i2o_controller *, int, int, u32, void *, int); extern void i2o_run_queue(struct i2o_controller *); extern void i2o_report_status(const char *, const char *, u32 *); @@ -615,7 +645,7 @@ extern const char *i2o_get_class_name(int); #define I2O_CMD_UTIL_PARAMS_GET 0x06 #define I2O_CMD_UTIL_PARAMS_SET 0x05 #define I2O_CMD_UTIL_EVT_REGISTER 0x13 -#define I2O_CMD_UTIL_ACK 0x14 +#define I2O_CMD_UTIL_EVT_ACK 0x14 #define I2O_CMD_UTIL_CONFIG_DIALOG 0x10 #define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D #define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F diff --git a/include/linux/mm.h b/include/linux/mm.h index 441a0ae1e023..5683f062d010 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -286,7 +286,6 @@ extern mem_map_t * mem_map; * goes to clearing the page. If you want a page without the clearing * overhead, just use __get_free_page() directly.. */ -extern struct page * __get_pages(int gfp_mask, unsigned long order); #define __get_free_page(gfp_mask) __get_free_pages((gfp_mask),0) #define __get_dma_pages(gfp_mask, order) __get_free_pages((gfp_mask) | GFP_DMA,(order)) extern unsigned long FASTCALL(__get_free_pages(int gfp_mask, unsigned long gfp_order)); @@ -335,7 +334,7 @@ extern int pgt_cache_water[2]; extern int check_pgt_cache(void); extern void paging_init(void); -extern void free_area_init(unsigned long); +extern void free_area_init(unsigned int * zones_size); extern void mem_init(void); extern void show_mem(void); extern void oom(struct task_struct * tsk); diff --git a/include/linux/module.h b/include/linux/module.h index bb3a3de158dc..3046cd391fdf 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -287,6 +287,5 @@ __attribute__((section("__ksymtab"))) = \ #define EXPORT_NO_SYMBOLS #endif /* MODULE */ -extern rwlock_t modlist_lock; extern unsigned long get_kcore_size(void); #endif /* _LINUX_MODULE_H */ diff --git a/include/linux/nbd.h b/include/linux/nbd.h index c2c0431f42da..934e87398643 100644 --- a/include/linux/nbd.h +++ b/include/linux/nbd.h @@ -1,3 +1,9 @@ +/* + * 1999 Copyright (C) Pavel Machek, pavel@ucw.cz. This code is GPL. + * 1999/11/04 Copyright (C) 1999 VMware, Inc. (Regis "HPReg" Duchesne) + * Made nbd_end_request() use the io_request_lock + */ + #ifndef LINUX_NBD_H #define LINUX_NBD_H @@ -27,12 +33,19 @@ extern int requests_out; static void nbd_end_request(struct request *req) { + unsigned long flags; + #ifdef PARANOIA requests_out++; #endif + spin_lock_irqsave(&io_request_lock, flags); if (end_that_request_first( req, !req->errors, "nbd" )) - return; + goto out; end_that_request_last( req ); + +out: + spin_unlock_irqrestore(&io_request_lock, flags); + return; } #define MAX_NBD 128 diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 19a3faf05844..15a0c6d20230 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -27,7 +27,7 @@ #define PAGE_CACHE_MASK PAGE_MASK #define PAGE_CACHE_ALIGN(addr) (((addr)+PAGE_CACHE_SIZE-1)&PAGE_CACHE_MASK) -#define page_cache_alloc() __get_pages(GFP_USER, 0) +#define page_cache_alloc() (mem_map+MAP_NR(__get_free_pages(GFP_USER, 0))) #define page_cache_free(x) __free_page(x) #define page_cache_release(x) __free_page(x) diff --git a/include/linux/swap.h b/include/linux/swap.h index 6782d70cf754..b3ddba42d3e8 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -61,7 +61,9 @@ struct swap_info_struct { }; extern int nr_swap_pages; -extern int nr_free_pages; +FASTCALL(unsigned int nr_free_pages(void)); +FASTCALL(unsigned int nr_free_buffer_pages(void)); +FASTCALL(unsigned int nr_free_highpages(void)); extern int nr_lru_pages; extern struct list_head lru_cache; extern atomic_t nr_async_pages; diff --git a/kernel/kmod.c b/kernel/kmod.c index 8b19e2415db3..36d75438053d 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -23,22 +23,36 @@ char modprobe_path[256] = "/sbin/modprobe"; static inline void -use_init_file_context(void) +use_init_fs_context(void) { - struct fs_struct * fs; - - lock_kernel(); + struct fs_struct *our_fs, *init_fs; /* - * Don't use the user's root, use init's root instead. - * Note that we can use "init_task" (which is not actually - * the same as the user-level "init" process) because we - * started "init" with a CLONE_FS + * Make modprobe's fs context be a copy of init's. + * + * We cannot use the user's fs context, because it + * may have a different root than init. + * Since init was created with CLONE_FS, we can grab + * its fs context from "init_task". + * + * The fs context has to be a copy. If it is shared + * with init, then any chdir() call in modprobe will + * also affect init and the other threads sharing + * init_task's fs context. + * + * We created the exec_modprobe thread without CLONE_FS, + * so we can update the fields in our fs context freely. */ - exit_fs(current); /* current->fs->count--; */ - fs = init_task.fs; - current->fs = fs; - atomic_inc(&fs->count); + lock_kernel(); + + our_fs = current->fs; + dput(our_fs->root); + dput(our_fs->pwd); + + init_fs = init_task.fs; + our_fs->umask = init_fs->umask; + our_fs->root = dget(init_fs->root); + our_fs->pwd = dget(init_fs->pwd); unlock_kernel(); } @@ -49,7 +63,10 @@ static int exec_modprobe(void * module_name) char *argv[] = { modprobe_path, "-s", "-k", (char*)module_name, NULL }; int i; - use_init_file_context(); + current->session = 1; + current->pgrp = 1; + + use_init_fs_context(); /* Prevent parent user process from sending signals to child. Otherwise, if the modprobe program does not exist, it might @@ -104,7 +121,7 @@ int request_module(const char * module_name) return -EPERM; } - pid = kernel_thread(exec_modprobe, (void*) module_name, CLONE_FS); + pid = kernel_thread(exec_modprobe, (void*) module_name, 0); if (pid < 0) { printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid); return pid; @@ -126,8 +143,8 @@ int request_module(const char * module_name) spin_unlock_irq(¤t->sigmask_lock); if (waitpid_result != pid) { - printk (KERN_ERR "kmod: waitpid(%d,NULL,0) failed, returning %d.\n", - pid, waitpid_result); + printk(KERN_ERR "request_module[%s]: waitpid(%d,...) failed, errno %d\n", + module_name, pid, -waitpid_result); } return 0; } diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 62605eecda1b..22a7b1ea9e1a 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -93,7 +93,6 @@ EXPORT_SYMBOL(exit_sighand); /* internal kernel memory management */ EXPORT_SYMBOL(__get_free_pages); -EXPORT_SYMBOL(__get_pages); EXPORT_SYMBOL(free_pages); EXPORT_SYMBOL(__free_page); EXPORT_SYMBOL(kmem_find_general_cachep); diff --git a/kernel/module.c b/kernel/module.c index a79fa619f22f..08f44a42b126 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -13,7 +13,6 @@ * 0.99.14 version by Jon Tombs , * Heavily modified by Bjorn Ekwall May 1994 (C) * Rewritten by Richard Henderson Dec 1996 - * Use rw spinlock instead of global kernel lock for module_list, by TA * * This source is covered by the GNU GPL, the same as all kernel sources. */ @@ -53,8 +52,6 @@ static void put_mod_name(char *buf); static struct module *find_module(const char *name); static void free_module(struct module *, int tag_freed); -rwlock_t modlist_lock = RW_LOCK_UNLOCKED; - /* needed for /proc/kcore, here because kernel_module is static (TA) */ unsigned long get_kcore_size(void) @@ -65,13 +62,13 @@ unsigned long get_kcore_size(void) if (module_list == &kernel_module) return ((unsigned long)high_memory - PAGE_OFFSET + PAGE_SIZE); - read_lock(&modlist_lock); + lock_kernel(); for (m=module_list; m; m=m->next) { try = (unsigned long)m + m->size; if (try > size) size = try; } - read_unlock(&modlist_lock); + unlock_kernel(); return (size - PAGE_OFFSET + PAGE_SIZE); } @@ -133,7 +130,7 @@ sys_create_module(const char *name_user, size_t size) long namelen, error; struct module *mod; - write_lock(&modlist_lock); + lock_kernel(); if (!capable(CAP_SYS_MODULE)) { error = -EPERM; goto err0; @@ -171,7 +168,7 @@ sys_create_module(const char *name_user, size_t size) err1: put_mod_name(name); err0: - write_unlock(&modlist_lock); + unlock_kernel(); return error; } @@ -188,7 +185,7 @@ sys_init_module(const char *name_user, struct module *mod_user) unsigned long mod_user_size; struct module_ref *dep; - write_lock(&modlist_lock); + lock_kernel(); if (!capable(CAP_SYS_MODULE)) goto err0; if ((namelen = get_mod_name(name_user, &name)) < 0) { @@ -367,7 +364,7 @@ err2: err1: put_mod_name(name); err0: - write_unlock(&modlist_lock); + unlock_kernel(); return error; } @@ -379,7 +376,7 @@ sys_delete_module(const char *name_user) long error = -EPERM; int something_changed; - write_lock(&modlist_lock); + lock_kernel(); if (!capable(CAP_SYS_MODULE)) goto out; @@ -432,7 +429,7 @@ restart: mod->flags &= ~MOD_JUST_FREED; error = 0; out: - write_unlock(&modlist_lock); + unlock_kernel(); return error; } @@ -446,21 +443,17 @@ qm_modules(char *buf, size_t bufsize, size_t *ret) nmod = space = 0; - read_lock(&modlist_lock); for (mod=module_list; mod != &kernel_module; mod=mod->next, ++nmod) { len = strlen(mod->name)+1; if (len > bufsize) goto calc_space_needed; - if (copy_to_user(buf, mod->name, len)) { - read_unlock(&modlist_lock); + if (copy_to_user(buf, mod->name, len)) return -EFAULT; - } buf += len; bufsize -= len; space += len; } - read_unlock(&modlist_lock); if (put_user(nmod, ret)) return -EFAULT; else @@ -471,7 +464,6 @@ calc_space_needed: while ((mod = mod->next) != &kernel_module) space += strlen(mod->name)+1; - read_unlock(&modlist_lock); if (put_user(space, ret)) return -EFAULT; else @@ -658,7 +650,7 @@ sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, struct module *mod; int err; - read_lock(&modlist_lock); + lock_kernel(); if (name_user == NULL) mod = &kernel_module; else { @@ -704,7 +696,7 @@ sys_query_module(const char *name_user, int which, char *buf, size_t bufsize, break; } out: - read_unlock(&modlist_lock); + unlock_kernel(); return err; } @@ -723,7 +715,7 @@ sys_get_kernel_syms(struct kernel_sym *table) int i; struct kernel_sym ksym; - read_lock(&modlist_lock); + lock_kernel(); for (mod = module_list, i = 0; mod; mod = mod->next) { /* include the count for the module name! */ i += mod->nsyms + 1; @@ -766,13 +758,12 @@ sys_get_kernel_syms(struct kernel_sym *table) } } out: - read_unlock(&modlist_lock); + unlock_kernel(); return i; } /* * Look for a module by name, ignoring modules marked for deletion. - * Callers must hold modlist_lock at least in read mode. */ static struct module * @@ -792,7 +783,6 @@ find_module(const char *name) /* * Free the given module. - * Callers must hold modlist_lock in exclusive (write) mode. */ static void @@ -849,7 +839,6 @@ int get_module_list(char *p) char tmpstr[64]; struct module_ref *ref; - read_lock(&modlist_lock); for (mod = module_list; mod != &kernel_module; mod = mod->next) { long len; const char *q; @@ -915,7 +904,6 @@ int get_module_list(char *p) } fini: - read_unlock(&modlist_lock); return PAGE_SIZE - left; } @@ -932,7 +920,6 @@ get_ksyms_list(char *buf, char **start, off_t offset, int length) off_t pos = 0; off_t begin = 0; - read_lock(&modlist_lock); for (mod = module_list; mod; mod = mod->next) { unsigned i; struct module_symbol *sym; @@ -967,7 +954,6 @@ leave_the_loop: len -= (offset - begin); if (len > length) len = length; - read_unlock(&modlist_lock); return len; } @@ -984,7 +970,6 @@ get_module_symbol(char *modname, char *symname) struct module_symbol *sym; int i; - read_lock(&modlist_lock); for (mp = module_list; mp; mp = mp->next) { if (((modname == NULL) || (strcmp(mp->name, modname) == 0)) && (mp->flags & (MOD_RUNNING | MOD_DELETED)) == MOD_RUNNING && @@ -993,13 +978,11 @@ get_module_symbol(char *modname, char *symname) i > 0; --i, ++sym) { if (strcmp(sym->name, symname) == 0) { - read_unlock(&modlist_lock); return sym->value; } } } } - read_unlock(&modlist_lock); return 0; } diff --git a/mm/highmem.c b/mm/highmem.c index def9ca7e36e9..863691221dc9 100644 --- a/mm/highmem.c +++ b/mm/highmem.c @@ -14,9 +14,9 @@ #include #include #include +#include unsigned long highmem_mapnr; -unsigned long nr_free_highpages = 0; struct page * prepare_highmem_swapout(struct page * page) { @@ -52,7 +52,7 @@ struct page * replace_with_highmem(struct page * page) struct page *highpage; unsigned long vaddr; - if (PageHighMem(page) || !nr_free_highpages) + if (PageHighMem(page) || !nr_free_highpages()) return page; highpage = get_free_highpage(GFP_ATOMIC|__GFP_HIGHMEM); diff --git a/mm/mmap.c b/mm/mmap.c index 5dbb24ae2608..99e86653d12a 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -64,7 +64,7 @@ int vm_enough_memory(long pages) free = atomic_read(&buffermem_pages); free += atomic_read(&page_cache_size); - free += nr_free_pages; + free += nr_free_pages(); free += nr_swap_pages; return free > pages; } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index e748bc428886..d59a08a7729d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4,6 +4,7 @@ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds * Swap reorganised 29.12.95, Stephen Tweedie * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 + * Reshaped it to be a zoned allocator, Ingo Molnar, Red Hat, 1999 */ #include @@ -22,7 +23,6 @@ #include int nr_swap_pages = 0; -int nr_free_pages = 0; int nr_lru_pages; LIST_HEAD(lru_cache); @@ -36,30 +36,46 @@ LIST_HEAD(lru_cache); #if CONFIG_AP1000 /* the AP+ needs to allocate 8MB contiguous, aligned chunks of ram for the ring buffers */ -#define NR_MEM_LISTS 12 +#define MAX_ORDER 12 #else -#define NR_MEM_LISTS 10 +#define MAX_ORDER 10 #endif -struct free_area_struct { +typedef struct free_area_struct { struct list_head free_list; unsigned int * map; - unsigned long count; -}; +} free_area_t; -#define MEM_TYPE_DMA 0 -#define MEM_TYPE_NORMAL 1 -#define MEM_TYPE_HIGH 2 - -static const char *mem_type_strs[] = {"DMA", "Normal", "High"}; +#define ZONE_DMA 0 +#define ZONE_NORMAL 1 #ifdef CONFIG_HIGHMEM -#define NR_MEM_TYPES 3 +# define ZONE_HIGHMEM 2 +# define NR_ZONES 3 #else -#define NR_MEM_TYPES 2 +# define NR_ZONES 2 #endif -static struct free_area_struct free_area[NR_MEM_TYPES][NR_MEM_LISTS]; +typedef struct zone_struct { + spinlock_t lock; + unsigned long offset; + unsigned long size; + free_area_t free_area[MAX_ORDER]; + + unsigned long free_pages; + unsigned long pages_low, pages_high; + int low_on_memory; + char * name; +} zone_t; + +static zone_t zones[NR_ZONES] = + { + { name: "DMA" }, + { name: "Normal" }, +#ifdef CONFIG_HIGHMEM + { name: "HighMem" } +#endif + }; /* * Free_page() adds the page to the free lists. This is optimized for @@ -88,35 +104,49 @@ spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED; #define memlist_next(x) ((x)->next) #define memlist_prev(x) ((x)->prev) +/* + * Temporary debugging check. + */ +#define BAD_RANGE(zone,x) ((((x)-mem_map) < zone->offset) || (((x)-mem_map) >= zone->offset+zone->size)) + + static inline void free_pages_ok(struct page *page, unsigned long map_nr, unsigned long order) { struct free_area_struct *area; - unsigned long index = map_nr >> (1 + order); - unsigned long mask = (~0UL) << order; + unsigned long index, page_idx, mask, offset; unsigned long flags; struct page *buddy; + zone_t *zone; + int i; - spin_lock_irqsave(&page_alloc_lock, flags); - -#define list(x) (mem_map+(x)) - -#ifdef CONFIG_HIGHMEM - if (map_nr >= highmem_mapnr) { - area = free_area[MEM_TYPE_HIGH]; - nr_free_highpages -= mask; - } else -#endif - if (PageDMA(page)) - area = free_area[MEM_TYPE_DMA]; - else - area = free_area[MEM_TYPE_NORMAL]; + /* + * Which zone is this page belonging to. + * + * (NR_ZONES is low, and we do not want (yet) to introduce + * put page->zone, it increases the size of mem_map[] + * unnecesserily. This small loop is basically equivalent + * to the previous #ifdef jungle, speed-wise.) + */ + i = NR_ZONES-1; + zone = zones + i; + for ( ; i >= 0; i--, zone--) + if (map_nr >= zone->offset) + break; + mask = (~0UL) << order; + offset = zone->offset; + area = zone->free_area; area += order; + page_idx = map_nr - zone->offset; + page_idx &= mask; + index = page_idx >> (1 + order); + mask = (~0UL) << order; - map_nr &= mask; - nr_free_pages -= mask; + spin_lock_irqsave(&zone->lock, flags); - while (mask + (1 << (NR_MEM_LISTS-1))) { + zone->free_pages -= mask; + + while (mask + (1 << (MAX_ORDER-1))) { if (!test_and_change_bit(index, area->map)) /* * the buddy page is still allocated. @@ -125,21 +155,22 @@ static inline void free_pages_ok(struct page *page, unsigned long map_nr, unsign /* * Move the buddy up one level. */ - buddy = list(map_nr ^ -mask); - page = list(map_nr); + buddy = mem_map + offset + (page_idx ^ -mask); + page = mem_map + offset + page_idx; + if (BAD_RANGE(zone,buddy)) + BUG(); + if (BAD_RANGE(zone,page)) + BUG(); - area->count--; memlist_del(&buddy->list); mask <<= 1; area++; index >>= 1; - map_nr &= mask; + page_idx &= mask; } - area->count++; - memlist_add_head(&(list(map_nr))->list, &area->free_list); -#undef list + memlist_add_head(&mem_map[offset + page_idx].list, &area->free_list); - spin_unlock_irqrestore(&page_alloc_lock, flags); + spin_unlock_irqrestore(&zone->lock, flags); } /* @@ -147,7 +178,6 @@ static inline void free_pages_ok(struct page *page, unsigned long map_nr, unsign */ #define MARK_USED(index, order, area) \ change_bit((index) >> (1+(order)), (area)->map) -#define CAN_DMA(x) (PageDMA(x)) #define ADDRESS(x) (PAGE_OFFSET + ((x) << PAGE_SHIFT)) int __free_page(struct page *page) @@ -182,16 +212,17 @@ int free_pages(unsigned long addr, unsigned long order) return 0; } -static inline unsigned long EXPAND (struct page *map, unsigned long index, +static inline unsigned long EXPAND (zone_t *zone, struct page *map, unsigned long index, int low, int high, struct free_area_struct * area) { unsigned long size = 1 << high; while (high > low) { + if (BAD_RANGE(zone,map)) + BUG(); area--; high--; size >>= 1; - area->count++; memlist_add_head(&(map)->list, &(area)->free_list); MARK_USED(index, high, area); index += size; @@ -201,79 +232,62 @@ static inline unsigned long EXPAND (struct page *map, unsigned long index, return index; } -static inline struct page * rmqueue (int order, unsigned type) +static inline struct page * rmqueue (zone_t *zone, int order) { - struct free_area_struct * area = free_area[type]+order; + struct free_area_struct * area = zone->free_area + order; unsigned long curr_order = order, map_nr; - struct page *page; struct list_head *head, *curr; + unsigned long flags; + struct page *page; + spin_lock_irqsave(&zone->lock, flags); do { head = &area->free_list; curr = memlist_next(head); if (curr != head) { + unsigned int index; + page = memlist_entry(curr, struct page, list); memlist_del(curr); - area->count--; - map_nr = page - mem_map; - MARK_USED(map_nr, curr_order, area); - nr_free_pages -= 1 << order; - map_nr = EXPAND(page, map_nr, order, curr_order, area); + map_nr = page - mem_map; + index = map_nr - zone->offset; + MARK_USED(index, curr_order, area); + zone->free_pages -= 1 << order; + map_nr = zone->offset + EXPAND(zone, page, index, order, curr_order, area); + spin_unlock_irqrestore(&zone->lock, flags); + page = mem_map + map_nr; + if (BAD_RANGE(zone,page)) + BUG(); return page; } curr_order++; area++; - } while (curr_order < NR_MEM_LISTS); + } while (curr_order < MAX_ORDER); + spin_unlock_irqrestore(&zone->lock, flags); return NULL; } -static inline int balance_lowmemory (int gfp_mask) +static inline int balance_memory (zone_t *zone, int gfp_mask) { int freed; - static int low_on_memory = 0; -#ifndef CONFIG_HIGHMEM - if (nr_free_pages > freepages.min) { - if (!low_on_memory) + if (zone->free_pages > zone->pages_low) { + if (!zone->low_on_memory) return 1; - if (nr_free_pages >= freepages.high) { - low_on_memory = 0; + /* + * Simple hysteresis: exit 'low memory mode' if + * the upper limit has been reached: + */ + if (zone->free_pages >= zone->pages_high) { + zone->low_on_memory = 0; return 1; } } + zone->low_on_memory = 1; - low_on_memory = 1; -#else - static int low_on_highmemory = 0; - - if (gfp_mask & __GFP_HIGHMEM) - { - if (nr_free_pages > freepages.min) { - if (!low_on_highmemory) { - return 1; - } - if (nr_free_pages >= freepages.high) { - low_on_highmemory = 0; - return 1; - } - } - low_on_highmemory = 1; - } else { - if (nr_free_pages-nr_free_highpages > freepages.min) { - if (!low_on_memory) { - return 1; - } - if (nr_free_pages-nr_free_highpages >= freepages.high) { - low_on_memory = 0; - return 1; - } - } - low_on_memory = 1; - } -#endif current->flags |= PF_MEMALLOC; freed = try_to_free_pages(gfp_mask); current->flags &= ~PF_MEMALLOC; @@ -283,13 +297,12 @@ static inline int balance_lowmemory (int gfp_mask) return 1; } -struct page * __get_pages(int gfp_mask, unsigned long order) +struct page * __get_pages(zone_t *zone, unsigned int gfp_mask, + unsigned long order) { - unsigned long flags; struct page *page; - unsigned type; - if (order >= NR_MEM_LISTS) + if (order >= MAX_ORDER) goto nopage; /* @@ -303,32 +316,20 @@ struct page * __get_pages(int gfp_mask, unsigned long order) * further thought. */ if (!(current->flags & PF_MEMALLOC)) - goto lowmemory; - -ok_to_allocate: -#ifdef CONFIG_HIGHMEM - if (gfp_mask & __GFP_HIGHMEM) - type = MEM_TYPE_HIGH; - else -#endif - if (gfp_mask & __GFP_DMA) - type = MEM_TYPE_DMA; - else - type = MEM_TYPE_NORMAL; - - spin_lock_irqsave(&page_alloc_lock, flags); + if (!balance_memory(zone, gfp_mask)) + goto nopage; + /* + * We are falling back to lower-level zones if allocation + * in a higher zone fails. This assumes a hierarchical + * dependency between zones, which is true currently. If + * you need something else then move this loop outside + * this function, into the zone-specific allocator. + */ do { - page = rmqueue(order, type); - if (page) { -#ifdef CONFIG_HIGHMEM - if (type == MEM_TYPE_HIGH) - nr_free_highpages -= 1 << order; -#endif - spin_unlock_irqrestore(&page_alloc_lock, flags); + page = rmqueue(zone, order); + if (page) return page; - } - } while (type-- > 0) ; - spin_unlock_irqrestore(&page_alloc_lock, flags); + } while (zone-- != zones) ; /* * If we can schedule, do so, and make sure to yield. @@ -342,17 +343,21 @@ ok_to_allocate: nopage: return NULL; - -lowmemory: - if (balance_lowmemory(gfp_mask)) - goto ok_to_allocate; - goto nopage; } unsigned long __get_free_pages(int gfp_mask, unsigned long order) { struct page *page; - page = __get_pages(gfp_mask, order); + zone_t *zone; + + if (gfp_mask & __GFP_DMA) + zone = zones + ZONE_DMA; + else + zone = zones + ZONE_NORMAL; + page = __get_pages(zone, gfp_mask, order); + if (gfp_mask & __GFP_DMA) + if (!PageDMA(page)) + BUG(); if (!page) return 0; return page_address(page); @@ -360,9 +365,44 @@ unsigned long __get_free_pages(int gfp_mask, unsigned long order) struct page * get_free_highpage(int gfp_mask) { - return __get_pages(gfp_mask, 0); + return __get_pages(zones + NR_ZONES-1, gfp_mask, 0); } +/* + * Total amount of free (allocatable) RAM: + */ +unsigned int nr_free_pages (void) +{ + unsigned int sum; + zone_t *zone; + + sum = 0; + for (zone = zones; zone < zones+NR_ZONES; zone++) + sum += zone->free_pages; + return sum; +} + +/* + * Amount of free RAM allocatable as buffer memory: + */ +unsigned int nr_free_buffer_pages (void) +{ + unsigned int sum; + zone_t *zone; + + sum = nr_lru_pages; + for (zone = zones; zone <= zones+ZONE_NORMAL; zone++) + sum += zone->free_pages; + return sum; +} + +#if CONFIG_HIGHMEM +unsigned int nr_free_highpages (void) +{ + return zones[ZONE_HIGHMEM].free_pages; +} +#endif + /* * Show free area list (used inside shift_scroll-lock stuff) * We also calculate the percentage fragmentation. We do this by counting the @@ -374,22 +414,31 @@ void show_free_areas(void) unsigned type; spin_lock_irqsave(&page_alloc_lock, flags); - printk("Free pages: %6dkB (%6ldkB HighMem)\n", - nr_free_pages<<(PAGE_SHIFT-10), - nr_free_highpages<<(PAGE_SHIFT-10)); + printk("Free pages: %6dkB (%6dkB HighMem)\n", + nr_free_pages()<<(PAGE_SHIFT-10), + nr_free_highpages()<<(PAGE_SHIFT-10)); printk("( Free: %d, lru_cache: %d (%d %d %d) )\n", - nr_free_pages, + nr_free_pages(), nr_lru_pages, freepages.min, freepages.low, freepages.high); - for (type = 0; type < NR_MEM_TYPES; type++) { + for (type = 0; type < NR_ZONES; type++) { + zone_t *zone = zones + type; unsigned long total = 0; - printk(" %s: ", mem_type_strs[type]); - for (order = 0; order < NR_MEM_LISTS; order++) { - unsigned long nr = free_area[type][order].count; + printk(" %s: ", zone->name); + for (order = 0; order < MAX_ORDER; order++) { + unsigned long i, nr; + + nr = 0; + for (i = 0; i < zone->size; i += 1<offset + i; + if (!page_count(page)) + nr++; + } total += nr * ((PAGE_SIZE>>10) << order); printk("%lu*%lukB ", nr, (unsigned long)((PAGE_SIZE>>10) << order)); } @@ -405,18 +454,24 @@ void show_free_areas(void) #define LONG_ALIGN(x) (((x)+(sizeof(long))-1)&~((sizeof(long))-1)) /* - * set up the free-area data structures: + * Set up the zone data structures: * - mark all pages reserved * - mark all memory queues empty * - clear the memory bitmaps */ -volatile int data; -void __init free_area_init(unsigned long end_mem_pages) +void __init free_area_init(unsigned int *zones_size) { mem_map_t * p; unsigned long i, j; unsigned long map_size; + unsigned int totalpages, offset; + + totalpages = 0; + for (i = 0; i < NR_ZONES; i++) + totalpages += zones_size[i]; + printk("totalpages: %08x\n", totalpages); + i = totalpages >> 7; /* * Select nr of pages we try to keep free for important stuff * with a minimum of 10 pages and a maximum of 256 pages, so @@ -424,7 +479,7 @@ void __init free_area_init(unsigned long end_mem_pages) * This is fairly arbitrary, but based on some behaviour * analysis. */ - i = end_mem_pages >> 7; + i = totalpages >> 7; if (i < 10) i = 10; if (i > 256) @@ -434,11 +489,10 @@ void __init free_area_init(unsigned long end_mem_pages) freepages.high = i * 3; /* - * Most architectures just pick 'start_mem'. Some architectures - * (with lots of mem and discontinous memory maps) have to search - * for a good area. + * Some architectures (with lots of mem and discontinous memory + * maps) have to search for a good mem_map area: */ - map_size = end_mem_pages*sizeof(struct page); + map_size = totalpages*sizeof(struct page); mem_map = (struct page *) alloc_bootmem(map_size); memset(mem_map, 0, map_size); @@ -447,27 +501,39 @@ void __init free_area_init(unsigned long end_mem_pages) * up by free_all_bootmem() once the early boot process is * done. */ - for (p = mem_map; p < mem_map + end_mem_pages; p++) { + for (p = mem_map; p < mem_map + totalpages; p++) { set_page_count(p, 0); p->flags = (1 << PG_DMA); SetPageReserved(p); init_waitqueue_head(&p->wait); memlist_init(&p->list); } - - for (j = 0 ; j < NR_MEM_TYPES ; j++) { + + offset = 0; + for (j = 0; j < NR_ZONES; j++) { + zone_t *zone = zones + j; unsigned long mask = -1; - for (i = 0 ; i < NR_MEM_LISTS ; i++) { + unsigned long size; + + size = zones_size[j]; + zone->size = size; + zone->offset = offset; + zone->pages_low = freepages.low; + zone->pages_high = freepages.high; + zone->low_on_memory = 0; + + offset += size; + for (i = 0; i < MAX_ORDER; i++) { unsigned long bitmap_size; unsigned int * map; - memlist_init(&free_area[j][i].free_list); + memlist_init(&zone->free_area[i].free_list); mask += mask; - end_mem_pages = (end_mem_pages + ~mask) & mask; - bitmap_size = end_mem_pages >> i; + size = (size + ~mask) & mask; + bitmap_size = size >> i; bitmap_size = (bitmap_size + 7) >> 3; bitmap_size = LONG_ALIGN(bitmap_size); map = (unsigned int *) alloc_bootmem(bitmap_size); - free_area[j][i].map = map; + zone->free_area[i].map = map; memset((void *) map, 0, bitmap_size); } } diff --git a/mm/vmscan.c b/mm/vmscan.c index 102e97e3a650..14f5dc44482a 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -503,7 +503,7 @@ int kswapd(void *unused) do { /* kswapd is critical to provide GFP_ATOMIC allocations (not GFP_HIGHMEM ones). */ - if (nr_free_pages - nr_free_highpages >= freepages.high) + if (nr_free_buffer_pages() >= freepages.high) break; if (!do_try_to_free_pages(GFP_KSWAPD)) -- 2.39.5