Commit 7d8d8414 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.3.81

parent d0d4e162
......@@ -1129,10 +1129,10 @@ S: Cambridge, Massachusetts 02139
S: USA
N: Simmule Turner
E: simmy@digex.com
E: sturner@tele-tv.com
D: Added swapping to filesystem
S: 8504 16th Street #406
S: Silver Spring, Maryland 20910
S: 4226 Landgreen Street
S: Rockville, Maryland 20853
S: USA
N: Stephen Tweedie
......
......@@ -2815,6 +2815,13 @@ CONFIG_ATIXL_BUSMOUSE
plugging in a COM port (9 or 25 pins) which is supported
automatically.
Support for user miscellaneous modules
CONFIG_UMISC
This option forces generic miscellaneous minor device support in the
kernel, and allows later loading of user miscellaneous device modules,
such as drivers for optic pens and touchscreens. Unless you need such
specific modules, or are willing to write/test one, just say N.
QIC-02 tape support
CONFIG_QIC02_TAPE
If you have a non-SCSI tape drive like that, say Y.
......
......@@ -102,6 +102,12 @@ M: faith@cs.unc.edu
L: linux-scsi@vger.rutgers.edu
S: Odd fixes (e.g., new signatures)
SCSI TAPE DRIVER
P: Kai Mdkisara
M: Kai.Makisara@metla.fi
L: linux-scsi@vger.rutgers.edu
S: Maintained
FTAPE/QIC-117:
P: Kai Harrekilde-Petersen
M: khp@@dolphinics.no
......
VERSION = 1
PATCHLEVEL = 3
SUBLEVEL = 80
SUBLEVEL = 81
ARCH = i386
......
......@@ -43,10 +43,17 @@ then
define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_LCA y
fi
if [ "$CONFIG_ALPHA_AVANTI" = "y" ]
then
bool 'Is it really a true XL' CONFIG_ALPHA_XL
fi
if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
-o "$CONFIG_ALPHA_EB64P" = "y" ]
then
bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
if [ "$CONFIG_ALPHA_XL" = "n" ]
then
bool 'Using SRM as bootloader' CONFIG_ALPHA_SRM
fi
define_bool CONFIG_PCI y
define_bool CONFIG_ALPHA_APECS y
fi
......
......@@ -393,10 +393,34 @@ int pcibios_write_config_dword (unsigned char bus, unsigned char device_fn,
unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end)
{
#ifdef CONFIG_ALPHA_XL
/*
* Set up the PCI->physical memory translation windows.
* For the XL we *must* use both windows, in order to
* maximize the amount of physical memory that can be used
* to DMA from the ISA bus, and still allow PCI bus devices
* access to all of host memory.
*
* see <asm/apecs.h> for window bases and sizes.
*
* this restriction due to the true XL motherboards' 82379AB SIO
* PCI<->ISA bridge chip which passes only 27 bits of address...
*/
*(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_XL_DMA_WIN1_BASE & 0xfff00000U);
*(vuip)APECS_IOC_PM1R = (APECS_XL_DMA_WIN1_SIZE - 1) & 0xfff00000U;
*(vuip)APECS_IOC_TB1R = 0;
*(vuip)APECS_IOC_PB2R = 1U<<19 | (APECS_XL_DMA_WIN2_BASE & 0xfff00000U);
*(vuip)APECS_IOC_PM2R = (APECS_XL_DMA_WIN2_SIZE - 1) & 0xfff00000U;
*(vuip)APECS_IOC_TB2R = 0;
#else /* CONFIG_ALPHA_XL */
/*
* Set up the PCI->physical memory translation windows.
* For now, window 1 is disabled. In the future, we may
* want to use it to do scatter/gather DMA. Window 0
* For now, window 2 is disabled. In the future, we may
* want to use it to do scatter/gather DMA. Window 1
* goes at 1 GB and is 1 GB large.
*/
*(vuip)APECS_IOC_PB2R = 0U; /* disable window 2 */
......@@ -404,6 +428,7 @@ unsigned long apecs_init(unsigned long mem_start, unsigned long mem_end)
*(vuip)APECS_IOC_PB1R = 1U<<19 | (APECS_DMA_WIN_BASE & 0xfff00000U);
*(vuip)APECS_IOC_PM1R = (APECS_DMA_WIN_SIZE - 1) & 0xfff00000U;
*(vuip)APECS_IOC_TB1R = 0;
#endif /* CONFIG_ALPHA_XL */
#ifdef CONFIG_ALPHA_CABRIOLET
/*
......
......@@ -82,7 +82,20 @@ extern struct hwrpb_struct *hwrpb;
#if PCI_MODIFY
static unsigned int io_base = 64*KB; /* <64KB are (E)ISA ports */
#if defined(CONFIG_ALPHA_XL)
/*
an AVANTI *might* be an XL, and an XL has only 27 bits of ISA address
that get passed through the PCI<->ISA bridge chip. Because this causes
us to set the PCI->Mem window bases lower than normal, we've gotta allocate
PCI bus devices' memory addresses *above* the PCI<->memory mapping windows,
so that CPU memory DMA addresses issued by a bus device don't conflict
with bus memory addresses, like frame buffer memory for graphics cards.
*/
static unsigned int mem_base = 1024*MB;
#else /* CONFIG_ALPHA_XL */
static unsigned int mem_base = 16*MB; /* <16MB is ISA memory */
#endif /* CONFIG_ALPHA_XL */
/*
* Disable PCI device DEV so that it does not respond to I/O or memory
......@@ -418,7 +431,7 @@ unsigned long pcibios_init(unsigned long mem_start,
* or 0x398/0x399. Unfortunately, autodetecting which base address is
* in use works only once (right after a reset). The Super I/O chip
* has the additional quirk that configuration register data must be
* written twice (I believe this is a saftey feature to prevent
* written twice (I believe this is a safety feature to prevent
* accidental modification---fun, isn't it?).
*/
static inline void enable_ide(long ide_base)
......
......@@ -21,6 +21,7 @@
#include <asm/segment.h>
#include <asm/pgtable.h>
#include <asm/hwrpb.h>
#include <asm/dma.h>
extern void die_if_kernel(char *,struct pt_regs *,long);
extern void show_net_buffers(void);
......@@ -156,6 +157,8 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
}
for (tmp = PAGE_OFFSET ; tmp < high_memory ; tmp += PAGE_SIZE) {
if (tmp >= MAX_DMA_ADDRESS)
mem_map[MAP_NR(tmp)].dma = 0;
if (mem_map[MAP_NR(tmp)].reserved)
continue;
mem_map[MAP_NR(tmp)].count = 1;
......
......@@ -147,6 +147,7 @@ CONFIG_SERIAL=y
# CONFIG_PSMOUSE is not set
# CONFIG_MS_BUSMOUSE is not set
# CONFIG_ATIXL_BUSMOUSE is not set
# CONFIG_UMISC is not set
# CONFIG_QIC02_TAPE is not set
# CONFIG_FTAPE is not set
# CONFIG_APM is not set
......
......@@ -306,7 +306,7 @@ static void make_request(int major,int rw, struct buffer_head * bh)
return;
}
kstat.pgpgin++;
max_req = NR_REQUEST; /* reads take precedence */
max_req = (major == MD_MAJOR) ? NR_REQUEST/2 : NR_REQUEST; /* reads take precedence */
break;
case WRITEA:
rw_ahead = 1;
......@@ -322,7 +322,7 @@ static void make_request(int major,int rw, struct buffer_head * bh)
* requests are only for reads.
*/
kstat.pgpgout++;
max_req = (NR_REQUEST * 2) / 3;
max_req = (major == MD_MAJOR) ? NR_REQUEST/3 : (NR_REQUEST * 2) / 3;
break;
default:
printk("make_request: bad block dev cmd, must be R/W/RA/WA\n");
......
......@@ -70,7 +70,7 @@ static XD_SIGNATURE xd_sigs[] = {
{ 0x0008,"06/24/88(C) Copyright 1988 Western Digital Corp.",xd_wd_init_controller,xd_wd_init_drive," Western Digital WDXT-GEN2" }, /* Dan Newcombe, newcombe@aa.csc.peachnet.edu */
{ 0x0015,"SEAGATE ST11 BIOS REVISION",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Salvador Abreu, spa@fct.unl.pt */
{ 0x0010,"ST11R BIOS",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11M/R" }, /* Risto Kankkunen, risto.kankkunen@cs.helsinki.fi */
{ 0x0010,"ST11 BIOS V1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
{ 0x0010,"ST11 BIOS v1.7",xd_seagate_init_controller,xd_seagate_init_drive," Seagate ST11R" }, /* Alan Hourihane, alanh@fairlite.demon.co.uk */
{ 0x1000,"(c)Copyright 1987 SMS",xd_omti_init_controller,xd_omti_init_drive,"n OMTI 5520" }, /* Dirk Melchers, dirk@merlin.nbg.sub.org */
};
static u_char *xd_bases[] =
......
......@@ -19,6 +19,7 @@ if [ "$CONFIG_PSMOUSE" != "n" ]; then
fi
tristate 'Microsoft busmouse support' CONFIG_MS_BUSMOUSE
tristate 'ATIXL busmouse support' CONFIG_ATIXL_BUSMOUSE
bool 'Support for user misc device modules' CONFIG_UMISC
bool 'QIC-02 tape support' CONFIG_QIC02_TAPE
if [ "$CONFIG_QIC02_TAPE" = "y" ]; then
......
......@@ -100,10 +100,15 @@ else
endif
endif
ifeq ($(CONFIG_UMISC),y)
# To support third-party modules, misc.c must reside in the kernel
M = y
endif
ifdef CONFIG_SOFT_WATCHDOG
L_OBJS += softdog.o
M = y
# This is not modularized, so if configured then "mouse.c" will be resident
# This is not modularized, so if configured then "misc.c" will be resident
endif
ifeq ($(CONFIG_WDT),y)
......@@ -134,10 +139,10 @@ LX_OBJS += apm_bios.o
endif
ifdef M
LX_OBJS += mouse.o
LX_OBJS += misc.o
else
ifdef MM
MX_OBJS += mouse.o
MX_OBJS += misc.o
endif
endif
......
......@@ -16,7 +16,7 @@
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <asm/io.h>
......@@ -194,7 +194,7 @@ struct file_operations atixl_busmouse_fops = {
fasync_mouse,
};
static struct mouse atixl_mouse = {
static struct miscdevice atixl_mouse = {
ATIXL_BUSMOUSE, "atixl", &atixl_busmouse_fops
};
......@@ -222,7 +222,7 @@ int atixl_busmouse_init(void)
mouse.dx = mouse.dy = 0;
mouse.wait = NULL;
printk("Bus mouse detected and installed.\n");
mouse_register(&atixl_mouse);
misc_register(&atixl_mouse);
return 0;
}
......@@ -235,6 +235,6 @@ int init_module(void)
void cleanup_module(void)
{
mouse_deregister(&atixl_mouse);
misc_deregister(&atixl_mouse);
}
#endif
......@@ -41,7 +41,7 @@
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <linux/delay.h>
#include <linux/ioport.h>
......@@ -240,7 +240,7 @@ struct file_operations bus_mouse_fops = {
fasync_mouse,
};
static struct mouse bus_mouse = {
static struct miscdevice bus_mouse = {
LOGITECH_BUSMOUSE, "busmouse", &bus_mouse_fops
};
......@@ -272,7 +272,7 @@ int bus_mouse_init(void)
mouse.wait = NULL;
printk("Logitech bus mouse detected, using IRQ %d.\n",
mouse_irq);
mouse_register(&bus_mouse);
misc_register(&bus_mouse);
return 0;
}
......@@ -285,7 +285,7 @@ int init_module(void)
void cleanup_module(void)
{
mouse_deregister(&bus_mouse);
misc_deregister(&bus_mouse);
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
}
#endif
......@@ -343,12 +343,30 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
static unsigned int prev_scancode = 0; /* remember E0, E1 */
char up_flag; /* 0 or 0200 */
char raw_mode;
int status;
pt_regs = regs;
send_cmd(0xAD); /* disable keyboard */
kb_wait();
if ((inb_p(0x64) & kbd_read_mask) != 0x01)
goto end_kbd_intr;
status = inb_p(0x64);
if ((status & kbd_read_mask) != 0x01) {
/*
* On some platforms (Alpha XL for one), the init code may leave
* an interrupt hanging, yet with status indicating no data.
* After making sure that there's no data indicated and its not a
* mouse interrupt, we will read the data register to clear it.
* If we don't do this, the data reg stays full and will not
* allow new data or interrupt from the keyboard. Sigh...
*/
if (!(status & 0x21)) { /* neither ODS nor OBF */
scancode = inb(0x60); /* read data anyway */
#if 0
printk("keyboard: status 0x%x mask 0x%x data 0x%x\n",
status, kbd_read_mask, scancode);
#endif
}
goto end_kbd_intr;
}
scancode = inb(0x60);
mark_bh(KEYBOARD_BH);
if (reply_expected) {
......
......@@ -11,7 +11,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/tty.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include <linux/tpqic02.h>
#include <linux/ftape.h>
#include <linux/malloc.h>
......@@ -387,10 +387,10 @@ int chr_dev_init(void)
#ifdef CONFIG_PRINTER
lp_init();
#endif
#if defined (CONFIG_BUSMOUSE) || \
#if defined (CONFIG_BUSMOUSE) || defined(CONFIG_UMISC) || \
defined (CONFIG_PSMOUSE) || defined (CONFIG_MS_BUSMOUSE) || \
defined (CONFIG_ATIXL_BUSMOUSE) || defined(CONFIG_SOFT_WATCHDOG)
mouse_init();
misc_init();
#endif
#ifdef CONFIG_SOUND
soundcard_init();
......
/*
* linux/drivers/char/mouse.c
* linux/drivers/char/misc.c
*
* Generic mouse open routine by Johan Myreen
* Generic misc open routine by Johan Myreen
*
* Based on code from Linus
*
......@@ -11,43 +11,72 @@
* See busmouse.c for particulars.
*
* Made things a lot mode modular - easy to compile in just one or two
* of the mouse drivers, as they are now completely independent. Linus.
* of the misc drivers, as they are now completely independent. Linus.
*
* Support for loadable modules. 8-Sep-95 Philip Blundell <pjb27@cam.ac.uk>
*
* Fixed a failing symbol register to free the device registration
* Alan Cox <alan@lxorguk.ukuu.org.uk> 21-Jan-96
*
* Dynamic minors and /proc/mice by Alessandro Rubini. 26-Mar-96
*
* Renamed to misc and miscdevice to be more accurate. Alan Cox 26-May-96
*/
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/malloc.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/tty.h> /* needed by selection.h */
#include "selection.h" /* export its symbols */
/*
* Head entry for the doubly linked mouse list
* Head entry for the doubly linked miscdevice list
*/
static struct mouse mouse_list = { 0, "head", NULL, &mouse_list, &mouse_list };
static struct miscdevice misc_list = { 0, "head", NULL, &misc_list, &misc_list };
/*
* Assigned numbers, used for dynamic minors
*/
#define DYNAMIC_MINORS 64 /* like dynamic majors */
static unsigned char misc_minors[DYNAMIC_MINORS / 8];
#ifndef MODULE
extern int bus_mouse_init(void);
extern int psaux_init(void);
extern int ms_bus_mouse_init(void);
extern int atixl_busmouse_init(void);
#endif
extern void watchdog_init(void);
static int mouse_open(struct inode * inode, struct file * file)
#ifdef CONFIG_PROC_FS
static int proc_misc_read(char *buf, char **start, off_t offset, int len, int unused)
{
struct miscdevice *p;
len=0;
for (p = misc_list.next; p != &misc_list; p = p->next)
len += sprintf(buf+len, "%3i %s\n",p->minor, p->name ?: "");
return len;
}
#endif /* PROC_FS */
#endif /* !MODULE */
static int misc_open(struct inode * inode, struct file * file)
{
int minor = MINOR(inode->i_rdev);
struct mouse *c = mouse_list.next;
struct miscdevice *c = misc_list.next;
file->f_op = NULL;
while (c != &mouse_list) {
while (c != &misc_list) {
if (c->minor == minor) {
file->f_op = c->fops;
break;
......@@ -60,7 +89,7 @@ static int mouse_open(struct inode * inode, struct file * file)
return file->f_op->open(inode,file);
}
static struct file_operations mouse_fops = {
static struct file_operations misc_fops = {
NULL, /* seek */
NULL, /* read */
NULL, /* write */
......@@ -68,56 +97,82 @@ static struct file_operations mouse_fops = {
NULL, /* select */
NULL, /* ioctl */
NULL, /* mmap */
mouse_open,
misc_open,
NULL /* release */
};
int mouse_register(struct mouse * mouse)
int misc_register(struct miscdevice * misc)
{
if (mouse->next || mouse->prev)
if (misc->next || misc->prev)
return -EBUSY;
if (misc->minor == MISC_DYNAMIC_MINOR) {
int i = DYNAMIC_MINORS;
while (--i >= 0)
if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
break;
if (i<0) return -EBUSY;
misc->minor = i;
}
if (misc->minor < DYNAMIC_MINORS)
misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
MOD_INC_USE_COUNT;
mouse->next = &mouse_list;
mouse->prev = mouse_list.prev;
mouse->prev->next = mouse;
mouse->next->prev = mouse;
misc->next = &misc_list;
misc->prev = misc_list.prev;
misc->prev->next = misc;
misc->next->prev = misc;
return 0;
}
int mouse_deregister(struct mouse * mouse)
int misc_deregister(struct miscdevice * misc)
{
if (!mouse->next || !mouse->prev)
int i = misc->minor;
if (!misc->next || !misc->prev)
return -EINVAL;
MOD_DEC_USE_COUNT;
mouse->prev->next = mouse->next;
mouse->next->prev = mouse->prev;
mouse->next = NULL;
mouse->prev = NULL;
misc->prev->next = misc->next;
misc->next->prev = misc->prev;
misc->next = NULL;
misc->prev = NULL;
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
}
return 0;
}
#ifdef MODULE
#define mouse_init init_module
#define misc_init init_module
void cleanup_module(void)
{
unregister_chrdev(MOUSE_MAJOR, "mouse");
unregister_chrdev(MOUSE_MAJOR, "misc");
}
#endif
static struct symbol_table mouse_syms = {
static struct symbol_table misc_syms = {
/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
#include <linux/symtab_begin.h>
X(mouse_register),
X(mouse_deregister),
X(misc_register),
X(misc_deregister),
#ifndef MODULE
X(set_selection), /* used by the kmisc module, can only */
X(clear_selection), /* be exported if misc.c is in linked in */
#endif
#include <linux/symtab_end.h>
};
int mouse_init(void)
int misc_init(void)
{
#ifndef MODULE
#ifdef CONFIG_PROC_FS
proc_register_dynamic(&proc_root, &(struct proc_dir_entry) {
0, 4, "misc",
S_IRUGO, 1, 0, 0,
0, NULL /* ops -- default to array */,
&proc_misc_read /* get_info */,
});
#endif /* PROC_FS */
#ifdef CONFIG_BUSMOUSE
bus_mouse_init();
#endif
......@@ -134,15 +189,15 @@ int mouse_init(void)
watchdog_init();
#endif
#endif /* !MODULE */
if (register_chrdev(MOUSE_MAJOR,"mouse",&mouse_fops)) {
printk("unable to get major %d for mouse devices\n",
MOUSE_MAJOR);
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
return -EIO;
}
if(register_symtab(&mouse_syms)!=0)
if(register_symtab(&misc_syms)!=0)
{
unregister_chrdev(MOUSE_MAJOR, "mouse");
unregister_chrdev(MISC_MAJOR, "misc");
return -EIO;
}
return 0;
......
......@@ -38,7 +38,7 @@
#include <linux/busmouse.h>
#include <linux/signal.h>
#include <linux/errno.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <asm/io.h>
......@@ -170,7 +170,7 @@ struct file_operations ms_bus_mouse_fops = {
fasync_mouse,
};
static struct mouse ms_bus_mouse = {
static struct miscdevice ms_bus_mouse = {
MICROSOFT_BUSMOUSE, "msbusmouse", &ms_bus_mouse_fops
};
......@@ -205,7 +205,7 @@ int ms_bus_mouse_init(void)
MS_MSE_INT_OFF();
request_region(MS_MSE_CONTROL_PORT, 0x04, "MS Busmouse");
printk("Microsoft BusMouse detected and installed.\n");
mouse_register(&ms_bus_mouse);
misc_register(&ms_bus_mouse);
return 0;
}
......@@ -217,7 +217,7 @@ int init_module(void)
void cleanup_module(void)
{
mouse_deregister(&ms_bus_mouse);
misc_deregister(&ms_bus_mouse);
release_region(MS_MSE_CONTROL_PORT, 0x04);
}
#endif
......
......@@ -39,7 +39,7 @@
#include <linux/errno.h>
#include <linux/timer.h>
#include <linux/malloc.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include <linux/random.h>
#include <asm/io.h>
......@@ -481,7 +481,7 @@ struct file_operations psaux_fops = {
* Initialize driver. First check for a 82C710 chip; if found
* forget about the Aux port and use the *_qp functions.
*/
static struct mouse psaux_mouse = {
static struct miscdevice psaux_mouse = {
PSMOUSE_MINOR, "ps2aux", &psaux_fops
};
......@@ -506,7 +506,7 @@ int psaux_init(void)
} else {
return -EIO;
}
mouse_register(&psaux_mouse);
misc_register(&psaux_mouse);
queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
memset(queue, 0, sizeof(*queue));
queue->head = queue->tail = 0;
......@@ -538,7 +538,7 @@ int init_module(void)
void cleanup_module(void)
{
mouse_deregister(&psaux_mouse);
misc_deregister(&psaux_mouse);
}
#endif
......
......@@ -110,8 +110,8 @@ static inline unsigned short limit(const unsigned short v, const unsigned short
return v;
}
/* set the current selection. Invoked by ioctl(). */
int set_selection(const unsigned long arg, struct tty_struct *tty)
/* set the current selection. Invoked by ioctl() or by kernel code. */
int set_selection(const unsigned long arg, struct tty_struct *tty, int user)
{
int sel_mode, new_sel_start, new_sel_end, spc;
char *bp, *obp;
......@@ -122,12 +122,19 @@ int set_selection(const unsigned long arg, struct tty_struct *tty)
{ unsigned short *args, xs, ys, xe, ye;
args = (unsigned short *)(arg + 1);
xs = get_user(args++) - 1;
ys = get_user(args++) - 1;
xe = get_user(args++) - 1;
ye = get_user(args++) - 1;
sel_mode = get_user(args);
if (user) {
xs = get_user(args++) - 1;
ys = get_user(args++) - 1;
xe = get_user(args++) - 1;
ye = get_user(args++) - 1;
sel_mode = get_user(args);
} else {
xs = *(args++) - 1; /* set selection from kernel */
ys = *(args++) - 1;
xe = *(args++) - 1;
ye = *(args++) - 1;
sel_mode = *args;
}
xs = limit(xs, video_num_columns - 1);
ys = limit(ys, video_num_lines - 1);
xe = limit(xe, video_num_columns - 1);
......
......@@ -6,7 +6,7 @@
extern int sel_cons;
extern void clear_selection(void);
extern int set_selection(const unsigned long arg, struct tty_struct *tty);
extern int set_selection(const unsigned long arg, struct tty_struct *tty, int user);
extern int paste_selection(struct tty_struct *tty);
extern int sel_loadlut(const unsigned long arg);
extern int mouse_reporting(void);
......
......@@ -23,7 +23,7 @@
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#define WATCHDOG_MINOR 130
#define TIMER_MARGIN (60*HZ) /* Allow 1 minute */
......@@ -106,13 +106,13 @@ void watchdog_init(void)
NULL,
NULL /* Fasync */
};
static struct mouse softdog_mouse={
static struct miscdevice softdog_mouse={
WATCHDOG_MINOR,
"softdog",
&softdog_fops
};
mouse_register(&softdog_mouse);
misc_register(&softdog_mouse);
init_timer(&watchdog_ticktock);
watchdog_ticktock.function=watchdog_fire;
printk("Software Watchdog Timer: 0.03\n");
......
......@@ -1543,7 +1543,7 @@ static int tty_ioctl(struct inode * inode, struct file * file,
return do_get_ps_info(arg);
#endif
case 2:
return set_selection(arg, tty);
return set_selection(arg, tty, 1);
case 3:
return paste_selection(tty);
case 4:
......
......@@ -27,7 +27,7 @@
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/mouse.h>
#include <linux/miscdevice.h>
#include "wd501p.h"
#include <linux/malloc.h>
#include <linux/ioport.h>
......@@ -213,7 +213,7 @@ static struct file_operations wdt_fops = {
wdt_release
};
static struct mouse wdt_mouse=
static struct miscdevice wdt_mouse=
{
WATCHDOG_MINOR,
"wdt",
......@@ -221,7 +221,7 @@ static struct mouse wdt_mouse=
};
#ifdef CONFIG_WDT_501
static struct mouse temp_mouse=
static struct miscdevice temp_mouse=
{
TEMP_MINOR,
"temperature",
......@@ -251,7 +251,7 @@ void cleanup_module(void)
{
mouse_deregister(&wdt_mouse);
#ifdef CONFIG_WDT_501
mouse_deregister(&temp_mouse);
misc_deregister(&temp_mouse);
#endif
release_region(io,8);
free_irq(irq, NULL);
......@@ -269,7 +269,7 @@ int wdt_init(void)
}
mouse_register(&wdt_mouse);
#ifdef CONFIG_WDT_501
mouse_register(&temp_mouse);
misc_register(&temp_mouse);
#endif
request_region(io, 8, "wdt501");
return 0;
......
......@@ -166,10 +166,14 @@ endif
ifeq ($(CONFIG_SLIP),y)
L_OBJS += slip.o
CONFIG_SLHC_BUILTIN = y
ifeq ($(CONFIG_SLIP_COMPRESSED),y)
CONFIG_SLHC_BUILTIN = y
endif
else
ifeq ($(CONFIG_SLIP),m)
CONFIG_SLHC_MODULE = y
ifeq ($(CONFIG_SLIP_COMPRESSED),y)
CONFIG_SLHC_MODULE = y
endif
M_OBJS += slip.o
endif
endif
......
......@@ -1158,6 +1158,7 @@ static void tr_tx(struct device *dev)
__u32 dhb;
unsigned char xmit_command;
int i;
struct trllc *llc;
if (readb(ti->asb + offsetof(struct asb_xmit_resp, ret_code))!=0xFF)
DPRINTK("ASB not free !!!\n");
......@@ -1169,13 +1170,14 @@ static void tr_tx(struct device *dev)
effective address where we will place data.*/
dhb=ti->sram
+ntohs(readw(ti->arb + offsetof(struct arb_xmit_req, dhb_address)));
llc = (struct trllc *) &(ti->current_skb->data[sizeof(struct trh_hdr)]);
xmit_command = readb(ti->srb + offsetof(struct srb_xmit, command));
writeb(xmit_command, ti->asb + offsetof(struct asb_xmit_resp, command));
writew(readb(ti->srb + offsetof(struct srb_xmit, station_id)),
ti->asb + offsetof(struct asb_xmit_resp, station_id));
writeb(EXTENDED_SAP, ti->asb + offsetof(struct asb_xmit_resp, rsap_value));
writeb(llc->ssap, ti->asb + offsetof(struct asb_xmit_resp, rsap_value));
writeb(readb(ti->srb + offsetof(struct srb_xmit, cmd_corr)),
ti->asb + offsetof(struct asb_xmit_resp, cmd_corr));
writeb(0, ti->asb + offsetof(struct asb_xmit_resp, ret_code));
......@@ -1248,6 +1250,8 @@ static void tr_rx(struct device *dev)
unsigned int rbuffer_len, lan_hdr_len;
unsigned int arb_frame_len;
struct sk_buff *skb;
unsigned int skb_size = 0;
int is8022 = 0;
rbuffer=(ti->sram
+ntohs(readw(ti->arb + offsetof(struct arb_rec_req, rec_buf_addr))));
......@@ -1293,6 +1297,11 @@ static void tr_rx(struct device *dev)
return;
}
if ((readb(llc + offsetof(struct trllc, dsap))!=0xAA) ||
(readb(llc + offsetof(struct trllc, ssap))!=0xAA)) {
is8022 = 1;
}
#if TR_VERBOSE
if ((readb(llc + offsetof(struct trllc, dsap))!=0xAA) ||
(readb(llc + offsetof(struct trllc, ssap))!=0xAA)) {
......@@ -1322,8 +1331,12 @@ static void tr_rx(struct device *dev)
#endif
arb_frame_len=ntohs(readw(ti->arb+offsetof(struct arb_rec_req, frame_len)));
skb_size = arb_frame_len-lan_hdr_len+sizeof(struct trh_hdr);
if (is8022) {
skb_size += sizeof(struct trllc);
}
if (!(skb=dev_alloc_skb(arb_frame_len-lan_hdr_len+sizeof(struct trh_hdr)))) {
if (!(skb=dev_alloc_skb(skb_size))) {
DPRINTK("out of memory. frame dropped.\n");
ti->tr_stats.rx_dropped++;
writeb(DATA_LOST, ti->asb + offsetof(struct asb_rec, ret_code));
......@@ -1331,7 +1344,7 @@ static void tr_rx(struct device *dev)
return;
}
skb_put(skb, arb_frame_len-lan_hdr_len+sizeof(struct trh_hdr));
skb_put(skb, skb_size);
skb->dev=dev;
data=skb->data;
......@@ -1344,6 +1357,12 @@ static void tr_rx(struct device *dev)
data+=sizeof(struct trh_hdr);
rbuffer_len=ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)))
-lan_hdr_len;
if (is8022) {
struct trllc *local_llc = (struct trllc *)data;
memset(local_llc, 0, sizeof(*local_llc));
local_llc->ethertype = htons(ETH_P_TR_802_2);
data += sizeof(struct trllc);
}
#if TR_VERBOSE
DPRINTK("rbuffer_len: %d, data: %p\n", rbuffer_len, data);
......
......@@ -344,24 +344,24 @@ static void sdla_errors(struct device *dev, int cmd, int dlci, int ret, int len,
case SDLA_RET_MODEM:
state = data;
if (*state & SDLA_MODEM_DCD_LOW)
printk(KERN_NOTICE "%s: Modem DCD unexpectedly low!\n", dev->name);
printk(KERN_INFO "%s: Modem DCD unexpectedly low!\n", dev->name);
if (*state & SDLA_MODEM_CTS_LOW)
printk(KERN_NOTICE "%s: Modem CTS unexpectedly low!\n", dev->name);
printk(KERN_INFO "%s: Modem CTS unexpectedly low!\n", dev->name);
/* I should probably do something about this! */
break;
case SDLA_RET_CHANNEL_OFF:
printk(KERN_NOTICE "%s: Channel became inoperative!\n", dev->name);
printk(KERN_INFO "%s: Channel became inoperative!\n", dev->name);
/* same here */
break;
case SDLA_RET_CHANNEL_ON:
printk(KERN_NOTICE "%s: Channel became operative!\n", dev->name);
printk(KERN_INFO "%s: Channel became operative!\n", dev->name);
/* same here */
break;
case SDLA_RET_DLCI_STATUS:
printk(KERN_NOTICE "%s: Status change reported by Access Node.\n", dev->name);
printk(KERN_INFO "%s: Status change reported by Access Node.\n", dev->name);
len /= sizeof(struct _dlci_stat);
for(pstatus = data, i=0;i < len;i++,pstatus++)
{
......@@ -376,14 +376,14 @@ static void sdla_errors(struct device *dev, int cmd, int dlci, int ret, int len,
else
state = "unknown status";
printk(KERN_NOTICE "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
printk(KERN_INFO "%s: DLCI %i: %s.\n", dev->name, pstatus->dlci, state);
/* same here */
}
break;
case SDLA_RET_DLCI_UNKNOWN:
printk(KERN_DEBUG "%s: Received unknown DLCIs:", dev->name);
len /= 2;
printk(KERN_INFO "%s: Received unknown DLCIs:", dev->name);
len /= sizeof(short);
for(pdlci = data,i=0;i < len;i++,pdlci++)
printk(" %i", *pdlci);
printk("\n");
......@@ -1058,6 +1058,7 @@ static int sdla_config(struct device *dev, struct frad_conf *conf, int get)
struct frad_local *flp;
struct conf_data data;
int i, err;
short size;
if (dev->type == 0xFFFF)
return(-EUNATCH);
......@@ -1127,11 +1128,22 @@ static int sdla_config(struct device *dev, struct frad_conf *conf, int get)
if (err)
return(err);
sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, &data, sizeof(data), NULL, NULL);
memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
/* no sense reading if the CPU isnt' started */
if (dev->start)
{
size = sizeof(data);
if (sdla_cmd(dev, SDLA_READ_DLCI_CONFIGURATION, 0, 0, NULL, 0, &data, &size) != SDLA_RET_OK)
return(-EIO);
}
else
if (flp->configured)
memcpy(&data.config, &flp->config, sizeof(struct frad_conf));
else
memset(&data.config, 0, sizeof(struct frad_conf));
memcpy(&flp->config, &data.config, sizeof(struct frad_conf));
data.config.flags &= ~SDLA_DIRECT_RECV;
data.config.mtu -= sizeof(struct fradhdr);
data.config.mtu -= data.config.mtu > sizeof(struct fradhdr) ? sizeof(struct fradhdr) : data.config.mtu;
memcpy_tofs(conf, &data.config, sizeof(struct frad_conf));
}
......
......@@ -553,7 +553,7 @@ static int sprint_command (char* buffer, int len, unsigned char *command) {
static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
int start = len;
PRINTP("destination target %d, lun %d\n" ANDP
PRINTP("host number %d destination target %d, lun %d\n" ANDP
cmd->host->host_no ANDP
cmd->target ANDP
cmd->lun);
......@@ -562,7 +562,7 @@ static int sprint_Scsi_Cmnd (char* buffer, int len, Scsi_Cmnd *cmd) {
return len-start;
}
const char *const scsi_device_types[] =
const char *const private_scsi_device_types[] =
{
"Direct-Access ",
"Sequential-Access",
......@@ -575,7 +575,7 @@ const char *const scsi_device_types[] =
"Medium Changer ",
"Communications "
};
#define MAX_SCSI_DEVICE_CODE sizeof(scsi_device_types)/sizeof(char*)
#define MAX_SCSI_DEVICE_CODE sizeof(private_scsi_device_types)/sizeof(char*)
int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int length, int hostno, int inout)
{
......@@ -630,7 +630,7 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
long tr = hostdata->time_read[dev->id] / HZ;
long tw = hostdata->time_write[dev->id] / HZ;
PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? scsi_device_types[(int)dev->type] : "Unknown");
PRINTP(" T:%d %s " ANDP dev->id ANDP (dev->type < MAX_SCSI_DEVICE_CODE) ? private_scsi_device_types[(int)dev->type] : "Unknown");
for (i=0; i<8; i++)
if (dev->vendor[i] >= 0x20)
*(buffer+(len++)) = dev->vendor[i];
......@@ -644,13 +644,13 @@ int generic_NCR5380_proc_info(char* buffer, char** start, off_t offset, int leng
*(buffer+(len++)) = dev->rev[i];
*(buffer+(len++)) = ' ';
PRINTP("\n%10d kb read in %5d secs" ANDP br/1024 ANDP tr);
PRINTP("\n%10ld kb read in %5ld secs" ANDP br/1024 ANDP tr);
if (tr)
PRINTP(" @ %5d bps" ANDP br / tr);
PRINTP(" @ %5ld bps" ANDP br / tr);
PRINTP("\n%10d kb written in %5d secs" ANDP bw/1024 ANDP tw);
PRINTP("\n%10ld kb written in %5ld secs" ANDP bw/1024 ANDP tw);
if (tw)
PRINTP(" @ %5d bps" ANDP bw / tw);
PRINTP(" @ %5ld bps" ANDP bw / tw);
PRINTP("\n");
}
}
......
......@@ -1638,6 +1638,7 @@ int seagate_st0x_biosparam(Disk * disk, kdev_t dev, int* ip) {
unsigned char buf[256 + sizeof(int) * 2], cmd[6], *data, *page;
int *sizes, result, formatted_sectors, total_sectors;
int cylinders, heads, sectors;
int capacity;
/*
* Only SCSI-I CCS drives and later implement the necessary mode sense
......@@ -1718,12 +1719,22 @@ printk("scsi%d : heads = %d cylinders = %d sectors = %d total = %d formatted = %
*/
if ((cylinders > 1024) || (sectors > 64))
result = -1;
else {
ip[0] = heads;
ip[1] = sectors;
ip[2] = cylinders;
/* The Seagate's seem to have some mapping
* Multiple heads * sectors * cyl to get capacity
* Then start rounding down. */
capacity = heads * sectors * cylinders;
sectors = 17; /* Old MFM Drives use this, so does the Seagate */
heads = 2;
capacity = capacity / sectors;
while (cylinders > 1024)
{
heads *= 2; /* For some reason, they go in multiples */
cylinders = capacity / heads;
};
}
ip[0] = heads;
ip[1] = sectors;
ip[2] = cylinders;
/*
* There should be an alternate mapping for things the seagate doesn't
......
......@@ -1016,8 +1016,10 @@ static void get_sectorsize(int i){
scsi_CDs[i].sector_size = 2048; /* A guess, just in case */
scsi_CDs[i].needs_sector_size = 1;
} else {
scsi_CDs[i].capacity = (buffer[0] << 24) |
(buffer[1] << 16) | (buffer[2] << 8) | buffer[3];
scsi_CDs[i].capacity = 1 + ((buffer[0] << 24) |
(buffer[1] << 16) |
(buffer[2] << 8) |
buffer[3]);
scsi_CDs[i].sector_size = (buffer[4] << 24) |
(buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
switch (scsi_CDs[i].sector_size) {
......@@ -1042,7 +1044,7 @@ static void get_sectorsize(int i){
scsi_CDs[i].needs_sector_size = 1;
}
scsi_CDs[i].needs_sector_size = 0;
sr_sizes[i] = scsi_CDs[i].capacity;
sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
};
scsi_free(buffer, 512);
}
......@@ -1103,7 +1105,7 @@ void sr_finish()
scsi_CDs[i].ten = 1;
scsi_CDs[i].remap = 1;
scsi_CDs[i].auto_eject = 0; /* Default is not to eject upon unmount. */
sr_sizes[i] = scsi_CDs[i].capacity;
sr_sizes[i] = scsi_CDs[i].capacity >> (BLOCK_SIZE_BITS - 9);
}
......
......@@ -11,7 +11,7 @@
Copyright 1992, 1993, 1994, 1995 Kai Makisara
email Kai.Makisara@metla.fi
Last modified: Mon Jan 29 21:18:12 1996 by root@kai.makisara.fi
Last modified: Fri Mar 29 20:55:05 1996 by root@kai.makisara.fi
Some small formal changes - aeb, 950809
*/
......@@ -84,8 +84,8 @@ static int st_max_buffers = ST_MAX_BUFFERS;
Scsi_Tape * scsi_tapes = NULL;
static ST_buffer *new_tape_buffer(int);
static int enlarge_buffer(ST_buffer *, int);
static ST_buffer *new_tape_buffer(int, int);
static int enlarge_buffer(ST_buffer *, int, int);
static void normalize_buffer(ST_buffer *);
static int st_init(void);
......@@ -171,7 +171,8 @@ st_chk_result(Scsi_Cmnd * SCpnt)
scsi_tapes[dev].recover_count);
}
#endif
return 0;
if ((sense[2] & 0xe0) == 0)
return 0;
}
return (-EIO);
}
......@@ -453,7 +454,7 @@ flush_buffer(struct inode * inode, struct file * filp, int seek_next)
scsi_tape_open(struct inode * inode, struct file * filp)
{
unsigned short flags;
int i;
int i, need_dma_buffer;
unsigned char cmd[10];
Scsi_Cmnd * SCpnt;
Scsi_Tape * STp;
......@@ -471,13 +472,15 @@ scsi_tape_open(struct inode * inode, struct file * filp)
STp->rew_at_close = (MINOR(inode->i_rdev) & 0x80) == 0;
/* Allocate buffer for this user */
need_dma_buffer = STp->restr_dma;
for (i=0; i < st_nbr_buffers; i++)
if (!st_buffers[i]->in_use)
if (!st_buffers[i]->in_use &&
(!need_dma_buffer || st_buffers[i]->dma))
break;
if (i >= st_nbr_buffers) {
STp->buffer = new_tape_buffer(FALSE);
STp->buffer = new_tape_buffer(FALSE, need_dma_buffer);
if (STp->buffer == NULL) {
printk(KERN_WARNING "st%d: No free buffers.\n", dev);
printk(KERN_WARNING "st%d: Can't allocate tape buffer.\n", dev);
return (-EBUSY);
}
}
......@@ -608,7 +611,7 @@ scsi_tape_open(struct inode * inode, struct file * filp)
}
if (STp->block_size > (STp->buffer)->buffer_size &&
!enlarge_buffer(STp->buffer, STp->block_size)) {
!enlarge_buffer(STp->buffer, STp->block_size, STp->restr_dma)) {
printk(KERN_NOTICE "st%d: Blocksize %d too large for buffer.\n", dev,
STp->block_size);
(STp->buffer)->in_use = 0;
......@@ -775,7 +778,7 @@ st_write(struct inode * inode, struct file * filp, const char * buf, int count)
if (STp->block_size == 0 &&
count > (STp->buffer)->buffer_size &&
!enlarge_buffer(STp->buffer, count))
!enlarge_buffer(STp->buffer, count, STp->restr_dma))
return (-EOVERFLOW);
if (STp->do_auto_lock && STp->door_locked == ST_UNLOCKED &&
......@@ -1016,7 +1019,7 @@ st_read(struct inode * inode, struct file * filp, char * buf, int count)
if (STp->block_size == 0 &&
count > (STp->buffer)->buffer_size &&
!enlarge_buffer(STp->buffer, count))
!enlarge_buffer(STp->buffer, count, STp->restr_dma))
return (-EOVERFLOW);
if (!(STp->do_read_ahead) && STp->block_size != 0 &&
......@@ -1968,7 +1971,7 @@ st_ioctl(struct inode * inode,struct file * file,
/* Try to allocate a new tape buffer */
static ST_buffer *
new_tape_buffer( int from_initialization )
new_tape_buffer( int from_initialization, int need_dma )
{
int priority, a_size;
ST_buffer *tb;
......@@ -1977,16 +1980,18 @@ new_tape_buffer( int from_initialization )
return NULL; /* Should never happen */
if (from_initialization) {
priority = GFP_ATOMIC | GFP_DMA;
priority = GFP_ATOMIC;
a_size = st_buffer_size;
}
else {
priority = GFP_KERNEL | GFP_DMA;
priority = GFP_KERNEL;
for (a_size = PAGE_SIZE; a_size < st_buffer_size; a_size <<= 1)
; /* Make sure we allocate efficiently */
}
tb = (ST_buffer *)scsi_init_malloc(sizeof(ST_buffer), priority);
if (tb) {
if (need_dma)
priority |= GFP_DMA;
tb->b_data = (unsigned char *)scsi_init_malloc(a_size, priority);
if (!tb->b_data) {
scsi_init_free((char *)tb, sizeof(ST_buffer));
......@@ -1998,13 +2003,14 @@ new_tape_buffer( int from_initialization )
st_nbr_buffers);
return NULL;
}
#if DEBUG
if (debugging)
printk(ST_DEB_MSG "st: Allocated tape buffer %d (%d bytes).\n",
st_nbr_buffers, a_size);
printk(ST_DEB_MSG
"st: Allocated tape buffer %d (%d bytes, dma: %d, a: %p).\n",
st_nbr_buffers, a_size, need_dma, tb->b_data);
#endif
tb->in_use = 0;
tb->dma = need_dma;
tb->buffer_size = a_size;
tb->writing = 0;
tb->orig_b_data = NULL;
......@@ -2015,9 +2021,9 @@ new_tape_buffer( int from_initialization )
/* Try to allocate a temporary enlarged tape buffer */
static int
enlarge_buffer(ST_buffer *STbuffer, int new_size)
enlarge_buffer(ST_buffer *STbuffer, int new_size, int need_dma)
{
int a_size;
int a_size, priority;
unsigned char *tbd;
normalize_buffer(STbuffer);
......@@ -2025,13 +2031,17 @@ enlarge_buffer(ST_buffer *STbuffer, int new_size)
for (a_size = PAGE_SIZE; a_size < new_size; a_size <<= 1)
; /* Make sure that we allocate efficiently */
tbd = (unsigned char *)scsi_init_malloc(a_size, GFP_DMA | GFP_KERNEL);
priority = GFP_KERNEL;
if (need_dma)
priority |= GFP_DMA;
tbd = (unsigned char *)scsi_init_malloc(a_size, priority);
if (!tbd)
return FALSE;
#if DEBUG
if (debugging)
printk(ST_DEB_MSG "st: Buffer enlarged to %d bytes.\n", a_size);
printk(ST_DEB_MSG
"st: Buffer at %p enlarged to %d bytes (dma: %d, a: %p).\n",
STbuffer->b_data, a_size, need_dma, tbd);
#endif
STbuffer->orig_b_data = STbuffer->b_data;
......@@ -2056,8 +2066,8 @@ normalize_buffer(ST_buffer *STbuffer)
#if DEBUG
if (debugging)
printk(ST_DEB_MSG "st: Buffer normalized to %d bytes.\n",
STbuffer->buffer_size);
printk(ST_DEB_MSG "st: Buffer at %p normalized to %d bytes.\n",
STbuffer->b_data, STbuffer->buffer_size);
#endif
}
......@@ -2123,6 +2133,7 @@ static int st_attach(Scsi_Device * SDp){
tpnt->waiting = NULL;
tpnt->in_use = 0;
tpnt->drv_buffer = 1; /* Try buffering if no mode sense */
tpnt->restr_dma = (SDp->host)->unchecked_isa_dma;
tpnt->density = 0;
tpnt->do_buffer_writes = ST_BUFFER_WRITES;
tpnt->do_async_writes = ST_ASYNC_WRITES;
......@@ -2131,9 +2142,10 @@ static int st_attach(Scsi_Device * SDp){
tpnt->two_fm = ST_TWO_FM;
tpnt->fast_mteom = ST_FAST_MTEOM;
tpnt->write_threshold = st_write_threshold;
tpnt->drv_block = 0;
tpnt->drv_block = (-1);
tpnt->moves_after_eof = 1;
tpnt->at_sm = 0;
(tpnt->mt_status)->mt_fileno = (tpnt->mt_status)->mt_blkno = (-1);
st_template.nr_dev++;
return 0;
......@@ -2238,8 +2250,9 @@ static int st_init()
target_nbr = st_max_buffers;
for (i=st_nbr_buffers=0; i < target_nbr; i++) {
if (!new_tape_buffer(TRUE)) {
if (!new_tape_buffer(TRUE, TRUE)) {
if (i == 0) {
#if 0
printk(KERN_ERR "Can't continue without at least one tape buffer.\n");
unregister_chrdev(SCSI_TAPE_MAJOR, "st");
scsi_init_free((char *) st_buffers,
......@@ -2247,6 +2260,10 @@ static int st_init()
scsi_init_free((char *) scsi_tapes,
st_template.dev_max * sizeof(Scsi_Tape));
return 1;
#else
printk(KERN_INFO "No tape buffers allocated at initialization.\n");
break;
#endif
}
printk(KERN_INFO "Number of tape buffers adjusted.\n");
break;
......
......@@ -10,7 +10,8 @@
#endif
typedef struct {
int in_use;
unsigned char in_use;
unsigned char dma; /* DMA-able buffer */
int buffer_size;
int buffer_blocks;
int buffer_bytes;
......@@ -37,6 +38,7 @@ typedef struct {
unsigned char in_use;
unsigned char eof_hit;
unsigned char drv_buffer;
unsigned char restr_dma;
unsigned char do_buffer_writes;
unsigned char do_async_writes;
unsigned char do_read_ahead;
......
Changelog for version 3.5.1
Changelog for version 3.5.2
---------------------------
Since 3.5.1
- TB Maui initialization support
Since 3.5
- Improved handling of playback underrunt situations.
......
Version 3.5.1 release notes
---------------------------
Version 3.5.2 release notes
--------------------------------
Most up to date information about this driver is available from
http://personal.eunet.fi/pp/voxware.
......
......@@ -34,8 +34,6 @@ mail me and ask about these cards. The unsupported cards are:
(Early 3.6-alpha versions?)
- Sound Galaxy Washington/Waverider
(3.6-alpha versions. Can't promise the waverider synth).
- TB Maui
(v3.6)
- Yamaha OPL4 (on cards having _RAM_ for samples)
(Late 96?. Works as OPL3 with current driver versions)
......@@ -180,8 +178,8 @@ Crystal CS4232 based cards such as AcerMagic S23, TB Tropez _Plus_ and
Turtle Beach Maui and Tropez
This driver version supports sample, patch and program loading commands
described in the Maui/Tropez User's manual. There is no initialization
code for Maui so it must be initialized with DOS. The audio side of
described in the Maui/Tropez User's manual.
There is now full initialization support too. The audio side of
the Tropez is based on the MAD16 chip (see above).
Jumpers and software configuration
......@@ -385,9 +383,8 @@ select some options automaticly as well.
cards made by known manufacturers such as Turtle Beach (Tropez),
Reveal (some models) and Diamond (some recent models).
"Support for TB Maui"
- This is just an experimental extension to the MPU401 driver.
Don't enable this option unless you are writing a .MOD
player for Maui.
- This enables TB Maui spesific initialization. Works with TB Maui
and TB Tropez (may not work with Tropez Plus).
"Audio Excel DSP 16 initialization support",
- Don't know much about this card. Look at aedsp16.c for more info.
......
......@@ -1470,6 +1470,39 @@ main (int argc, char *argv[])
}
}
if (selected_options & B (OPT_MAUI))
{
oswf_again:
if (think_positively (
"Do you have access to the OSWF.MOT file", 1,
"TB Maui and Tropez have a microcontroller which needs to be initialized\n"
"prior use. OSWF.MOT is a file distributed with card's DOS/Windows drivers\n"
"which is required during initialization\n"))
{
char path[512];
fprintf (stderr,
"Enter full name of the OSWF.MOT file (pwd is sound): ");
scanf ("%s", path);
fprintf (stderr, "including microcode file %s\n", path);
if (!bin2hex (path, "maui_boot.h", "maui_os"))
{
fprintf (stderr, "Couldn't open file %s\n",
path);
if (think_positively ("Try again with correct path", 1,
"The specified file could not be opened. Enter the correct path to the\n"
"file.\n"))
goto oswf_again;
}
else
{
printf ("#define HAVE_MAUI_BOOT\n");
printf ("/*build bin2hex %s maui_boot.h maui_os */\n", path);
}
}
}
if (!(selected_options & ANY_DEVS))
{
printf ("invalid_configuration__run_make_config_again\n");
......
......@@ -55,6 +55,10 @@ static int *maui_osp;
static int (*orig_load_patch) (int dev, int format, const char *addr,
int offs, int count, int pmgr_flag) = NULL;
#ifdef HAVE_MAUI_BOOT
#include "maui_boot.h"
#endif
static wait_handle *maui_sleeper = NULL;
static volatile struct snd_wait maui_sleep_flag =
{0};
......@@ -139,6 +143,158 @@ mauiintr (int irq, void *dev_id, struct pt_regs *dummy)
irq_ok = 1;
}
static int
download_code (void)
{
int i, lines = 0;
int eol_seen = 0, done = 0;
int skip = 1;
printk ("Code download (%d bytes): ", maui_osLen);
for (i = 0; i < maui_osLen; i++)
{
if (maui_os[i] != '\r')
if (!skip || (maui_os[i] == 'S' && (i == 0 || maui_os[i - 1] == '\n')))
{
skip = 0;
if (maui_os[i] == '\n')
eol_seen = skip = 1;
else if (maui_os[i] == 'S')
{
if (maui_os[i + 1] == '8')
done = 1;
if (!maui_write (0xF1))
goto failure;
if (!maui_write ('S'))
goto failure;
}
else
{
if (!maui_write (maui_os[i]))
goto failure;
}
if (eol_seen)
{
int c = 0;
int n;
eol_seen = 0;
for (n = 0; n < 2; n++)
if (maui_wait (STAT_RX_AVAIL))
{
c = inb (HOST_DATA_PORT);
break;
}
if (c != 0x80)
{
printk ("Doanload not acknowledged\n");
return 0;
}
else if (!(lines++ % 10))
printk (".");
if (done)
{
printk ("\nDownload complete\n");
return 1;
}
}
}
}
failure:
printk ("\nDownload failed!!!\n");
return 0;
}
static int
maui_init (int irq)
{
int i;
unsigned char bits;
switch (irq)
{
case 9:
bits = 0x00;
break;
case 5:
bits = 0x08;
break;
case 12:
bits = 0x10;
break;
case 15:
bits = 0x18;
break;
default:
printk ("Maui: Invalid IRQ %d\n", irq);
return 0;
}
outb (0x00, HOST_CTRL_PORT); /* Reset */
outb (bits, HOST_DATA_PORT); /* Set the IRQ bits */
outb (bits | 0x80, HOST_DATA_PORT); /* Set the IRQ bits again? */
outb (0x80, HOST_CTRL_PORT); /* Leave reset */
outb (0x80, HOST_CTRL_PORT); /* Leave reset */
outb (0xD0, HOST_CTRL_PORT); /* Cause interrupt */
for (i = 0; i < 1000000 && !irq_ok; i++);
if (!irq_ok)
return 0;
outb (0x80, HOST_CTRL_PORT); /* Leave reset */
printk ("Turtle Beach Maui initialization\n");
if (!download_code ())
return 0;
outb (0xE0, HOST_CTRL_PORT); /* Normal operation */
/* Select mpu401 mode */
maui_write (0xf0);
maui_write (1);
if (maui_read () != 0x80)
{
maui_write (0xf0);
maui_write (1);
if (maui_read () != 0x80)
printk ("Maui didn't acknowledge set HW mode command\n");
}
printk ("Maui initialized OK\n");
return 1;
}
static int
maui_short_wait (int mask)
{
int i;
for (i = 0; i < 1000; i++)
{
if (inb (HOST_STAT_PORT) & mask)
{
return 1;
}
}
return 0;
}
int
maui_load_patch (int dev, int format, const char *addr,
......@@ -222,6 +378,22 @@ probe_maui (struct address_info *hw_config)
return 0;
maui_sleep_flag.mode = WK_NONE;
/*
* Initialize the processor if necessary
*/
if (maui_osLen > 0)
{
if (!(inb (HOST_STAT_PORT) & STAT_TX_AVAIL) ||
!maui_write (0x9F) || /* Report firmware version */
!maui_short_wait (STAT_RX_AVAIL) ||
maui_read () == -1 || maui_read () == -1)
if (!maui_init (hw_config->irq))
{
snd_release_irq (hw_config->irq);
return 0;
}
}
if (!maui_write (0xCF)) /* Report hardware version */
{
......
#define SOUND_VERSION_STRING "3.5.1-960324"
#define SOUND_VERSION_STRING "3.5.2-960330"
#define SOUND_INTERNAL_VERSION 0x030500
......@@ -1196,7 +1196,9 @@ attach_ss_ms_sound (long mem_start, struct address_info *hw_config)
void
unload_sscape (struct address_info *hw_config)
{
#if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
unload_mpu401 (hw_config);
#endif
snd_release_irq (hw_config->irq);
sound_free_dma (hw_config->dma);
}
......
......@@ -28,7 +28,7 @@ if [ "$CONFIG_INET" = "y" ]; then
fi
tristate 'SMB filesystem support (to mount WfW shares etc..)' CONFIG_SMB_FS
fi
if [ "$CONFIG_IPX" = "y" ]; then
if [ "$CONFIG_IPX" != "n" ]; then
tristate 'NCP filesystem support (to mount NetWare volumes)' CONFIG_NCP_FS
fi
tristate 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS
......
......@@ -14,6 +14,11 @@
#include <linux/termios.h>
#include <linux/mm.h>
/*
* Define this if you want SunOS compatibility wrt braindead
* select behaviour on FIFO's.
*/
#undef FIFO_SUNOS_BRAINDAMAGE
/* We don't use the head/tail construction any more. Now we use the start/len*/
/* construction providing full use of PIPE_BUF (multiple of PAGE_SIZE) */
......@@ -169,6 +174,7 @@ static int pipe_select(struct inode * inode, struct file * filp, int sel_type, s
return 0;
}
#ifdef FIFO_SUNOS_BRAINDAMAGE
/*
* Arggh. Why does SunOS have to have different select() behaviour
* for pipes and fifos? Hate-Hate-Hate. See difference in SEL_IN..
......@@ -194,6 +200,11 @@ static int fifo_select(struct inode * inode, struct file * filp, int sel_type, s
}
return 0;
}
#else
#define fifo_select pipe_select
#endif /* FIFO_SUNOS_BRAINDAMAGE */
/*
* The 'connect_xxx()' functions are needed for named pipes when
......
......@@ -1074,6 +1074,7 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c
int length;
int end;
unsigned int type, pid;
struct proc_dir_entry *dp;
if (count < 0)
return -EINVAL;
......@@ -1085,8 +1086,13 @@ static int array_read(struct inode * inode, struct file * file,char * buf, int c
pid = type >> 16;
type &= 0x0000ffff;
start = NULL;
length = fill_array((char *) page, pid, type,
&start, file->f_pos, count);
dp = (struct proc_dir_entry *) inode->u.generic_ip;
if (dp->get_info)
length = dp->get_info((char *)page, &start, file->f_pos,
count, 0);
else
length = fill_array((char *) page, pid, type,
&start, file->f_pos, count);
if (length < 0) {
free_page(page);
return length;
......
......@@ -18,10 +18,61 @@
* david.rusling@reo.mts.dec.com Initial Version.
*
*/
#include <linux/config.h>
#ifdef CONFIG_ALPHA_XL
/*
An AVANTI *might* be an XL, and an XL has only 27 bits of ISA address
that get passed through the PCI<->ISA bridge chip. So we've gotta use
both windows to max out the physical memory we can DMA to. Sigh...
If we try a window at 0 for 1GB as a work-around, we run into conflicts
with ISA/PCI bus memory which can't be relocated, like VGA aperture and
BIOS ROMs. So we must put the windows high enough to avoid these areas.
We put window 1 at BUS 64Mb for 64Mb, mapping physical 0 to 64Mb-1,
and window 2 at BUS 512Mb for 512Mb, mapping physical 0 to 512Mb-1.
Yes, this does map 0 to 64Mb-1 twice, but only window 1 will actually
be used for that range (via virt_to_bus()).
Window 1 will be used for all DMA from the ISA bus; yes, that does
limit what memory an ISA floppy or soundcard or Ethernet can touch, but
it's also a known limitation on other platforms as well. We use the
same technique that is used on INTEL platforms with similar limitation:
set MAX_DMA_ADDRESS and clear some pages' DMAable flags during mem_init().
We trust that any ISA bus device drivers will *always* ask for DMAable
memory explicitly via kmalloc()/get_free_pages() flags arguments.
Note that most PCI bus devices' drivers do *not* explicitly ask for
DMAable memory; they count on being able to DMA to any memory they
get from kmalloc()/get_free_pages(). They will also use window 1 for
any physical memory accesses below 64Mb; the rest will be handled by
window 2, maxing out at 512Mb of memory. I trust this is enough... :-)
Finally, the reason we make window 2 start at 512Mb for 512Mb, is so that
we can allocate PCI bus devices' memory starting at 1Gb and up, to ensure
that no conflicts occur and bookkeeping is simplified (ie we don't
try to fill the gap between the two windows, we just go above the top).
Note that the XL is treated differently from the AVANTI, even though
for most other things they are identical. It didn't seem reasonable to
make the AVANTI support pay for the limitations of the XL. It is true,
however, that an XL kernel will run on an AVANTI without problems.
*/
#define APECS_XL_DMA_WIN1_BASE (64*1024*1024)
#define APECS_XL_DMA_WIN1_SIZE (64*1024*1024)
#define APECS_XL_DMA_WIN2_BASE (512*1024*1024)
#define APECS_XL_DMA_WIN2_SIZE (512*1024*1024)
#else /* CONFIG_ALPHA_XL */
/* these are for normal APECS family machines, AVANTI/MUSTANG/EB64/PC64 */
#define APECS_DMA_WIN_BASE (1024*1024*1024)
#define APECS_DMA_WIN_SIZE (1024*1024*1024)
#endif /* CONFIG_ALPHA_XL */
/*
* 21071-DA Control and Status registers.
* These are used for PCI memory access.
......@@ -165,7 +216,15 @@
*/
extern inline unsigned long virt_to_bus(void * address)
{
return virt_to_phys(address) + APECS_DMA_WIN_BASE;
unsigned long paddr = virt_to_phys(address);
#ifdef CONFIG_ALPHA_XL
if (paddr < APECS_XL_DMA_WIN1_SIZE)
return paddr + APECS_XL_DMA_WIN1_BASE;
else
return paddr + APECS_XL_DMA_WIN2_BASE; /* win 2 xlates to 0 also */
#else /* CONFIG_ALPHA_XL */
return paddr + APECS_DMA_WIN_BASE;
#endif /* CONFIG_ALPHA_XL */
}
extern inline void * bus_to_virt(unsigned long address)
......@@ -176,9 +235,18 @@ extern inline void * bus_to_virt(unsigned long address)
* detect null "pointers" (the NCR driver is much simpler if
* NULL pointers are preserved).
*/
#ifdef CONFIG_ALPHA_XL
if (address < APECS_XL_DMA_WIN1_BASE)
return 0;
else if (address < (APECS_XL_DMA_WIN1_BASE + APECS_XL_DMA_WIN1_SIZE))
return phys_to_virt(address - APECS_XL_DMA_WIN1_BASE);
else /* should be more checking here, maybe? */
return phys_to_virt(address - APECS_XL_DMA_WIN2_BASE);
#else /* CONFIG_ALPHA_XL */
if (address < APECS_DMA_WIN_BASE)
return 0;
return phys_to_virt(address - APECS_DMA_WIN_BASE);
#endif /* CONFIG_ALPHA_XL */
}
/*
......
......@@ -18,6 +18,8 @@
#ifndef _ASM_DMA_H
#define _ASM_DMA_H
#include <linux/config.h>
#include <asm/io.h> /* need byte IO */
#define dma_outb outb
......@@ -73,8 +75,16 @@
#define MAX_DMA_CHANNELS 8
/* The maximum address that we can perform a DMA transfer to on this platform */
#ifdef CONFIG_ALPHA_XL
/* The maximum address that we can perform a DMA transfer to on Alpha XL,
due to a hardware SIO (PCI<->ISA bus bridge) chip limitation, is 64MB.
see <asm/apecs.h> for more info */
#define MAX_DMA_ADDRESS (0xfffffc0004000000UL)
#else /* CONFIG_ALPHA_XL */
/* The maximum address that we can perform a DMA transfer to on normal
Alpha platforms */
#define MAX_DMA_ADDRESS (~0UL)
#endif /* CONFIG_ALPHA_XL */
/* 8237 DMA controllers */
#define IO_DMA1_BASE 0x00 /* 8 bit slave DMA, channels 0..3 */
......
......@@ -10,6 +10,8 @@
#ifndef __ASM_ALPHA_FLOPPY_H
#define __ASM_ALPHA_FLOPPY_H
#include <linux/config.h>
#define fd_inb(port) inb_p(port)
#define fd_outb(port,value) outb_p(port,value)
......@@ -47,8 +49,13 @@ static int FDC2 = -1;
#define N_DRIVE 8
/*
* The Alpha has no problems with floppy DMA crossing 64k borders.
* Most Alphas have no problems with floppy DMA crossing 64k borders. Sigh...
*/
#define CROSS_64KB(a,s) (0)
#ifdef CONFIG_ALPHA_XL
#define CROSS_64KB(a,s) \
((unsigned long)(a)/0x10000 != ((unsigned long)(a) + (s) - 1) / 0x10000)
#else /* CONFIG_ALPHA_XL */
#define CROSS_64KB(a,s) (0)
#endif /* CONFIG_ALPHA_XL */
#endif /* __ASM_ALPHA_FLOPPY_H */
......@@ -78,18 +78,17 @@ extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
if (!size)
return 0;
__asm__("
cld
movl $-1,%%eax
xorl %%edx,%%edx
repe; scasl
je 1f
xorl -4(%%edi),%%eax
subl $4,%%edi
bsfl %%eax,%%edx
1: subl %%ebx,%%edi
shll $3,%%edi
addl %%edi,%%edx"
__asm__("cld\n\t"
"movl $-1,%%eax\n\t"
"xorl %%edx,%%edx\n\t"
"repe; scasl\n\t"
"je 1f\n\t"
"xorl -4(%%edi),%%eax\n\t"
"subl $4,%%edi\n\t"
"bsfl %%eax,%%edx\n"
"1:\tsubl %%ebx,%%edi\n\t"
"shll $3,%%edi\n\t"
"addl %%edi,%%edx"
:"=d" (res)
:"c" ((size + 31) >> 5), "D" (addr), "b" (addr)
:"ax", "cx", "di");
......@@ -105,11 +104,10 @@ extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
/*
* Look for zero in first byte
*/
__asm__("
bsfl %1,%0
jne 1f
movl $32, %0
1: "
__asm__("bsfl %1,%0\n\t"
"jne 1f\n\t"
"movl $32, %0\n"
"1:"
: "=r" (set)
: "r" (~(*p >> bit)));
if (set < (32 - bit))
......
......@@ -71,6 +71,7 @@
#define ETH_P_PPP_MP 0x0008 /* Dummy type for PPP MP frames */
#define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudeo type */
#define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/
#define ETH_P_TR_802_2 0x0011 /* 802.2 frames */
/*
* This is an Ethernet frame header.
......
......@@ -174,24 +174,6 @@ struct ip_fwpkt
#ifdef __KERNEL__
#include <linux/config.h>
#ifdef CONFIG_IP_MASQUERADE
struct ip_masq {
struct ip_masq *next; /* next member in list */
struct timer_list timer; /* Expiration timer */
__u16 protocol; /* Which protocol are we talking? */
__u32 src, dst; /* Source and destination IP addresses */
__u16 sport,dport; /* Source and destination ports */
__u16 mport; /* Masquaraded port */
__u32 init_seq; /* Add delta from this seq. on */
short delta; /* Delta in sequence numbers */
short previous_delta; /* Delta in sequence numbers before last resized PORT command */
char sawfin; /* Did we saw an FIN packet? */
};
extern struct ip_masq *ip_msq_hosts;
extern void ip_fw_masquerade(struct sk_buff **, struct device *);
extern int ip_fw_demasquerade(struct sk_buff *);
#endif
#ifdef CONFIG_IP_FIREWALL
extern struct ip_fw *ip_fw_in_chain;
extern struct ip_fw *ip_fw_out_chain;
......@@ -212,21 +194,5 @@ extern int ip_fw_chk(struct iphdr *, struct device *rif,struct ip_fw *, int, int
extern void ip_fw_init(void);
#endif /* KERNEL */
#ifdef CONFIG_IP_MASQUERADE
#undef DEBUG_MASQ
#define MASQUERADE_EXPIRE_TCP 15*60*HZ
#define MASQUERADE_EXPIRE_TCP_FIN 2*60*HZ
#define MASQUERADE_EXPIRE_UDP 5*60*HZ
/*
* Linux ports don't normally get allocated above 32K. I used an extra 4K port-space
*/
#define PORT_MASQ_BEGIN 60000
#define PORT_MASQ_END (PORT_MASQ_BEGIN+4096)
#define FTP_DPORT_TBD (PORT_MASQ_END+1) /* Avoid using hardcoded port 20 for ftp data connection */
#endif
#endif /* _IP_FW_H */
......@@ -40,6 +40,7 @@ typedef struct ipx_interface_definition
#define IPX_FRAME_8022 2
#define IPX_FRAME_ETHERII 3
#define IPX_FRAME_8023 4
#define IPX_FRAME_TR_8022 5
unsigned char ipx_special;
#define IPX_SPECIAL_NONE 0
#define IPX_PRIMARY 1
......
......@@ -27,17 +27,14 @@
#define SCSI_DISK_MAJOR 8
#define SCSI_TAPE_MAJOR 9
#define MD_MAJOR 9
#define MOUSE_MAJOR 10
#define MISC_MAJOR 10
#define SCSI_CDROM_MAJOR 11
#define QIC02_TAPE_MAJOR 12
#define XT_DISK_MAJOR 13
#define SOUND_MAJOR 14
#define CDU31A_CDROM_MAJOR 15
#define SOCKET_MAJOR 16
#define GOLDSTAR_CDROM_MAJOR 16
#define AF_UNIX_MAJOR 17
#define OPTICS_CDROM_MAJOR 17
#define AF_INET_MAJOR 18
#define SANYO_CDROM_MAJOR 18
#define CYCLADES_MAJOR 19
#define CYCLADESAUX_MAJOR 20
......
#ifndef _LINUX_MOUSE_H
#define _LINUX_MOUSE_H
#ifndef _LINUX_MISCDEVICE_H
#define _LINUX_MISCDEVICE_H
#define BUSMOUSE_MINOR 0
#define PSMOUSE_MINOR 1
#define MS_BUSMOUSE_MINOR 2
#define ATIXL_BUSMOUSE_MINOR 3
#define MISC_DYNAMIC_MINOR 255
extern int mouse_init(void);
extern int misc_init(void);
struct mouse {
struct miscdevice
{
int minor;
const char *name;
struct file_operations *fops;
struct mouse * next, * prev;
struct miscdevice * next, * prev;
};
extern int mouse_register(struct mouse * mouse);
extern int mouse_deregister(struct mouse * mouse);
extern int mouse_register(struct miscdevice * misc);
extern int mouse_deregister(struct miscdevice * misc);
#endif
......@@ -100,6 +100,7 @@ enum net_directory_inos {
PROC_NET_AX25_BPQETHER,
PROC_NET_ALIAS_TYPES,
PROC_NET_ALIASES,
PROC_NET_IP_MASQ_APP,
PROC_NET_LAST
};
......
......@@ -96,8 +96,6 @@ struct msghdr
#define SOL_TCP 6
#define SOL_UDP 17
#ifdef __KERNEL__
/* IP options */
#define IP_TOS 1
#define IPTOS_LOWDELAY 0x10
......@@ -113,8 +111,6 @@ struct msghdr
#define IP_ADD_MEMBERSHIP 35
#define IP_DROP_MEMBERSHIP 36
#endif /* __KERNEL__ */
/* These need to appear somewhere around here */
#define IP_DEFAULT_MULTICAST_TTL 1
#define IP_DEFAULT_MULTICAST_LOOP 1
......
/*
* IP masquerading functionality definitions
*/
#ifndef _IP_MASQ_H
#define _IP_MASQ_H
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
/*
* Linux ports don't normally get allocated above 32K.
* I used an extra 4K port-space
*/
#define PORT_MASQ_BEGIN 60000
#define PORT_MASQ_END (PORT_MASQ_BEGIN+4096)
#define MASQUERADE_EXPIRE_TCP 15*60*HZ
#define MASQUERADE_EXPIRE_TCP_FIN 2*60*HZ
#define MASQUERADE_EXPIRE_UDP 5*60*HZ
#define IP_MASQ_F_OUT_SEQ 0x01 /* must do output seq adjust */
#define IP_MASQ_F_IN_SEQ 0x02 /* must do input seq adjust */
#define IP_MASQ_F_NO_DPORT 0x04 /* no dport set yet */
#define IP_MASQ_F_NO_DADDR 0x08 /* no daddr yet */
#define IP_MASQ_F_HASHED 0x10 /* hashed entry */
#define IP_MASQ_F_SAW_FIN 0x20 /* tcp fin pkt seen */
#ifdef __KERNEL__
/*
* Delta seq. info structure
* Each MASQ struct has 2 (output AND input seq. changes).
*/
struct ip_masq_seq {
__u32 init_seq; /* Add delta from this seq */
short delta; /* Delta in sequence numbers */
short previous_delta; /* Delta in sequence numbers before last resized pkt */
};
/*
* MASQ structure allocated for each masqueraded association
*/
struct ip_masq {
struct ip_masq *m_link, *s_link; /* hashed link ptrs */
struct timer_list timer; /* Expiration timer */
__u16 protocol; /* Which protocol are we talking? */
__u16 sport, dport, mport; /* src, dst & masq ports */
__u32 saddr, daddr, maddr; /* src, dst & masq addresses */
struct ip_masq_seq out_seq, in_seq;
struct ip_masq_app *app; /* bound ip_masq_app object */
unsigned flags; /* status flags */
};
/*
* [0]: UDP free_ports
* [1]: TCP free_ports
*/
extern int ip_masq_free_ports[2];
/*
* ip_masq initializer (registers symbols and /proc/net entries)
*/
extern int ip_masq_init(void);
/*
* functions called from ip layer
*/
extern void ip_fw_masquerade(struct sk_buff **, struct device *);
extern int ip_fw_demasquerade(struct sk_buff **, struct device *);
/*
* ip_masq obj creation/deletion functions.
*/
extern struct ip_masq *ip_masq_new(struct device *dev, int proto, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned flags);
extern void ip_masq_set_expire(struct ip_masq *ms, unsigned long tout);
/*
*
* IP_MASQ_APP: IP application masquerading definitions
*
*/
struct ip_masq_app
{
struct ip_masq_app *next;
unsigned type; /* type = proto<<16 | port (host byte order)*/
int n_attach;
int (*masq_init_1) /* ip_masq initializer */
(struct ip_masq_app *, struct ip_masq *);
int (*masq_done_1) /* ip_masq fin. */
(struct ip_masq_app *, struct ip_masq *);
int (*pkt_out) /* output (masquerading) hook */
(struct ip_masq_app *, struct ip_masq *, struct sk_buff **, struct device *);
int (*pkt_in) /* input (demasq) hook */
(struct ip_masq_app *, struct ip_masq *, struct sk_buff **, struct device *);
};
/*
* ip_masq_app initializer
*/
extern int ip_masq_app_init(void);
/*
* ip_masq_app object registration functions (port: host byte order)
*/
extern int register_ip_masq_app(struct ip_masq_app *mapp, unsigned short proto, __u16 port);
extern int unregister_ip_masq_app(struct ip_masq_app *mapp);
/*
* get ip_masq_app obj by proto,port(net_byte_order)
*/
extern struct ip_masq_app * ip_masq_app_get(unsigned short proto, __u16 port);
/*
* ip_masq TO ip_masq_app (un)binding functions.
*/
extern struct ip_masq_app * ip_masq_bind_app(struct ip_masq *ms);
extern int ip_masq_unbind_app(struct ip_masq *ms);
/*
* output and input app. masquerading hooks.
*
*/
extern int ip_masq_app_pkt_out(struct ip_masq *, struct sk_buff **skb_p, struct device *dev);
extern int ip_masq_app_pkt_in(struct ip_masq *, struct sk_buff **skb_p, struct device *dev);
/*
* /proc/net entry
*/
extern int ip_masq_app_getinfo(char *buffer, char **start, off_t offset, int length, int dummy);
/*
* skb_replace function used by "client" modules to replace
* a segment of skb.
*/
extern struct sk_buff * ip_masq_skb_replace(struct sk_buff *skb, int pri, char *o_buf, int o_len, char *n_buf, int n_len);
#endif /* __KERNEL__ */
#endif /* _IP_MASQ_H */
#ifndef _NET_P8022TR_H
#define _NET_P8022TR_H
extern struct datalink_proto *register_8022tr_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *));
extern void unregister_8022tr_client(unsigned char type);
#endif
/* Separate to keep compilation of Space.c simpler */
extern void p8022tr_proto_init(struct net_proto *);
......@@ -861,11 +861,6 @@ static inline void do_process_times(struct task_struct *p,
long psecs;
p->utime += user;
if (p->priority < DEF_PRIORITY)
kstat.cpu_nice += user;
else
kstat.cpu_user += user;
kstat.cpu_system += system;
p->stime += system;
psecs = (p->stime + p->utime) / HZ;
......@@ -917,14 +912,20 @@ static void update_process_times(unsigned long ticks, unsigned long system)
{
#ifndef __SMP__
struct task_struct * p = current;
unsigned long user = ticks - system;
if (p->pid) {
p->counter -= ticks;
if (p->counter < 0) {
p->counter = 0;
need_resched = 1;
}
if (p->priority < DEF_PRIORITY)
kstat.cpu_nice += user;
else
kstat.cpu_user += user;
kstat.cpu_system += system;
}
update_one_process(p, ticks, ticks-system, system);
update_one_process(p, ticks, user, system);
#else
int cpu,j;
cpu = smp_processor_id();
......
......@@ -15,12 +15,12 @@ O_OBJS += tr.o
endif
ifdef CONFIG_IPX
OX_OBJS += p8022.o psnap.o
O_OBJS += p8022.o psnap.o p8022tr.o
endif
ifdef CONFIG_ATALK
ifndef CONFIG_IPX
OX_OBJS += p8022.o psnap.o
O_OBJS += p8022.o psnap.o p8022tr.o
endif
endif
......
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <net/datalink.h>
#include <linux/mm.h>
#include <linux/in.h>
#include <net/p8022tr.h>
#define SNAP_HEADER_LEN 8
static struct datalink_proto *p8022tr_list = NULL;
/*
* We don't handle the loopback SAP stuff, the extended
* 802.2 command set, multicast SAP identifiers and non UI
* frames. We have the absolute minimum needed for IPX,
* IP and Appletalk phase 2.
*/
static struct datalink_proto *
find_8022tr_client(unsigned char type)
{
struct datalink_proto *proto;
for (proto = p8022tr_list;
((proto != NULL) && (*(proto->type) != type));
proto = proto->next)
;
return proto;
}
int
p8022tr_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
{
struct datalink_proto *proto;
proto = find_8022tr_client(*(skb->h.raw));
if (proto != NULL) {
skb->h.raw += 3;
skb_pull(skb,3);
return proto->rcvfunc(skb, dev, pt);
}
skb->sk = NULL;
kfree_skb(skb, FREE_READ);
return 0;
}
static void
p8022tr_datalink_header(struct datalink_proto *dl,
struct sk_buff *skb, unsigned char *dest_node)
{
struct device *dev = skb->dev;
unsigned char *rawp;
unsigned char *olddata;
unsigned char *newdata;
rawp = skb_push(skb,3);
*rawp++ = dl->type[0];
*rawp++ = dl->type[0];
*rawp = 0x03; /* UI */
dev->hard_header(skb, dev, ETH_P_802_3, dest_node, NULL, skb->len);
olddata = skb->data;
newdata = skb_pull(skb, SNAP_HEADER_LEN);
memmove(newdata, olddata, dev->hard_header_len - SNAP_HEADER_LEN);
}
static struct packet_type p8022tr_packet_type =
{
0,
NULL, /* All devices */
p8022tr_rcv,
NULL,
NULL,
};
static struct symbol_table p8022tr_proto_syms = {
#include <linux/symtab_begin.h>
X(register_8022tr_client),
X(unregister_8022tr_client),
#include <linux/symtab_end.h>
};
void p8022tr_proto_init(struct net_proto *pro)
{
p8022tr_packet_type.type=htons(ETH_P_TR_802_2);
dev_add_pack(&p8022tr_packet_type);
register_symtab(&p8022tr_proto_syms);
}
struct datalink_proto *
register_8022tr_client(unsigned char type, int (*rcvfunc)(struct sk_buff *, struct device *, struct packet_type *))
{
struct datalink_proto *proto;
if (find_8022tr_client(type) != NULL)
return NULL;
proto = (struct datalink_proto *) kmalloc(sizeof(*proto), GFP_ATOMIC);
if (proto != NULL) {
proto->type[0] = type;
proto->type_len = 1;
proto->rcvfunc = rcvfunc;
proto->header_length = 3;
proto->datalink_header = p8022tr_datalink_header;
proto->string_name = "802.2TR";
proto->next = p8022tr_list;
p8022tr_list = proto;
}
return proto;
}
void unregister_8022tr_client(unsigned char type)
{
struct datalink_proto *tmp, **clients = &p8022tr_list;
unsigned long flags;
save_flags(flags);
cli();
while ((tmp = *clients) != NULL)
{
if (tmp->type[0] == type) {
*clients = tmp->next;
kfree_s(tmp, sizeof(struct datalink_proto));
break;
} else {
clients = &tmp->next;
}
}
restore_flags(flags);
}
......@@ -151,7 +151,8 @@ static atalk_socket *atalk_search_socket(struct sockaddr_at *to, struct atalk_if
}
if ( to->sat_addr.s_net == s->protinfo.af_at.src_net &&
to->sat_addr.s_node == s->protinfo.af_at.src_node )
(to->sat_addr.s_node == s->protinfo.af_at.src_node
||to->sat_addr.s_node == ATADDR_BCAST ))
{
break;
}
......
......@@ -1349,7 +1349,9 @@ int net_dev_init(void)
* SLHC if present needs attaching so other people see it
* even if not opened.
*/
#if (defined(CONFIG_SLIP_COMPRESSED) || defined(CONFIG_PPP)) && defined(CONFIG_SLHC_BUILTIN)
#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
|| defined(CONFIG_PPP) \
|| (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
slhc_install();
#endif
......
......@@ -37,6 +37,11 @@ else
endif
endif
ifeq ($(CONFIG_IP_MASQUERADE),y)
IPV4_OBJS += ip_masq.o ip_masq_app.o
M_OBJS += ip_masq_ftp.o ip_masq_irc.o
endif
ifeq ($(CONFIG_IP_ALIAS),y)
IPV4_OBJS += ip_alias.o
else
......
......@@ -90,6 +90,9 @@
#include <net/raw.h>
#include <net/icmp.h>
#include <linux/ip_fw.h>
#ifdef CONFIG_IP_MASQUERADE
#include <net/ip_masq.h>
#endif
#ifdef CONFIG_IP_ALIAS
#include <net/ip_alias.h>
#endif
......
......@@ -1115,7 +1115,6 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* check if that someone else is one of our proxies. If it isn't,
* we can toss it.
*/
grat = (sip == tip) && (sha == tha);
arp_fast_lock();
for (proxy_entry=arp_proxy_list;
......@@ -1137,12 +1136,6 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
}
if (proxy_entry)
{
if (grat)
{
if(!(proxy_entry->flags&ATF_PERM))
arp_destroy(proxy_entry);
goto gratuitous;
}
memcpy(ha, proxy_entry->ha, dev->addr_len);
arp_unlock();
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,ha, sha);
......@@ -1151,11 +1144,7 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
}
else
{
if (grat)
goto gratuitous;
arp_unlock();
kfree_skb(skb, FREE_READ);
return 0;
}
}
else
......@@ -1165,6 +1154,8 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
*/
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
}
grat = 1;
goto gratuitous;
}
/*
* It is now an arp reply.
......@@ -1182,13 +1173,13 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
* needs to be added to the arp cache, or have its entry updated if it is
* there.
*/
gratuitous:
arp_fast_lock();
gratuitous:
hash = HASH(sip);
for (entry=arp_tables[hash]; entry; entry=entry->next)
if (entry->ip == sip && entry->dev == dev)
break;
......@@ -1198,8 +1189,14 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
/*
* Entry found; update it only if it is not a permanent entry.
*/
if (!(entry->flags & ATF_PERM)) {
memcpy(entry->ha, sha, dev->addr_len);
if (!(entry->flags & ATF_PERM))
{
if(memcmp(entry->ha, sha,dev->addr_len)!=0)
{
memcpy(entry->ha, sha, dev->addr_len);
if(entry->flags & ATF_COM)
arp_update_hhs(entry);
}
entry->last_updated = jiffies;
arpd_update(entry, __LINE__);
}
......
......@@ -517,15 +517,14 @@ static void ip_mc_dec_group(struct device *dev, unsigned long addr)
{
if((*i)->multiaddr==addr)
{
if(--((*i)->users))
return;
else
if(--((*i)->users) == 0)
{
struct ip_mc_list *tmp= *i;
igmp_group_dropped(tmp);
*i=(*i)->next;
kfree_s(tmp,sizeof(*tmp));
}
return;
}
}
}
......
......@@ -29,6 +29,9 @@
#include <linux/udp.h>
#include <linux/firewall.h>
#include <linux/ip_fw.h>
#ifdef CONFIG_IP_MASQUERADE
#include <net/ip_masq.h>
#endif
#include <net/checksum.h>
#include <linux/route.h>
#include <net/route.h>
......@@ -210,7 +213,10 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
#ifndef CONFIG_IP_NO_ICMP_REDIRECT
if (dev == dev2 &&
!((iph->saddr^dev->pa_addr)&dev->pa_mask) &&
(rt->rt_flags&RTF_MODIFIED) && !opt->srr)
/* The daddr!=raddr test isnt obvious - what its doing
is avoiding sending a frame the receiver will not
believe anyway.. */
iph->daddr != raddr/*ANK*/ && !opt->srr)
icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, raddr, dev);
#endif
#ifdef CONFIG_IP_MROUTE
......
This diff is collapsed.
......@@ -149,6 +149,9 @@
#include <net/checksum.h>
#include <linux/igmp.h>
#include <linux/ip_fw.h>
#ifdef CONFIG_IP_MASQUERADE
#include <net/ip_masq.h>
#endif
#include <linux/firewall.h>
#include <linux/mroute.h>
#include <net/netlink.h>
......@@ -423,7 +426,7 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
/*
* Do we need to de-masquerade this fragment?
*/
if (ip_fw_demasquerade(skb))
if (ip_fw_demasquerade(&skb,dev))
{
struct iphdr *iph=skb->h.iph;
if (ip_forward(skb, dev, is_frag|IPFWD_MASQUERADED, iph->daddr))
......
This diff is collapsed.
This diff is collapsed.
/*
* IP_MASQ_FTP ftp masquerading module
*
*
* Version: @(#)ip_masq_ftp.c 0.01 02/05/96
*
* Author: Wouter Gadeyne
*
*
* Fixes:
* Wouter Gadeyne : Fixed masquerading support of ftp PORT commands
* Juan Jose Ciarlante : Code moved and adapted from ip_fw.c
*
*
*
* 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.
*
*/
#include <linux/module.h>
#include <asm/system.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/ip_masq.h>
#define DEBUG_CONFIG_IP_MASQ_FTP 0
static int
masq_ftp_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
MOD_INC_USE_COUNT;
return 0;
}
static int
masq_ftp_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
MOD_DEC_USE_COUNT;
return 0;
}
int
masq_ftp_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev)
{
struct sk_buff *skb;
struct iphdr *iph;
struct tcphdr *th;
char *p, *data, *data_limit;
unsigned char p1,p2,p3,p4,p5,p6;
__u32 from;
__u16 port;
struct ip_masq *n_ms;
char buf[24]; /* xxx.xxx.xxx.xxx,ppp,ppp\000 */
unsigned buf_len;
int diff;
skb = *skb_p;
iph = skb->h.iph;
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
data = (char *)&th[1];
data_limit = skb->h.raw + skb->len - 18;
while (data < data_limit)
{
if (memcmp(data,"PORT ",5) && memcmp(data,"port ",5))
{
data ++;
continue;
}
p = data+5;
p1 = simple_strtoul(data+5,&data,10);
if (*data!=',')
continue;
p2 = simple_strtoul(data+1,&data,10);
if (*data!=',')
continue;
p3 = simple_strtoul(data+1,&data,10);
if (*data!=',')
continue;
p4 = simple_strtoul(data+1,&data,10);
if (*data!=',')
continue;
p5 = simple_strtoul(data+1,&data,10);
if (*data!=',')
continue;
p6 = simple_strtoul(data+1,&data,10);
if (*data!='\r' && *data!='\n')
continue;
from = (p1<<24) | (p2<<16) | (p3<<8) | p4;
port = (p5<<8) | p6;
#if DEBUG_CONFIG_IP_MASQ_FTP
printk("PORT %lX:%X detected\n",from,port);
#endif
/*
* Now create an masquerade entry for it
*/
n_ms = ip_masq_new(dev, IPPROTO_TCP,
htonl(from), htons(port),
iph->daddr, 0,
IP_MASQ_F_NO_DPORT);
if (n_ms==NULL)
return 0;
ip_masq_set_expire(n_ms, MASQUERADE_EXPIRE_TCP_FIN);
/*
* Replace the old PORT with the new one
*/
from = ntohl(n_ms->maddr);
port = ntohs(n_ms->mport);
sprintf(buf,"%d,%d,%d,%d,%d,%d",
from>>24&255,from>>16&255,from>>8&255,from&255,
port>>8&255,port&255);
buf_len = strlen(buf);
/*
* Calculate required delta-offset to keep TCP happy
*/
diff = buf_len - (data-p);
/*
* No shift.
*/
if (diff==0)
{
/*
* simple case, just replace the old PORT cmd
*/
memcpy(p,buf,buf_len);
return 0;
}
*skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC, p, data-p, buf, buf_len);
return diff;
}
return 0;
}
struct ip_masq_app ip_masq_ftp = {
NULL, /* next */
0, /* type */
0, /* n_attach */
masq_ftp_init_1, /* ip_masq_init_1 */
masq_ftp_done_1, /* ip_masq_done_1 */
masq_ftp_out, /* pkt_out */
NULL /* pkt_in */
};
/*
* ip_masq_ftp initialization
*/
int ip_masq_ftp_init(void)
{
return register_ip_masq_app(&ip_masq_ftp, IPPROTO_TCP, 21);
}
/*
* ip_masq_ftp fin.
*/
int ip_masq_ftp_done(void)
{
return unregister_ip_masq_app(&ip_masq_ftp);
}
#ifdef MODULE
int init_module(void)
{
if (ip_masq_ftp_init() != 0)
return -EIO;
register_symtab(0);
return 0;
}
void cleanup_module(void)
{
if (ip_masq_ftp_done() != 0)
printk("ip_masq_ftp: can't remove module");
}
#endif /* MODULE */
/*
* IP_MASQ_IRC irc masquerading module
*
*
* Version: @(#)ip_masq_irc.c 0.01 03/20/96
*
* Author: Juan Jose Ciarlante
*
*
* Fixes:
* - set NO_DADDR flag in ip_masq_new().
*
* FIXME:
* - detect also previous "PRIVMSG" string ?.
*
* 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.
*
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <asm/system.h>
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <net/protocol.h>
#include <net/tcp.h>
#include <net/ip_masq.h>
#define DEBUG_CONFIG_IP_MASQ_IRC 0
static int
masq_irc_init_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
MOD_INC_USE_COUNT;
return 0;
}
static int
masq_irc_done_1 (struct ip_masq_app *mapp, struct ip_masq *ms)
{
MOD_DEC_USE_COUNT;
return 0;
}
int
masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, struct device *dev)
{
struct sk_buff *skb;
struct iphdr *iph;
struct tcphdr *th;
char *data, *data_limit;
__u32 s_addr;
__u16 s_port;
struct ip_masq *n_ms;
char buf[20]; /* "m_addr m_port" (dec base)*/
unsigned buf_len;
int diff;
int xtra_args = 0; /* extra int args wanted after addr */
char *dcc_p, *addr_beg_p, *addr_end_p;
skb = *skb_p;
iph = skb->h.iph;
th = (struct tcphdr *)&(((char *)iph)[iph->ihl*4]);
data = (char *)&th[1];
/*
* Hunt irc DCC string, the _shortest_:
*
* strlen("DCC CHAT chat AAAAAAAA P\x01\n")=26
* strlen("DCC SEND F AAAAAAAA P S\x01\n")=25
* AAAAAAAAA: bound addr (1.0.0.0==16777216, min 8 digits)
* P: bound port (min 1 d )
* F: filename (min 1 d )
* S: size (min 1 d )
* 0x01, \n: terminators
*/
data_limit = skb->h.raw + skb->len;
while (data < (data_limit - 25) )
{
if (memcmp(data,"DCC ",4)) {
data ++;
continue;
}
dcc_p = data;
data += 4; /* point to DCC cmd */
if (memcmp(data, "CHAT ", 5) == 0 ||
memcmp(data, "SEND ", 5) == 0)
{
/*
* extra arg (file_size) req. for "SEND"
*/
if (*data == 'S') xtra_args++;
data += 5;
}
else
continue;
/*
* skip next string.
*/
while( *data++ != ' ')
/*
* must still parse, at least, "AAAAAAAA P\x01\n",
* 12 bytes left.
*/
if (data > (data_limit-12)) return 0;
addr_beg_p = data;
/*
* client bound address in dec base
*/
s_addr = simple_strtoul(data,&data,10);
if (*data++ !=' ')
continue;
/*
* client bound port in dec base
*/
s_port = simple_strtoul(data,&data,10);
addr_end_p = data;
/*
* should check args consistency?
*/
while(xtra_args) {
if (*data != ' ')
break;
data++;
simple_strtoul(data,&data,10);
xtra_args--;
}
if (xtra_args != 0) continue;
/*
* terminators.
*/
if (data[0] != 0x01)
continue;
if (data[1]!='\r' && data[1]!='\n')
continue;
/*
* Now create an masquerade entry for it
* must set NO_DPORT and NO_DADDR because
* connection is requested by another client.
*/
n_ms = ip_masq_new(dev, IPPROTO_TCP,
htonl(s_addr),htons(s_port),
0, 0,
IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR
);
if (n_ms==NULL)
return 0;
ip_masq_set_expire(n_ms, MASQUERADE_EXPIRE_TCP_FIN);
/*
* Replace the old "address port" with the new one
*/
buf_len = sprintf(buf,"%lu %u",
ntohl(n_ms->maddr),ntohs(n_ms->mport));
/*
* Calculate required delta-offset to keep TCP happy
*/
diff = buf_len - (addr_end_p-addr_beg_p);
#if DEBUG_CONFIG_IP_MASQ_IRC
*addr_beg_p = '\0';
printk("masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff);
#endif
/*
* No shift.
*/
if (diff==0)
{
/*
* simple case, just copy.
*/
memcpy(addr_beg_p,buf,buf_len);
return 0;
}
*skb_p = ip_masq_skb_replace(skb, GFP_ATOMIC,
addr_beg_p, addr_end_p-addr_beg_p,
buf, buf_len);
return diff;
}
return 0;
}
/*
* Main irc object
* You need 1 object per port in case you need
* to offer also other used irc ports (6665,6666,etc),
* they will share methods but they need own space for
* data.
*/
struct ip_masq_app ip_masq_irc = {
NULL, /* next */
0, /* type */
0, /* n_attach */
masq_irc_init_1, /* init_1 */
masq_irc_done_1, /* done_1 */
masq_irc_out, /* pkt_out */
NULL /* pkt_in */
};
/*
* ip_masq_irc initialization
*/
int ip_masq_irc_init(void)
{
return register_ip_masq_app(&ip_masq_irc, IPPROTO_TCP, 6667);
}
/*
* ip_masq_irc fin.
*/
int ip_masq_irc_done(void)
{
return unregister_ip_masq_app(&ip_masq_irc);
}
#ifdef MODULE
int init_module(void)
{
if (ip_masq_irc_init() != 0)
return -EIO;
register_symtab(NULL);
return 0;
}
void cleanup_module(void)
{
if (ip_masq_irc_done() != 0)
printk("ip_masq_irc: can't remove module");
}
#endif /* MODULE */
......@@ -239,7 +239,7 @@ int ip_build_header(struct sk_buff *skb, __u32 saddr, __u32 daddr,
if ((LOOPBACK(saddr) && !LOOPBACK(daddr)) || !saddr)
saddr = rt ? rt->rt_src : (*dev)->pa_addr;
raddr = rt ? rt->rt_gateway : 0;
raddr = rt ? rt->rt_gateway : daddr;
if (opt && opt->is_strictroute && rt && (rt->rt_flags & RTF_GATEWAY))
{
......@@ -248,13 +248,6 @@ int ip_build_header(struct sk_buff *skb, __u32 saddr, __u32 daddr,
return -ENETUNREACH;
}
/*
* No gateway so aim at the real destination
*/
if (raddr == 0)
raddr = daddr;
/*
* Now build the MAC header.
*/
......
......@@ -41,6 +41,7 @@
* Olaf Erb : irtt wasnt being copied right.
* Bjorn Ekwall : Kerneld route support.
* Alan Cox : Multicast fixed (I hope)
* Pavel Krauz : Limited broadcast fixed
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -1558,9 +1559,9 @@ struct rtable * ip_rt_slow_route (__u32 daddr, int local)
if (!(rth->rt_flags & RTF_GATEWAY))
rth->rt_gateway = rth->rt_dst;
/*
* Multicast is never gatewayed.
* Multicast or limited broadcast is never gatewayed.
*/
if (MULTICAST(daddr))
if (MULTICAST(daddr) || daddr == 0xFFFFFFFF)
rth->rt_gateway = rth->rt_dst;
if (ip_rt_lock == 1)
......
......@@ -74,6 +74,7 @@
#include <linux/termios.h> /* For TIOCOUTQ/INQ */
#include <linux/interrupt.h>
#include <net/p8022.h>
#include <net/p8022tr.h>
#include <net/psnap.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
......@@ -90,6 +91,7 @@ static char ipxcfg_auto_create_interfaces = 0;
/* Global Variables */
static struct datalink_proto *p8022_datalink = NULL;
static struct datalink_proto *p8022tr_datalink = NULL;
static struct datalink_proto *pEII_datalink = NULL;
static struct datalink_proto *p8023_datalink = NULL;
static struct datalink_proto *pSNAP_datalink = NULL;
......@@ -840,6 +842,7 @@ ipx_map_frame_type(unsigned char type)
switch (type) {
case IPX_FRAME_ETHERII: return htons(ETH_P_IPX);
case IPX_FRAME_8022: return htons(ETH_P_802_2);
case IPX_FRAME_TR_8022: return htons(ETH_P_TR_802_2);
case IPX_FRAME_SNAP: return htons(ETH_P_SNAP);
case IPX_FRAME_8023: return htons(ETH_P_802_3);
}
......@@ -869,6 +872,10 @@ ipxitf_create(ipx_interface_definition *idef)
dlink_type = htons(ETH_P_IPX);
datalink = pEII_datalink;
break;
case IPX_FRAME_TR_8022:
dlink_type = htons(ETH_P_TR_802_2);
datalink = p8022tr_datalink;
break;
case IPX_FRAME_8022:
dlink_type = htons(ETH_P_802_2);
datalink = p8022_datalink;
......@@ -969,6 +976,7 @@ ipxitf_auto_create(struct device *dev, unsigned short dlink_type)
switch (htons(dlink_type)) {
case ETH_P_IPX: datalink = pEII_datalink; break;
case ETH_P_802_2: datalink = p8022_datalink; break;
case ETH_P_TR_802_2: datalink = p8022tr_datalink; break;
case ETH_P_SNAP: datalink = pSNAP_datalink; break;
case ETH_P_802_3: datalink = p8023_datalink; break;
default: return NULL;
......@@ -1318,6 +1326,7 @@ ipx_frame_name(unsigned short frame)
case ETH_P_802_2: return "802.2";
case ETH_P_SNAP: return "SNAP";
case ETH_P_802_3: return "802.3";
case ETH_P_TR_802_2: return "802.2TR";
default: return "None";
}
}
......@@ -2257,6 +2266,9 @@ ipx_proto_init(struct net_proto *pro)
if ((p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv)) == NULL)
printk("IPX: Unable to register with 802.2\n");
if ((p8022tr_datalink = register_8022tr_client(ipx_8022_type, ipx_rcv)) == NULL)
printk("IPX: Unable to register with 802.2TR\n");
if ((pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv)) == NULL)
printk("IPX: Unable to register with SNAP\n");
......
......@@ -56,11 +56,11 @@ extern void destroy_8023_client(struct datalink_proto *);
static struct symbol_table net_syms = {
#include <linux/symtab_begin.h>
/* Socket layer registration */
X(sock_register),
X(sock_unregister),
/* Socket layer registration */
X(sock_register),
X(sock_unregister),
/* Socket layer support routines */
/* Socket layer support routines */
X(memcpy_fromiovec),
X(sock_setsockopt),
X(sock_getsockopt),
......@@ -116,8 +116,8 @@ static struct symbol_table net_syms = {
#endif
#ifdef CONFIG_TR
X(tr_setup),
X(tr_type_trans),
X(tr_setup),
X(tr_type_trans),
#endif
#ifdef CONFIG_NET_ALIAS
......
......@@ -21,6 +21,7 @@
#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
#include <net/ipxcall.h>
#include <net/p8022call.h>
#include <net/p8022trcall.h>
#endif
#ifdef CONFIG_AX25
#include <net/ax25call.h>
......@@ -31,6 +32,7 @@
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
#if ! ( defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) )
#include <net/p8022call.h>
#include <net/p8022trcall.h>
#endif
#include <net/atalkcall.h>
#endif
......@@ -51,6 +53,7 @@ struct net_proto protocols[] = {
#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE) || \
defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
{ "802.2", p8022_proto_init }, /* 802.2 demultiplexor */
{ "802.2TR", p8022tr_proto_init }, /* 802.2 demultiplexor */
{ "SNAP", snap_proto_init }, /* SNAP demultiplexor */
#endif
#ifdef CONFIG_TR
......
......@@ -65,7 +65,10 @@
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/firewall.h>
#ifdef CONFIG_KERNELD
#include <linux/kerneld.h>
#endif
#include <net/netlink.h>
......@@ -1027,7 +1030,7 @@ asmlinkage int sys_recvfrom(int fd, void * ubuf, int size, unsigned flags,
return err;
msg.msg_accrights=NULL;
msg.msg_iovlen=0;
msg.msg_iovlen=1;
msg.msg_iov=&iov;
iov.iov_len=size;
iov.iov_base=ubuf;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment