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
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
#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;
#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;
#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;
#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;
}
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),
{
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;
}
#ifndef _FP_EMU_H
#define _FP_EMU_H
-#ifndef __ASSEMBLY__
-
+#include "../kernel/m68k_defs.h"
#include <asm/math-emu.h>
+#ifndef __ASSEMBLY__
+
#define IS_INF(a) ((a)->exp == 0x7fff)
#define IS_ZERO(a) ((a)->mant.m64 == 0)
#else /* __ASSEMBLY__ */
-#include "../kernel/m68k_defs.h"
-#include <asm/math-emu.h>
-
/*
* set, reset or clear a bit in the fp status register
*/
#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;
#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;
#include <asm/bootinfo.h>
#include <asm/setup.h>
-#include <asm/system.h>
#include <asm/pgtable.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
#include <linux/openpic.h>
#include <linux/version.h>
#include <linux/adb.h>
-#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ide.h>
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;
#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
{
#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;
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
#include <linux/ide.h>
#include <linux/vt_kern.h>
#include <linux/console.h>
-#include <linux/ide.h>
#include <linux/pci.h>
#include <linux/adb.h>
#include <linux/cuda.h>
*/
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)
{
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.
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:
#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;
#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;
#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;
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;
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)
break;
}
out:
- read_unlock(&modlist_lock);
+ unlock_kernel();
return err;
}
#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;
#include <linux/errno.h>
#include <linux/file.h>
#include <linux/ioctl.h>
+#include <net/sock.h>
#include <asm/segment.h>
#include <asm/uaccess.h>
do {
+ sock->sk->allocation = GFP_ATOMIC;
iov.iov_base = buf;
iov.iov_len = size;
msg.msg_name = NULL;
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
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
--- /dev/null
+/* 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
# include "xf86.h"
# include "xf86drm.h"
# include "xf86_OSlib.h"
-# include "xf86drm.h"
#else
# include <unistd.h>
# include <signal.h>
--- /dev/null
+/* 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
#include <linux/string.h>
#include <linux/random.h>
#include <linux/init.h>
-#include <linux/module.h>
#include <asm/keyboard.h>
#include <asm/bitops.h>
#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)
#endif
#ifdef CONFIG_VIDEO_DEV
videodev_init();
+#endif
+#ifdef CONFIG_PPDEV
+ pp_init();
#endif
return 0;
}
#include <linux/malloc.h>
#include <linux/tty.h>
#include <linux/errno.h>
-#include <linux/sched.h> /* to get the struct task_struct */
#include <linux/string.h> /* used in new tty drivers */
#include <linux/signal.h> /* used in new tty drivers */
#include <asm/system.h>
{
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;
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)
{
--- /dev/null
+/* 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
--- /dev/null
+/*
+ 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 <linux/types.h>
+#include <linux/wait.h>
+
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+
+#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
--- /dev/null
+/*
+ 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
--- /dev/null
+/*
+ * stradis.c - stradis 4:2:2 mpeg decoder driver
+ *
+ * Stradis 4:2:2 MPEG-2 Decoder Driver
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/pci.h>
+#include <linux/signal.h>
+#include <asm/io.h>
+#include <linux/ioport.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <linux/sched.h>
+#include <asm/segment.h>
+#include <asm/types.h>
+#include <linux/types.h>
+#include <linux/wrapper.h>
+#include <linux/interrupt.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+
+#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
{"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
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
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
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
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 ?
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
IX. Uploading Software
SYNOPSIS
-
+
ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw);
struct i2o_sw_xfer
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
* - 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
#include <asm/uaccess.h>
#include <asm/io.h>
-#include "i2o_proc.h"
-
static int i2o_cfg_token = 0;
static int i2o_cfg_context = -1;
static void *page_buf;
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;
if(!c)
return -ENXIO;
- hrt = (pi2o_hrt)c->hrt;
+ hrt = (i2o_hrt *)c->hrt;
i2o_unlock_controller(c);
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;
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;
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);
}
token = i2o_post_wait(c, msg, 9*4, 10);
- if(token)
+ if(token != I2O_POST_WAIT_OK)
{
i2o_unlock_controller(c);
kfree(res);
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)
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);
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)
{
#include <linux/bitops.h>
#include <linux/wait.h>
+#include <linux/delay.h>
#include <linux/timer.h>
#include <asm/io.h>
u32 *p;
struct i2o_device *d;
char str[22];
- pi2o_lct lct = c->lct;
+ i2o_lct *lct = c->lct;
max = lct->table_size;
/* Wait for a reply */
time=jiffies;
+
+ /* DPT driver claims they need this */
+ mdelay(5);
#ifdef DRIVERDEBUG
printk(KERN_INFO "Reset posted, waiting...\n");
{
/*
* 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
u32 m;
u32 *msg;
u8 *status_block;
+ int i;
#ifdef DRIVERDEBUG
printk(KERN_INFO "Getting status block for iop%d\n", c->unit);
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
}
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;
}
*/
static void __init i2o_sys_init()
{
- struct i2o_controller *iop;
+ struct i2o_controller *iop, *niop;
int ret;
u32 m;
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 ||
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);
{
printk(KERN_CRIT "Failed to initialize iop%d\n", iop->unit);
i2o_delete_controller(iop);
+ continue;
}
}
}
/*
* 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)))
{
"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);
/*
* 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;
}
}
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
}
/*
* 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
{
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
{
printk(KERN_ERR "Could not get LCT from iop%d\n", iop->unit);
i2o_delete_controller(iop);
+ continue;
}
else
i2o_parse_lct(iop);
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;
/*
{
printk(KERN_ERR "i2o/iop%d: IOP outbound initialise failed.\n",
c->unit);
- kfree(workspace);
return -ETIMEDOUT;
}
schedule();
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:
/*
* 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
* 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 <Auvo.Hakkinen@cs.Helsinki.FI>
* Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
* 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
*/
#include <linux/trdevice.h>
#include <linux/init.h>
#include <linux/spinlock.h>
+#include <linux/tqueue.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <linux/i2o.h>
#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);
}
#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
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 */
}
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;
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) {
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);
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)
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;
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;
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;
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)
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;
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;
// 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
/* 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;
/*
* 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;
}
#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)
}
#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;
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;
}
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
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);
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);
}
}
- 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 {
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)
}
#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);
#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 {
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 <iop,tid> */
+
+ 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 <iop,tid> */
- /* 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)
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));
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;
#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;
}
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",
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;
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
}
{
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);
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;
MODULE_PARM(bucketthresh, "i"); // Bucket post threshold
MODULE_PARM(rx_copybreak, "i");
-#endif
+#endif
/* 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
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 */
* (C) Copyright 1999 Red Hat Software
*
* Written by Alan Cox, Building Number Three Ltd
- * Modified by Deepak Saxena <deepak@plexity.net>
+ * Modified by Deepak Saxena <deepak@plexity.net>
*
* 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:
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));
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;
}
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;
}
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;
}
}
- 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;
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)
{
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;
}
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);
#include <asm/uaccess.h>
#include <asm/byteorder.h>
-
-#include "i2o_proc.h"
-
#include "i2o_lan.h"
/*
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 * );
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 *,
{
{"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}
};
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}
};
};
#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 */
*/
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,
{"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}
};
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",
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;
}
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)
{
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;
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
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;
}
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;
}
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],
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;
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");
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;
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
{
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])
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");
/* 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;
}
/* 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;
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);
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);
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);
}
-/* 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
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;
}
}
-
-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);
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)
{
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;
}
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)
{
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;
}
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;
}
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; i<field16[0]; i++, field8+=8)
+ for (i = 0; i < result.row_count; i++)
{
+ memcpy(mc_addr, result.mc_addr[i], 8);
+
len += sprintf(buf+len, "MC MAC address[%d]: "
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
- i,
- field8[0], field8[1], field8[2],
- field8[3], field8[4], field8[5],
- field8[6], field8[7]);
+ i, mc_addr[0], mc_addr[1], mc_addr[2],
+ mc_addr[3], mc_addr[4], mc_addr[5],
+ mc_addr[6], mc_addr[7]);
}
spin_unlock(&i2o_proc_lock);
token = i2o_query_scalar(d->controller, 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;
}
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,
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;
}
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");
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;
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; i<field16[0]; i++, field8+=8)
+ for (i=0; i < result.row_count; i++)
{
+ memcpy(alt_addr,result.alt_addr[i],8);
len += sprintf(buf+len, "Alternate address[%d]: "
"%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n",
- i,
- field8[0], field8[1], field8[2],
- field8[3], field8[4], field8[5],
- field8[6], field8[7]);
+ i, alt_addr[0], alt_addr[1], alt_addr[2],
+ alt_addr[3], alt_addr[4], alt_addr[5],
+ alt_addr[6], alt_addr[7]);
}
spin_unlock(&i2o_proc_lock);
token = i2o_query_scalar(d->controller, 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;
}
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)
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;
}
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)
{
"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;
}
}
/* 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)
{
};
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",
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]));
+++ /dev/null
-#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 */
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
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. */
# 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
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
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
#include <linux/malloc.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
+#include <linux/init.h>
#include <linux/version.h>
#include <linux/delay.h>
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);
}
}
#include <linux/malloc.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
-#include <linux/malloc.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/errno.h>
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;
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 */
#include <linux/version.h>
#include <linux/kernel.h>
-#include <linux/version.h>
#include <linux/sched.h>
#include <linux/string.h>
#include <linux/errno.h>
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
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
#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
#include "sun3_scsi.h"
#endif
-#ifdef CONFIG_MAC_SCSI
-#include "mac_scsi.h"
-#endif
-
#ifdef CONFIG_SCSI_MAC_ESP
#include "mac_esp.h"
#endif
#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
#include <stdarg.h>
-#include <asm/io.h>
#include <asm/irq.h>
-#include <linux/string.h>
#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
#include <linux/delay.h>
-#include <linux/sched.h>
#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
#include <linux/bios32.h>
#endif
#include <linux/pci.h>
-#include <linux/proc_fs.h>
#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,23)
#include <linux/init.h>
#endif
#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
#include <linux/spinlock.h>
#endif
-#include "sd.h"
-#include "scsi.h"
-#include "hosts.h"
-#include "inia100.h"
#include <linux/stat.h>
-#include <linux/malloc.h>
#include <linux/config.h>
-
#else
-#include <linux/kernel.h>
#include <linux/head.h>
#include <linux/types.h>
+#include <asm/system.h>
+#include "../block/blk.h"
+#endif
+
+#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/ioport.h>
-
#include <linux/sched.h>
#include <linux/proc_fs.h>
-#include <asm/system.h>
#include <asm/io.h>
-#include "../block/blk.h"
#include "scsi.h"
#include "sd.h"
#include "hosts.h"
#include <linux/malloc.h>
#include "inia100.h"
-#endif
#ifdef MODULE
Scsi_Host_Template driver_template = INIA100;
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/string.h>
+#include <linux/hdreg.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/smp.h>
+#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/io.h>
#define MAJOR_NR SCSI_DISK0_MAJOR
#include <linux/blk.h>
+#include <linux/blkpg.h>
#include "scsi.h"
#include "hosts.h"
#include "sd.h"
#include <scsi/scsi_ioctl.h>
#include "constants.h"
+#include <scsi/scsicam.h> /* must follow "hosts.h" */
#include <linux/genhd.h>
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);
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)
+++ /dev/null
-/*
- * drivers/scsi/sd_ioctl.c
- *
- * ioctl handling for SCSI disks
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/hdreg.h>
-#include <linux/errno.h>
-
-#include <asm/uaccess.h>
-
-#define MAJOR_NR SCSI_DISK0_MAJOR
-#include <linux/blk.h>
-#include <linux/blkpg.h>
-#include "scsi.h"
-#include <scsi/scsi_ioctl.h>
-#include "hosts.h"
-#include "sd.h"
-#include <scsi/scsicam.h> /* 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:
- */
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)
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)
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)
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)
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)
endif
ifeq ($(CONFIG_USB_HUB),m)
M_OBJS += hub.o
- MIX_OBJS += hub.o
+ MI_OBJS += hub.o
endif
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)
ifeq ($(CONFIG_USB_PRINTER),m)
M_OBJS += printer.o
- MIX_OBJS += printer.o
+ MI_OBJS += printer.o
endif
ifeq ($(CONFIG_USB_SERIAL),y)
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)
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)
ifeq ($(CONFIG_USB_AUDIO),m)
M_OBJS += audio.o
- MIX_OBJS += audio.o
+ MI_OBJS += audio.o
endif
ifeq ($(CONFIG_USB_CPIA),y)
ifeq ($(CONFIG_USB_CPIA),m)
M_OBJS += cpia.o
- MIX_OBJS += cpia.o
+ MI_OBJS += cpia.o
endif
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)
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
ifeq ($(CONFIG_USB_EZUSB),m)
M_OBJS += ezusb.o
- MIX_OBJS += ezusb.o
+ MI_OBJS += ezusb.o
endif
ifeq ($(CONFIG_USB_USS720),y)
ifeq ($(CONFIG_USB_USS720),m)
M_OBJS += uss720.o
- MIX_OBJS += uss720.o
+ MI_OBJS += uss720.o
endif
include $(TOPDIR)/Rules.make
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.
/*
* 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 <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-
#include "usb.h"
+
/*#define SERIAL_DEBUG 1*/
#ifdef SERIAL_DEBUG
#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
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;
-
-/* 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);
}
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");
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)
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)
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);
}
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);
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;
}
}
+ /* 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!!! */
}
+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;
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) {
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;
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;
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);
#include <linux/elf.h>
#include <linux/elfcore.h>
#include <linux/module.h>
-#include <linux/proc_fs.h>
+#include <linux/smp_lock.h>
+
#include <asm/uaccess.h>
#ifdef CONFIG_KCORE_AOUT
#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);
dhdr->p_align = 0;
elf->e_phnum++;
}
- read_unlock(&modlist_lock);
+ lock_kernel();
}
#endif
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);
* 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"
#else
-#include "udfdecl.h"
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#ifdef __KERNEL__
#include <linux/types.h>
-#include <linux/udf_udf.h>
#include <linux/udf_fs.h>
#include <linux/config.h>
#error "The UDF Module Current Requires Kernel Version 2.3.7 or greater"
#endif
+#include <linux/fs.h>
/* 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 <linux/fs.h>
/* explicitly include udf_fs_sb.h and udf_fs_i.h */
#include <linux/udf_fs_sb.h>
#include <linux/udf_fs_i.h>
-#else
-#include <linux/fs.h> /* also gets udf_fs_i.h and udf_fs_sb.h */
#endif
struct dentry;
#else
#include <sys/types.h>
-#include <linux/udf_udf.h>
#endif /* __KERNEL__ */
+#include <linux/udf_udf.h>
#include "udfend.h"
/* structures */
--- /dev/null
+#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
#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 */
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
/* 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 */
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;
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;
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;
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;
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;
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;
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 */
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 */
char name[16];
int unit;
int type;
- int enabled; /* Bus level enable */
+ int enabled;
#define I2O_TYPE_PCI 0x01 /* PCI 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 */
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 *);
#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
* 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));
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);
#define EXPORT_NO_SYMBOLS
#endif /* MODULE */
-extern rwlock_t modlist_lock;
extern unsigned long get_kcore_size(void);
#endif /* _LINUX_MODULE_H */
+/*
+ * 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
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
#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)
};
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;
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();
}
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
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;
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;
}
/* 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);
* 0.99.14 version by Jon Tombs <jon@gtex02.us.es>,
* Heavily modified by Bjorn Ekwall <bj0rn@blox.se> May 1994 (C)
* Rewritten by Richard Henderson <rth@tamu.edu> Dec 1996
- * Use rw spinlock instead of global kernel lock for module_list, by TA <tigran@sco.com>
*
* This source is covered by the GNU GPL, the same as all kernel sources.
*/
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)
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);
}
long namelen, error;
struct module *mod;
- write_lock(&modlist_lock);
+ lock_kernel();
if (!capable(CAP_SYS_MODULE)) {
error = -EPERM;
goto err0;
err1:
put_mod_name(name);
err0:
- write_unlock(&modlist_lock);
+ unlock_kernel();
return error;
}
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) {
err1:
put_mod_name(name);
err0:
- write_unlock(&modlist_lock);
+ unlock_kernel();
return error;
}
long error = -EPERM;
int something_changed;
- write_lock(&modlist_lock);
+ lock_kernel();
if (!capable(CAP_SYS_MODULE))
goto out;
mod->flags &= ~MOD_JUST_FREED;
error = 0;
out:
- write_unlock(&modlist_lock);
+ unlock_kernel();
return error;
}
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
while ((mod = mod->next) != &kernel_module)
space += strlen(mod->name)+1;
- read_unlock(&modlist_lock);
if (put_user(space, ret))
return -EFAULT;
else
struct module *mod;
int err;
- read_lock(&modlist_lock);
+ lock_kernel();
if (name_user == NULL)
mod = &kernel_module;
else {
break;
}
out:
- read_unlock(&modlist_lock);
+ unlock_kernel();
return err;
}
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;
}
}
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 *
/*
* Free the given module.
- * Callers must hold modlist_lock in exclusive (write) mode.
*/
static void
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;
}
fini:
- read_unlock(&modlist_lock);
return PAGE_SIZE - left;
}
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;
len -= (offset - begin);
if (len > length)
len = length;
- read_unlock(&modlist_lock);
return len;
}
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 &&
i > 0; --i, ++sym) {
if (strcmp(sym->name, symname) == 0) {
- read_unlock(&modlist_lock);
return sym->value;
}
}
}
}
- read_unlock(&modlist_lock);
return 0;
}
#include <linux/mm.h>
#include <linux/pagemap.h>
#include <linux/highmem.h>
+#include <linux/swap.h>
unsigned long highmem_mapnr;
-unsigned long nr_free_highpages = 0;
struct page * prepare_highmem_swapout(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);
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;
}
* 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 <linux/config.h>
#include <asm/pgtable.h>
int nr_swap_pages = 0;
-int nr_free_pages = 0;
int nr_lru_pages;
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
#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.
/*
* 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);
}
/*
*/
#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)
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;
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;
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;
/*
* 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.
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);
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
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<<order) {
+ struct page * page;
+ page = mem_map + zone->offset + i;
+ if (!page_count(page))
+ nr++;
+ }
total += nr * ((PAGE_SIZE>>10) << order);
printk("%lu*%lukB ", nr, (unsigned long)((PAGE_SIZE>>10) << order));
}
#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
* 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)
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);
* 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);
}
}
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))