]> git.neil.brown.name Git - history.git/commitdiff
Linux 2.0.36pre8 2.0.36pre8
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:58 +0000 (15:11 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:58 +0000 (15:11 -0500)
Bug Fixes

   Large Memory
          Linux 2.0.36 uses the newer bios calls to automatically size
          memory above 64Mbytes, where supported by the BIOS.

   Readv/Writev
          Processes issuing a readv or writev to a device that did not
          have the relevant read/write operation could cause an Oops and
          potentially a crash.

   UDMA Drives
          Report Bad CRC (cable errors) as a cable error. Handling of
          such errors was correct.

   pipe syscall error
          The pipe call could return ENFILE not -1 and errno= -ENFILE.
          Fixed.

   AIC7xxx
          The 2.0.36 kernel contains the 5.0.20 release of the AIC7xxx
          driver. This should cure most of the remaining problems with
          the older chipsets. Users with the latest AIC7xxx devices will
          have to wait for the next driver version to become available or
          try the beta test driver.

   Procfs permissions fix
          A process with root file rights can now read all /proc files.

   Daylight Savings in SMB
          The SMB file system honours daylight savings time.

   EATA SCSI/Ultrastor 14f/34f
          Reverse scan order support and configurable extended geometry.
          Increased the busy timeout.

   Build fixes
          Use relative paths for sound, remove trampoline.hex on a make
          clean, support the newer versioned symbols as part of a multi
          object file module.

   Oops handling
          A small fencepost error in Oops handling on syscall return has
          been cured.

   TLan 1.0
          The Thunderlan driver has been updated to the 1.0 release.

   Delay loops
          The delay loop code has been modified to eliminate most of the
          remaining cache/branch prediction and other variants to its
          performance.

   5.25" floppy
          An incorrect floppy table entry has been altered, and a
          potential crash on unload fixed.

   Iomega ZIP driver
          Handle 23.D firmware funnies.

   Cyclades Serial
          Upgraded driver from vendor, with assorted bugs fixed.

   Printer Driver
          The correction in the printer handling upset the Epson Stylus
          800. The driver know has a LPSTRICT option that can be set for
          printers that need absolute strict NBUSY handling.

   Beeper gets stuck
          The case where the beeper decides to beep forever has been
          cured.

   3c509 ethernet
          Upgraded to v1.16. Fixes ID port clash with sound cards,
          waiting for discard messages and recovers faster from transmit
          errors.

   3c59x driver
          Updated 3c59x ethernet driver. This should cure the skb_push
          panics some people saw with 3c59x/3c90x drivers under load.

   Lance driver
          Module unload bugs in the lance driver have been fixed.

   Plip driver
          Messages without severity levels now have appropriate levels.

   AHA1542
          Allow the use of DMA 0 on newer motherboards.

   SHM swap off
          A case where the machine might crash when turning swapping off
          has been fixed.

   MMAP security
          Linux did not allow a writable mmap of an append only file. It
          did however allow a readonly mmap of such a file then an
          mprotect. Fixed.

   NAKAMICH MJ-5.16S
          This SCSI device has been added to the blacklist.

   Single lun blacklisting
          A bug in the single lun blacklisting has been fixed.

   SCSI CAM division by zero
          A corrupt geometry could cause the kernel to divide by zero and
          crash.

   Sound blaster
          Don't report a DMA channel 0 for the MPU

   Sequencer
          If there are no synths or midi devices do not lock the
          sequencer busy forever.

   Autofs
          Fix a small glitch in the directory hash.

   ISOfs
          Fix a fencepost error in the iso fs size checks.

   Vfat fs
          Disallow periods at the end of names.

   NFS file system
          Support FIFO's over NFS. Handle kill of nfsiod for module
          unload.

   NFS root
          IFF_MULTICAST could be incorrectly not set.

   Non modular soundmodem/baycom
          These devices only worked as modules. They now work compiled
          in.

   Memory leak in networking
          A very obscure leak in the networking code has been fixed.

   TCP select
          TCP select for urgent data now has correct semantics.
          Previously it could do the wrong thing.

   TCP SIGIO
          SIGIO on an incoming connection is now correctly issued on the
          completion of the three way handshake.

Enhancements

   ISDN
          The Isdn4linux layer is signifcantly upgraded. The new driver
          set adds support for the Teles 16.3c, Teles PCI, Teles S0Box,
          Creatix S0Box, Compaq ISDN S0 ISA, ELSA Quickstep 1000PCI, Elsa
          Quickstep 3000, Elsa Quickstep 3000PCI, Eicon.Diehl Diva 2.0
          ISA/PCI (not Pro), Eicon.Diehl Diva Piccola, AsusCom ISDNLink
          128K, Dynalink IS64PH, HFC-2BS0 based cards, Sedlbauer Speed
          Card(Speed win, teledat 100), Sedlbauer Speed Star PCMCIA, USR
          Sportster Internal TA, ITH MIC 16 ISA, Traverse NETjet PCI,
          Niccy PnP/PCI

   Shaper
          The shaper device provides a simple traffic limiting driver for
          Linux 2.0.x. For full traffic shaping watch for Linux 2.2
          coming soon..

   Tulip
          The tulip driver has been upgraded to 0.89H which should also
          support the clone PNIC and MXIC tulip devices.

   Extended CPUID/Chip identification
          The Cyrix/AMD extended CPUID mode is supported. Cyrix
          processors are identified even when CPUID is not available. The
          Intel Celeron Mendicino is recognized. K6's with the random
          oops bug are normally now detected. The K6 cpu deadlock problem
          isn't detected as we know no way to check for it except to try
          it.

   Multi-Tech driver
          Driver for multi-tech 4/8 port modem and serial
          cards.(Experimental).

   EtherExpress
          The Compaq LTE should now be recognized (experimental)

   Intel 440GX
          The 440GX chipset is known to the PCI data tables.

   Nvidia
          NVidia/SGS Thomson is known to the PCI data tables.

   SCSI medium changers
          These are no long reported as unknown device types.

   ROSE networking
          The ROSE network layer has been updated.

Other

   Bigger system call table
          To support add ons that use syscalls in the new range.

   Hooks for dumping
          Kernel hooks for optional threaded core dump module.

26 files changed:
Documentation/Changes
Documentation/Configure.help
Documentation/ippfvsadm.c [deleted file]
Documentation/isdn/README.TimRu.De [deleted file]
arch/i386/kernel/setup.c
drivers/char/Config.in
drivers/char/Makefile
drivers/char/cyclades.c
drivers/char/isicom.c [new file with mode: 0644]
drivers/char/isicom.h [new file with mode: 0644]
drivers/char/lp.c
drivers/isdn/Config.in
drivers/pci/pci.c
drivers/scsi/scsicam.c
drivers/sound/Makefile
fs/nfs/nfsroot.c
include/linux/cyclades.h
include/linux/ip_fw.h
include/linux/lp.h
include/linux/proc_fs.h
include/net/ip_masq.h
net/ipv4/Config.in
net/ipv4/ip_fw.c
net/ipv4/ip_masq.c
net/ipv4/ip_sockglue.c
net/ipv4/tcp_input.c

index efb08999a2843314f78a2c6379d968ef29ae64d1..d2cde64a9d70c03bac0351de772b62c4b2dd3f62 100644 (file)
@@ -17,10 +17,6 @@ Boldt's (boldt@math.ucsb.edu) Configure.help file, among other sources,
 and was originally written and maintained by Alessandro Sigala
 (ssigala@globalnet.it).
 
-   There is now a web page based on this material, thanks to John
-Taylor.  Check out http://www.cviog.uga.edu/LinuxBleed.html if you
-prefer a HTML-ized shopping list.
-
    Para aquellos que prefieran una version en castellano de este
 documento, consultad la traduccion de Alfredo Sanjuan en
 http://slug.ctv.es/~alfredo/Cambios.html (Spanish translation).
index 8d3a79af8f6f08bb7e9e539c7d5eedbbceea88f5..e836ee8c767611332d5c8c1acb8f3377ce3c3eeb 100644 (file)
@@ -1194,22 +1194,6 @@ CONFIG_IP_MASQUERADE_IPAUTOFW
   and other information, is available at
   ftp://ftp.netis.com/pub/members/rlynch/.
 
-IP: ipportfw masquerade and virtual server support
-CONFIG_IP_MASQUERADE_IPPFVS
-  ippfvs is port forwarding & virtual server program in Linux kernel
-  by Wensong Zhang, based on IP masquerading and Steven Clarke's
-  port forwarding codes. It can dynamically forward a connection on
-  given ports from outside to one server in a cluster of servers 
-  inside a firewall, the round-robin secheduling or weighted 
-  round-robin scheduling algorithm is used to choose which server 
-  the connection is redirected to. This function can be used to build 
-  a virtual internet server on a cluster of servers, such as scalable
-  web server.
-  For information and source of ippfvsadm administration program, 
-  please visit the following URL: 
-        http://proxy.iinchina.net/~wensong/ippfvs/
-  If you want this, say Y.
-
 IP: ICMP masquerading
 CONFIG_IP_MASQUERADE_ICMP
   The basic masquerade code described for CONFIG_IP_MASQUERADE only
diff --git a/Documentation/ippfvsadm.c b/Documentation/ippfvsadm.c
deleted file mode 100644 (file)
index 5a90c47..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
-
- *      ippfvsadm - Port Fowarding & Virtual Server ADMinistration program v1.0
- *
- *      Copyright (c) 1998 Wensong Zhang
- *      All rights reserved.
- *
- *      Author: Wensong Zhang <wensong@iinchina.net>
- *
- *      This program is derived from Steven Clarke's ipportfw program.
- *
- *      portfw - Port Forwarding Table Editing v1.1
- *
- *      Copyright (c) 1997 Steven Clarke
- *      All rights reserved.
- *
- *      Author: Steven Clarke <steven@monmouth.demon.co.uk>
- *
- *              Keble College
- *              Oxford
- *              OX1 3PG
- *
- *              WWW:    http://www.monmouth.demon.co.uk/
- *
- *
- *      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 <stdio.h>
-#include <errno.h>
-#include <limits.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <getopt.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <linux/icmp.h>
-#include <linux/if.h>
-#include <linux/timer.h>
-#include <linux/ip_fw.h>
-#include <sys/param.h>
-
-#define IP_PORTFW_NONE 0
-#define IP_PORTFW_LIST 10000
-#define DEFAULT_WEIGHT      1
-#define IPPROTO_NONE   65535
-
-long string_to_number (char *str, int min, int max);
-int parse_addressport (char *name, __u32 * raddr, __u16 * rport);
-int do_setsockopt (int cmd, struct ip_portfw_edits *data, int length);
-void exit_error (int status, char *msg);
-void exit_display_help (void);
-void list_forwarding (void);
-
-char *program;
-
-int 
-main (int argc, char *argv[])
-{
-    int c;
-    int command = IP_PORTFW_NONE;
-    struct ip_portfw_edits pfw;
-
-    pfw.protocol = IPPROTO_NONE;
-    pfw.raddr = 0;
-    pfw.rport = 0;
-    pfw.laddr = 0;
-    pfw.lport = 0;
-    pfw.weight = 0;
-
-    program = argv[0];
-
-    while ((c = getopt (argc, argv, "ADCLt:u:R:w:h")) != -1)
-       switch (c)
-         {
-         case 'A':
-             if (command != IP_PORTFW_NONE)
-                 exit_error (2, "multiple commands specified");
-             command = IP_PORTFW_ADD;
-             break;
-         case 'D':
-             if (command != IP_PORTFW_NONE)
-                 exit_error (2, "multiple commands specified");
-             command = IP_PORTFW_DEL;
-             break;
-         case 'C':
-             if (command != IP_PORTFW_NONE)
-                 exit_error (2, "multiple commands specified");
-             command = IP_PORTFW_FLUSH;
-             break;
-         case 'L':
-             if (command != IP_PORTFW_NONE)
-                 exit_error (2, "multiple commands specified");
-             command = IP_PORTFW_LIST;
-             break;
-
-         case 't':
-         case 'u':
-             if (pfw.protocol != IPPROTO_NONE)
-                 exit_error (2, "multiple protocols specified");
-             pfw.protocol = (c == 't' ? IPPROTO_TCP : IPPROTO_UDP);
-             if (parse_addressport (optarg, &pfw.laddr, &pfw.lport) == -1)
-                 exit_error (2, "illegal virtual server address:port specified");
-             break;
-         case 'R':
-             if (pfw.raddr != 0 || pfw.rport != 0)
-                 exit_error (2, "multiple destinations specified");
-             if (parse_addressport (optarg, &pfw.raddr, &pfw.rport) == -1)
-                 exit_error (2, "illegal destination specified");
-             break;
-         case 'w':
-             if (pfw.weight != 0)
-                 exit_error (2, "multiple server weights specified");
-             pfw.weight = string_to_number (optarg, SERVER_WEIGHT_MIN, SERVER_WEIGHT_MAX);
-             if (pfw.weight == -1)
-                 exit_error (2, "illegal weight specified");
-             break;
-         case 'h':
-         case '?':
-         default:
-             exit_display_help ();
-         }
-
-    if (pfw.weight == 0)
-       pfw.weight = DEFAULT_WEIGHT;
-
-    if (optind < argc)
-       exit_error (2, "unknown arguments found on commandline");
-
-    if (command == IP_PORTFW_NONE)
-       exit_display_help ();
-
-    else if (command == IP_PORTFW_ADD &&
-            (pfw.protocol == IPPROTO_NONE || pfw.lport == 0 ||
-             pfw.rport == 0 || pfw.raddr == 0))
-       exit_error (2, "insufficient options specified");
-
-    else if (command == IP_PORTFW_DEL &&
-            (pfw.protocol == IPPROTO_NONE || pfw.lport == 0))
-       exit_error (2, "insufficient options specified");
-
-    else if ((command == IP_PORTFW_FLUSH || command == IP_PORTFW_LIST) &&
-            (pfw.protocol != IPPROTO_NONE || pfw.lport != 0 ||
-             pfw.rport != 0 || pfw.raddr != 0))
-       exit_error (2, "incompatible options specified");
-
-    if (command == IP_PORTFW_LIST)
-       list_forwarding ();
-    else
-       exit (do_setsockopt (command, &pfw, sizeof (pfw)));
-}
-
-
-long 
-string_to_number (char *str, int min, int max)
-{
-    char *end;
-    long number;
-
-    number = strtol (str, &end, 10);
-    if (*end == '\0' && end != str)
-      {
-         if (min <= number && number <= max)
-             return number;
-         else
-             return -1;
-      }
-    else
-       return -1;
-}
-
-
-int 
-parse_addressport (char *name, __u32 * raddr, __u16 * rport)
-{
-    char buf[23];              /* xxx.xxx.xxx.xxx:ppppp\0 */
-    char *p, *q;
-    int onebyte, i;
-    long l;
-
-    strncpy (buf, name, sizeof (buf) - 1);
-    if ((p = strchr (buf, ':')) == NULL)
-       return -1;
-
-    *p = '\0';
-    if ((l = string_to_number (p + 1, IP_PORTFW_PORT_MIN, IP_PORTFW_PORT_MAX)) == -1)
-       return -1;
-    else
-       *rport = l;
-
-    p = buf;
-    *raddr = 0;
-    for (i = 0; i < 3; i++)
-      {
-         if ((q = strchr (p, '.')) == NULL)
-             return -1;
-         else
-           {
-               *q = '\0';
-               if ((onebyte = string_to_number (p, 0, 255)) == -1)
-                   return -1;
-               else
-                   *raddr = (*raddr << 8) + onebyte;
-           }
-         p = q + 1;
-      }
-
-    /* we've checked 3 bytes, now we check the last one */
-    if ((onebyte = string_to_number (p, 0, 255)) == -1)
-       return -1;
-    else
-       *raddr = (*raddr << 8) + onebyte;
-
-    return 0;
-}
-
-
-int 
-do_setsockopt (int cmd, struct ip_portfw_edits *data, int length)
-{
-    static int sockfd = -1;
-    int ret;
-
-    if (sockfd == -1)
-      {
-         if ((sockfd = socket (AF_INET, SOCK_RAW, IPPROTO_RAW)) == -1)
-           {
-               perror ("ippfvsadm: socket creation failed");
-               exit (1);
-           }
-      }
-
-    ret = setsockopt (sockfd, IPPROTO_IP, cmd, (char *) data, length);
-    if (ret)
-       perror ("ippfvsadm: setsockopt failed");
-
-    return ret;
-}
-
-
-void 
-exit_error (int status, char *msg)
-{
-    fprintf (stderr, "%s: %s\n", program, msg);
-    exit (status);
-}
-
-void 
-list_forwarding (void)
-{
-    char buffer[256];
-
-    FILE *handle;
-    handle = fopen ("/proc/net/ip_portfw", "r");
-    if (!handle)
-      {
-         printf ("Could not open /proc/net/ip_portfw\n");
-         printf ("Are you sure you have Port Forwarding & Virtual Server support installed?\n");
-         exit (1);
-      }
-
-    while (!feof (handle))
-       if (fgets (buffer, 256, handle))
-           printf ("%s", buffer);
-    fclose (handle);
-
-}
-
-void 
-exit_display_help (void)
-{
-    printf ("%s v1.0 1998/5/26\n\n"
-         "Usage: %s -A -[t|u] l.l.l.l:lport -R a.a.a.a:rport [-w weight]\n"
-           "       %s -D -[t|u] l.l.l.l:lport -R a.a.a.a:rport\n"
-           "       %s -C\n"
-           "       %s -L\n\n"
-           "Commands:\n"
-           "       -A  To add a real server\n"
-           "       -D  To delete a real server\n"
-           "       -C  To clear the table\n"
-           "       -L  To list the table\n\n"
-           "Options:\n"
-           "  t means TCP protocol, and u indicates UDP protocol.\n"
-            "  l.l.l.l:lport are the IP address and port of the virtual server.\n"
-           "  a.a.a.a:rport are the IP address and port of the real server.\n"
-           "  weight is a value to indicate the processing capacity of a real server.\n",
-           program, program, program, program, program);
-
-    exit (0);
-}
diff --git a/Documentation/isdn/README.TimRu.De b/Documentation/isdn/README.TimRu.De
deleted file mode 100644 (file)
index e3f86ac..0000000
+++ /dev/null
@@ -1,296 +0,0 @@
---( Version: 11.10.1997 )--
-
-TimRu-Erweiterungen:
-====================
-
-1. erfolglose Anwahlversuche per ICMP zurueckmelden
----------------------------------------------------
-
-isdnctrl dialtimeout <name> <timeout>
-    name:    Name des Interfaces
-    timeout: -1: kein Waehl-Timeout
-              0: jede Telefonnummer dialmax-mal probieren
-             >0: Zeitraum in Sekunden, in dem die Anwahl versucht wird
-
-    isdnctrl dialtimeout bewirkt, dass die Anwahl der Gegenstelle im Fehler-
-    fall nicht unbegrenzt versucht wird, sondern entweder nach einer bestimmten
-    Anzahl von Versuchen oder nach einem bestimmten Zeitraum abgebrochen wird
-    und alle ausstehenden Pakete fuer den durch isdnctrl dialwait bestimmten
-    Zeitraum mit ICMP_NET_UNREACHABLE beantwortet werden.
-
-
-isdnctrl dialwait <name> <seconds>
-    name:    Name des Interfaces
-    seconds:  0: keine Waehl-Unterdrueckung im Fehlerfall
-             >0: Zeit in Sekunden, in der nach einem erfolglosen Anwahl-
-                 versuch Pakete mit ICMP_NET_UNREACHABLE beantwortet werden
-
-
-1.1 einzelne Interfaces stoppen / starten
------------------------------------------
-
-isdnctrl status <name> <status>
-    name:   Name des Interfaces
-    status: on:  Interface einschalten
-            off: Interface ausschalten
-
-    Dieser Befehl wirkt wie 'isdnctrl system on/off' auf Interface-Ebene.
-
-
-2. bessere Kontrolle ueber Aufbau und Hangup einer Verbindung
--------------------------------------------------------------
-
-isdnctrl <cmd> <name> bringup <seconds> <rule>
-isdnctrl <cmd> <name> keepup in <seconds> <rule>
-isdnctrl <cmd> <name> keepup out <seconds> <rule>
-isdnctrl <cmd> <name> keepup both <seconds> <rule>
-    cmd:     addrule:        Regel am Ende der Regelliste anfuegen
-             insrule:        Regel am Anfang der Regelliste einfuegen
-             delrule:        Regel loeschen
-             default:        Was tun, wenn keine Regel passt?
-             showrules:      alle Regeln anzeigen
-             flushrules:     alle Regeln einer Art loeschen (bringup, ...)
-             flushallrules:  alle Regeln loeschen
-
-    name:    Name des Interfaces
-    seconds: Mindester Hangup-Timeout ab jetzt
-    rule:    Regel, auf die ein Paket passen muss, damit die Verbindung
-             aufgebaut oder der Hangup-Timeout verlaengert wird
-
-
-    Eine passende Bringup-Regel erlaubt den Aufbau der Verbindung,
-    wenn ihr Timeout > 0 ist. Eine Bringup-Regel mit einen Timeout == 0
-    verhindert einen Verbindungsaufbau. Dieser Timeout muss eigentlich nur
-    so gross sein, dass die Verbindung zum Gegenrechner erfolgreich
-    zustande kommt, da das ausloesende Datenpaket danach durch die
-    Keepup-Logik 'geht' und der Hangup-Timeout erneut berechnet wird.
-
-    Eine passende Keepup-Regel verlaengert den Hangup-Timeout, wobei
-    nach eingehenden und ausgehenden Paketen unterschieden werden kann.
-
-    Die Kontrolle eines Paketes stoppt bei der ersten passenden Regel, falls
-    keine Regel anwendbar ist, gilt die Default-Regel.
-
-    Die Regeln haben folgenden Aufbau:
-        ip/icmp <src>/<mask> <type> <dst>/<mask>
-        ip/tcp  <src>/<mask> <port> <dst>/<mask> <port>
-        ip/udp  <src>/<mask> <port> <dst>/<mask> <port>
-        ip/*    <src>/<mask>        <dst>/<mask>
-        ip/any  <src>/<mask>        <dst>/<mask>
-
-        ipx/*
-        ipx/any
-
-        ppp/ipcp
-        ppp/ipxcp
-        ppp/ccp
-        ppp/lcp
-        ppp/chap
-        ppp/pap
-        ppp/lqr
-        ppp/*
-        ppp/any
-
-        */*
-        any
-
-
-        src:    Absender-Adresse des Paketes als Nummer oder Name
-        dst:    Empfaenger-Adresse des Paketes als Nummer oder Name
-        mask:   Subnet-Maske als Anzahl Bits oder als Maske
-        type:   ICMP-Message-Type als Nummer
-        port:   Portnummer als Nummer oder Name
-
-
-       Wildcards ('*', 'any') sind ueberall erlaubt.
-
-        Fuer <src> und <dst> gilt:
-            <host>:           Host-Adresse als Nummer oder Name,
-                              Subnet-Mask /32
-            <host>/<mask>:    Host-Adresse als Nummer oder Name,
-                              Subnet-Mask als Anzahl Bits oder Maske
-            <network>:        Netzwerk-Adresse als Nummer oder Name,
-                              Subnet-Mask /32
-            <network>/<mask>: Host-Adresse als Nummer oder Name,
-                              Subnet-Mask als Anzahl Bits oder Maske
-            0.0.0.0/0
-            0/0
-            *
-            any:              Wildcard, passt auf jede Adresse.
-
-       Fuer <ports> gilt:
-            <from>-<to>: alle Ports von <from> bis <to>, numerische Angabe
-            <from>-:     alle Ports von <from> bis 65535, numerische Angabe
-            -<to>:       alle Ports von 0 bis <to>, numerische Angabe
-            <port>:      ein Port als Nummer oder Name
-            -, *
-            oder any:    alle Ports
-
-       Beginnt die Regel mit einem '!' oder mit 'not', so dreht sich ihre Aussage um:
-        falls sie NICHT passt, wird die Verbindung aufgebaut, bzw. der
-        Hangup-Timeout verlaengert.
-
-
-    Default-Regeln werden folgendermassen angegeben:
-
-        isdnctrl default <name> bringup <timeout>
-            name:    Name des Interfaces
-            timeout:  0: Verbindung wird nicht aufgebaut
-                     >0: Verbindung wird aufgebaut, anfaenglicher Timeout
-                         ist <timeout>.
-
-        isdnctrl default <name> keepup in <seconds>
-        isdnctrl default <name> keepup out <seconds>
-        isdnctrl default <name> keepup both <seconds>
-            name:    Name des Interfaces
-            seconds: Mindester Hangup-Timeout
-
-
-3. Budget-Erweiterungen
------------------------
-
-Diese Erweiterung erlaubt es, bestimmte 'Verbrauchswerte' pro
-Zeitraum zu limitieren. Falls ein Budget aufgebraucht ist, findet
-keine Anwahl mehr statt und eine bestehende Verbindung wird unterbrochen.
-Sobald wieder alle Budgets verfuegbar sind, werden wieder Verbindungen
-zugelassen.
-Die Gebuehrenimpuls-Zaehlung setzt momentan auf der Uebertragung der
-CINF-Pakete, also der Gebuehreninformation waehrend der Verbindung auf.
-Unmittelbar nach Aufbau der Verbindung wird der erste Gebuehrenimpuls
-'angenommen'.
-Fuer ISDN-Anschluesse, bei denen die Gebuehren erst am Ende der Ver-
-bindung uebertragen werden, faellt uns bestimmt auch noch was ein ;-).
-
-isdnctrl budget <name> <budget-type> <amount> <period>
-    setzt die Werte eines bestimmten Budgets. Ein aufgebrauchtes
-    Budget wird unmittelbar wieder aktiviert.
-
-       budget-type: dial:    Anzahl der Anwahlversuche (erfolgreich oder
-                          erfolglos) pro Periode
-                 charge:  Anzahl der Gebuehreneinheiten pro Periode
-                 online:  Online-Zeit pro Periode
-
-    amount:      Hoehe des Budgets. Bei <budget-type> 'dial' oder 'charge'
-                 ist das die Anzahl Anwahlen oder Einheiten, bei 'online'
-                 eine Zeitangabe (s.u.)
-
-    period:      Dauer der Periode in folgendem Format (<n> steht fuer eine
-                 natuerliche Zahl):
-
-                 <n>
-                 <n>s
-                 <n>sec,    <n> Sekunden
-
-                 <n>m
-                 <n>min,    <n> Minuten
-
-                 <n>h
-                 <n>hour,   <n> Stunden
-
-                 <n>d
-                 <n>day,    <n> Tage
-
-                 <n>w
-                 <n>week,   <n> Wochen (a 7 Tage)
-
-                 <n>M
-                 <n>month,  <n> Monate (a 30 Tage)
-
-                 <n>y
-                 <n>year,   <n> Jahre (a 365 Tage)
-
-                 Diese Angaben koennen miteinander kombiniert werden, z.B.:
-
-                     2h30m15
-                     2hour,30min,15sec
-                     1M2week,1day,8h
-
-
-isdnctrl budget <name> <budget-type> off
-    schaltet die Kontrolle des entsprechenden Budgets aus
-
-isdnctrl budget <name> showbudgets
-    zeigt die momentaten Budgets an
-
-isdnctrl budget <name> savebudgets
-    gibt die momentaten Budgets in einen Format aus, das vom Befehl 'restore-
-    budgets' wieder eingelesen kann
-
-isdnctrl budget <name> restorebudgets <saved-budget> ...
-    setzt die Budgets wieder auf die vorher mit 'savebudgets' ausgegebenen
-    Werte. Damit koennen Budgets auch ueber den Reboot der Maschine hinaus
-    Gueltigkeit haben.
-
-
-Hier ein Beispiel fuer die TimRu-Erweiterung:
-
-    # Alle Regeln loeschen
-    isdnctrl flushallrules ippp0
-
-    # Default: jeder Datenverkehr setzt den Hangup-Timeout auf 60 Sek.
-    isdnctrl default ippp0 keepup both 60
-
-    # FTP und Telnet erhoehen den Timeout auf 5 Minuten
-    isdnctrl addrule ippp0 keepup both 300 ip/tcp 0/0 20-23 0/0 -
-
-    # Anzeige der Regeln:
-    isdnctrl showrules ippp0
-
-    # ... erzeugt folgende Ausgabe:
-
-Timeout rules for interface ippp0:
-Default bringup policy: true
-Default huptimeout for incoming packets: 60 sec.
-Default huptimeout for outgoing packets: 60 sec.
-
-Current huptimeout: 60 sec.
-Time until hangup: 45 sec.
-
-Keepup-rules for incoming ip-packets:
-1-1-0 keepup_in 300 ip/tcp 0/0 20-23 0/0 * 
-
-Keepup-rules for outgoing ip-packets:
-2-1-0 keepup_out 300 ip/tcp 0/0 * 0/0 20-23 
-
-
-Hier ein Beispiel fuer die Budget-Erweiterung:
-
-    # Hoechstens 60 Anwahlversuche pro Stunde
-    isdnctrl budget ippp0 dial 60 1h
-
-    # Hoechstens 3000 Einheiten pro Monat
-    isdnctrl budget ippp0 charge 3000 1M
-
-    # Hoechstens 8 Stunden online pro Tag
-    isdnctrl budget ippp0 online 8h 1d
-
-    # Anzeige der Budgets:
-    isdnctrl showbudgets ippp0
-
-    # ... erzeugt nach kurzer Zeit folgende Ausgabe:
-
-
-Budgets for interface ippp0:
-
-TYPE    AMOUNT     PERIOD     USED       SINCE
-dial    60         1h         1          01.07.1997, 17:43:40
-charge  3000       1M         2          01.07.1997, 17:43:49
-online  8h         1d         2m26s      01.07.1997, 17:43:57
-
-
-Zum Nachfuehren der Budgets ueber einen laengeren Zeitraum koennte man
-folgende Methode verwenden:
-
-beim Herunterfahren oder per 'cron' jede Minute: 
-
-    INTERFACES="ippp0 ippp1 ippp2"
-    for i in $INTERFACES; do
-        isdnctrl savebudgets $i > /var/isdn/saved-budgets/$i
-    done
-
-
-und dann beim Neustart:
-
-    for f in /var/isdn/saved-budgets/*; do
-        isdnctrl restorebudgets ${f##*/} `cat $f`
-    done
index fe9b129b85de096d6f05edcaa3201a750a3085e6..bcebba70ad6332dbdd783c05f597c1af9bc6b4d7 100644 (file)
@@ -372,7 +372,7 @@ static struct cpu_model_info intel_models[] = {
            NULL, NULL, NULL, NULL }},
        { 6,
          { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)", 
-           NULL, "Pentium II (Deschutes)", NULL, NULL, NULL, NULL, NULL, NULL,
+           NULL, "Pentium II (Deschutes)", "Celeron (Mendocino)", NULL, NULL, NULL, NULL, NULL,
            NULL, NULL, NULL, NULL }},
 };
 
@@ -381,11 +381,21 @@ static const char * Intelmodel(void)
        const char *p = "386 SX/DX";    /* default to a 386 */
        int i;
        
+       /*
+        *      Old 486SX has no CPU ID. Set the model to 2 for this
+        *      case.
+        */
+        
+       if( x86==4 && x86_model == 0 && hard_math == 0)
+               x86_model = 2;
+       
        for (i=0; i<sizeof(intel_models)/sizeof(struct cpu_model_info); i++)
                if (intel_models[i].cpu_x86 == x86) {
                        p = intel_models[i].model_names[(int)x86_model];
                        break;
                }
+       
+       
        return p;
 }
        
@@ -409,16 +419,19 @@ static const char * get_cpu_mkt_name(void)
 }
 
 static const char * getmodel(void)
-/* Default is Intel. We disregard Nexgen and UMC processors. */
+/* Default is Intel. We disregard Nexgen processors. */
 {
         const char *p = NULL;
-       if      (strncmp(x86_vendor_id, "Au", 2) == 0)  /* AuthenticAMD */
+       if      (strcmp(x86_vendor_id, "AuthenticAMD") == 0)    /* AuthenticAMD */
                p = AMDmodel();
-       else if (strncmp(x86_vendor_id, "Cy", 2) == 0)  /* CyrixInstead */
+       else if (strcmp(x86_vendor_id, "CyrixInstead") == 0)    /* CyrixInstead */
                p = Cx86model();
-       else if (strncmp(x86_vendor_id, "Ce", 2) == 0)  /* CentaurHauls */
+       else if (strcmp(x86_vendor_id, "CentaurHauls") == 0)    /* CentaurHauls */
                p = IDTmodel();
-       else /* default */
+       /* This isnt quite right */
+       else if (strcmp(x86_vendor_id, "UMC UMC UMC ") == 0)    /* UMC */
+               p = Intelmodel();
+       else /* default - this could be anyone */
                p = Intelmodel();
        if (ext_cpuid)
                return get_cpu_mkt_name();
@@ -431,7 +444,7 @@ int get_cpuinfo(char * buffer)
         int i, len = 0;
         static const char *x86_cap_flags[] = {
                 "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
-                "cx8", "apic", "10", "11", "mtrr", "pge", "mca", "cmov",
+                "cx8", "apic", "10", "sep", "mtrr", "pge", "mca", "cmov",
                 "16", "17", "18", "19", "20", "21", "22", "mmx",
                 "24", "25", "26", "27", "28", "29", "30", "31"
         };
index 256bec07904976f0e2f8da1212d361d9082fe00b..c82566fab39cc9b77964992490284b9f8e102ee7 100644 (file)
@@ -7,6 +7,9 @@ comment 'Character devices'
 tristate 'Standard/generic serial support' CONFIG_SERIAL
 bool 'Digiboard PC/Xx Support' CONFIG_DIGI
 tristate 'Cyclades async mux support' CONFIG_CYCLADES
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+       dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m
+fi
 bool 'Stallion multiport serial support' CONFIG_STALDRV
 if [ "$CONFIG_STALDRV" = "y" ]; then
   tristate '  Stallion EasyIO or EC8/32 support' CONFIG_STALLION
index db8cad930d01f8eb81f31bc173b168565ad023ac..7a13e826eed25b91505661398d929340b46932ef 100644 (file)
@@ -86,6 +86,14 @@ else
   endif
 endif
 
+ifeq ($(CONFIG_ISI),y)
+L_OBJS += isicom.o
+else
+  ifeq ($(CONFIG_ISI),m)
+  M_OBJS += isicom.o
+  endif
+endif
+
 ifeq ($(CONFIG_ATIXL_BUSMOUSE),y)
 M = y
 L_OBJS += atixlmouse.o
index e466469a573e8c303141bc2a46edfdf5f0646fd3..cddde8b33ae365132d513e802cf9c96a3cf99aa4 100644 (file)
@@ -1,7 +1,7 @@
 #define BLOCKMOVE
 #define        Z_WAKE
 static char rcsid[] =
-"$Revision: 2.1.1.8 $$Date: 1998/08/20 17:04:54 $";
+"$Revision: 2.1.1.9 $$Date: 1998/09/02 14:47:01 $";
 
 /*
  *  linux/drivers/char/cyclades.c
@@ -31,6 +31,11 @@ static char rcsid[] =
  *   void cleanup_module(void);
  *
  * $Log: cyclades.c,v $
+ * Revision 2.1.1.9  1998/09/02 14:47:01 ivan
+ * Fixed bug in cy_close function, which was not informing HW of
+ * which port should have the reception disabled before doing so;
+ * fixed Cyclom-8YoP hardware detection bug.
+ * 
  * Revision 2.1.1.8  1998/08/20 17:04:54 ivan
  * Fixed bug in cy_close function, which causes malfunction
  * of one of the first 4 ports when a higher port is closed
@@ -2741,14 +2746,16 @@ cy_close(struct tty_struct * tty, struct file * filp)
        unsigned char *base_addr = (unsigned char *)
                        (cy_card[info->card].base_addr +
                         (cy_chip_offset[channel>>2] <<index));
-        /* Stop accepting input */
-        cy_writeb((u_long)base_addr+(CySRER<<index),
-                        cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
-        if (info->flags & ASYNC_INITIALIZED) {
-            /* Waiting for on-board buffers to be empty before closing
-               the port */
-            cy_wait_until_sent(tty, info->timeout);
-        }
+       /* Stop accepting input */
+       channel &= 0x03;
+       cy_writeb((ulong)base_addr+(CyCAR<<index), (u_char)channel);
+       cy_writeb((u_long)base_addr+(CySRER<<index),
+                       cy_readb(base_addr+(CySRER<<index)) & ~CyRxData);
+       if (info->flags & ASYNC_INITIALIZED) {
+           /* Waiting for on-board buffers to be empty before closing
+              the port */
+           cy_wait_until_sent(tty, info->timeout);
+       }
     } else {
 #ifdef Z_WAKE
        /* Waiting for on-board buffers to be empty before closing the port */
@@ -4699,7 +4706,7 @@ cy_detect_pci(void))
   unsigned long         pci_intr_ctrl;
   unsigned char         cy_pci_irq;
   uclong                cy_pci_addr0, cy_pci_addr1, cy_pci_addr2;
-  unsigned short        i,j,cy_pci_nchan;
+  unsigned short        i,j,cy_pci_nchan, plx_ver;
   unsigned short        device_id,dev_index = 0,board_index = 0;
   uclong               mailbox;
   uclong               Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0;
@@ -4823,11 +4830,27 @@ cy_detect_pci(void))
                 cy_card[j].num_chips = cy_pci_nchan/4;
                 IRQ_cards[cy_pci_irq] = &cy_card[j];
 
-                /* enable interrupts in the PCI interface */
-                outw(inw(cy_pci_addr1+0x68)|0x0900,cy_pci_addr1+0x68);
-                pci_intr_ctrl = (unsigned long)
-                               (inw(cy_pci_addr1+0x68)
+               /* enable interrupts in the PCI interface */
+               plx_ver = cy_readb(cy_pci_addr2 + CyPLX_VER) & 0x0f;
+                switch (plx_ver) {
+                   case PLX_9050:
+
+                   outw(inw(cy_pci_addr1+0x4c)|0x0040,cy_pci_addr1+0x4c);
+                   pci_intr_ctrl = (unsigned long)
+                               (inw(cy_pci_addr1+0x4c)
+                               | inw(cy_pci_addr1+0x4e)<<16);
+                   break;
+
+                   case PLX_9060:
+                   case PLX_9080:
+                   default: /* Old boards, use PLX_9060 */
+
+                   outw(inw(cy_pci_addr1+0x68)|0x0900,cy_pci_addr1+0x68);
+                   pci_intr_ctrl = (unsigned long)
+                               (inw(cy_pci_addr1+0x68)
                                | inw(cy_pci_addr1+0x6a)<<16);
+                   break;
+                }
 
                 /* print message */
                 printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ",
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
new file mode 100644 (file)
index 0000000..de2383c
--- /dev/null
@@ -0,0 +1,1928 @@
+/*
+ *     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.
+ *
+ *     Original driver code supplied by Multi-Tech
+ *
+ *     Changes
+ *     1/9/98  alan@redhat.com         Merge to 2.0.x kernel tree
+ *                                     Obtain and use official major/minors
+ *                                     Loader switched to a misc device
+ *                                     (fixed range check bug as a side effect)
+ *                                     Printk clean up
+ */
+
+#include <linux/config.h> 
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/termios.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include "isicom.h"
+
+static int isicom_refcount = 0;
+static int prev_card = 3;      /*      start servicing isi_card[0]     */
+static struct isi_board * irq_to_board[16] = { NULL, };
+static struct tty_driver isicom_normal, isicom_callout;
+static struct tty_struct * isicom_table[PORT_COUNT] = { NULL, };
+static struct termios * isicom_termios[PORT_COUNT] = { NULL, };
+static struct termios * isicom_termios_locked[PORT_COUNT] = { NULL, };
+
+static struct isi_board isi_card[BOARD_COUNT];
+static struct isi_port  isi_ports[PORT_COUNT];
+
+DECLARE_TASK_QUEUE(tq_isicom);
+
+static struct timer_list tx;
+static char re_schedule = 1;
+#ifdef ISICOM_DEBUG
+unsigned long tx_count = 0;
+#endif
+
+static int ISILoad_open(struct inode *inode, struct file *filp);
+static void ISILoad_release(struct inode *inode, struct file *filp);
+static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned  int cmd, unsigned long arg);
+
+static void isicom_tx(unsigned long _data);
+static void isicom_start(struct tty_struct * tty);
+
+static unsigned char * tmp_buf = 0;
+static struct semaphore tmp_buf_sem = MUTEX;
+
+/*   baud index mappings from linux defns to isi */
+
+static char linuxb_to_isib[] = {
+       -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,     
+       18, 19
+};
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static struct file_operations ISILoad_fops = {
+       NULL,   /*      lseek   */
+       NULL,   /*      read    */
+       NULL,   /*      write   */
+       NULL,   /*      readdir */
+       NULL,   /*      select  */
+       ISILoad_ioctl,
+       NULL,   /*      mmap    */
+       ISILoad_open,
+       ISILoad_release,
+       NULL,   /*      fsync   */
+       NULL,   /*      fasync  */
+       NULL,   /*      check_media_change      */
+       NULL,   /*      revalidate      */
+};
+
+struct miscdevice isiloader_device = {
+       ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
+};
+
+extern inline int WaitTillCardIsFree(unsigned short base)
+{
+       unsigned long count=0;
+       while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
+       if (inw(base+0xe)&0x1)  
+               return 0;
+       else
+               return 1;
+}
+
+static int ISILoad_open(struct inode *inode, struct file *filp)
+{
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISILoad:Card%d Opened!!!\n",MINOR(inode->i_rdev)+1);
+#endif 
+       return 0;
+}
+
+static void ISILoad_release(struct inode *inode, struct file *filp)
+{
+#ifdef ISICOM_DEBUG
+       printk(KERN_DEBUG "ISILoad:Card%d Close(Release)d\n",MINOR(inode->i_rdev)+1);
+#endif 
+}
+
+static int ISILoad_ioctl(struct inode *inode, struct file *filp,
+                        unsigned int cmd, unsigned long arg)
+{
+       unsigned int card, i, j, signature, status;
+       unsigned short error, word_count, base;
+       bin_frame frame;
+       /* exec_record exec_rec; */
+       
+       i=get_user((int *)arg);
+       if(i<0 || i >= BOARD_COUNT)
+               return -ENXIO;
+               
+       card=i;
+       base=isi_card[card].base;
+       
+       if(base==0)
+               return -ENXIO;
+       
+       switch(cmd) {
+               case MIOCTL_RESET_CARD:
+                       if (!suser())
+                               return -EPERM;
+                       error=verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
+                       if (error)
+                               return error;
+                               
+                       printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
+                                                               
+                       inw(base+0x8);
+                       
+                       for(i=jiffies+HZ/100;i>jiffies;);
+                               
+                       outw(0,base+0x8); /* Reset */
+                       
+                       for(j=1;j<=3;j++) {
+                               for(i=jiffies+HZ;i>jiffies;);
+                               printk(".");
+                       }       
+                       signature=(inw(base+0x4)) & 0xff;       
+                               
+                       if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
+#ifdef ISICOM_DEBUG                            
+                               printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
+#endif                         
+                               printk("\nISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+                               return -EIO;                                    
+                       }
+                               
+                       switch(signature) {
+                       case    0xa5:
+                       case    0xbb:
+                       case    0xdd:   isi_card[card].port_count = 8;
+                                       isi_card[card].shift_count = 12;
+                                       break;
+                                       
+                       case    0xcc:   isi_card[card].port_count = 16;
+                                       isi_card[card].shift_count = 11;
+                                       break;                          
+                                       
+                       default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+#ifdef ISICOM_DEBUG                    
+                                printk("Sig=0x%x\n",signature);
+#endif                          
+                                return -EIO;
+                       }
+                       printk("-Done\n");
+                       put_user(signature,(unsigned int*)arg);
+                       return 0;
+                                               
+       case    MIOCTL_LOAD_FIRMWARE:
+                       if (!suser())
+                               return -EPERM;
+                       error=verify_area(VERIFY_READ, (void *) arg, sizeof(bin_frame));
+                       if (error)
+                               return error;
+                               
+                       memcpy_fromfs(&frame, (void *) arg, sizeof(bin_frame));
+                       
+                       if (WaitTillCardIsFree(base))
+                               return -EIO;
+                       
+                       outw(0xf0,base);        /* start upload sequence */ 
+                       outw(0x00,base);
+                       outw((frame.addr), base);/*      lsb of adderess    */
+                       
+                       word_count=(frame.count >> 1) + frame.count % 2;
+                       outw(word_count, base);
+                       InterruptTheCard(base);
+                       
+                       for(i=0;i<=0x2f;i++);   /* a wee bit of delay */
+                       
+                       if (WaitTillCardIsFree(base)) 
+                               return -EIO;
+                               
+                       if ((status=inw(base+0x4))!=0) {
+                               printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
+                               card+1, frame.addr, frame.count, status);
+                               return -EIO;
+                       }
+                       outsw(base, (void *) frame.bin_data, word_count);
+                       
+                       InterruptTheCard(base);
+                       
+                       for(i=0;i<=0x0f;i++);   /* another wee bit of delay */ 
+                       
+                       if (WaitTillCardIsFree(base)) 
+                               return -EIO;
+                               
+                       if ((status=inw(base+0x4))!=0) {
+                               printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
+                               return -EIO;
+                       }       
+                       return 0;
+                                               
+       case    MIOCTL_READ_FIRMWARE:
+                       if (!suser())
+                               return -EPERM;
+                       error=verify_area(VERIFY_READ, (void *) arg, sizeof(bin_header));
+                       if (error)
+                               return error;
+                               
+                       memcpy_fromfs(&frame, (void *) arg, sizeof(bin_header));
+                       
+                       if (WaitTillCardIsFree(base))
+                               return -EIO;
+                       
+                       outw(0xf1,base);        /* start download sequence */ 
+                       outw(0x00,base);
+                       outw((frame.addr), base);/*      lsb of adderess    */
+                       
+                       word_count=(frame.count >> 1) + frame.count % 2;
+                       outw(word_count+1, base);
+                       InterruptTheCard(base);
+                       
+                       for(i=0;i<=0xf;i++);    /* a wee bit of delay */
+                       
+                       if (WaitTillCardIsFree(base)) 
+                               return -EIO;
+                               
+                       if ((status=inw(base+0x4))!=0) {
+                               printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
+                               card+1, frame.addr, frame.count, status);
+                               return -EIO;
+                       }
+                       
+                       inw(base);
+                       insw(base, frame.bin_data, word_count);
+                       InterruptTheCard(base);
+                       
+                       for(i=0;i<=0x0f;i++);   /* another wee bit of delay */ 
+                       
+                       if (WaitTillCardIsFree(base)) 
+                               return -EIO;
+                               
+                       if ((status=inw(base+0x4))!=0) {
+                               printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
+                               return -EIO;
+                       }       
+                       error=verify_area(VERIFY_WRITE, (void *) arg, sizeof(bin_frame));
+                       if (error)
+                               return error;
+                       memcpy_tofs((void *) arg, &frame, sizeof(bin_frame));   
+                       
+                       return 0;
+       
+       case    MIOCTL_XFER_CTRL:
+                       if (!suser())
+                               return -EPERM;
+                       if (WaitTillCardIsFree(base)) 
+                               return -EIO;
+                                       
+                       outw(0xf2, base);
+                       outw(0x800, base);
+                       outw(0x0, base);
+                       outw(0x0, base);
+                       InterruptTheCard(base);
+                       
+                       isi_card[card].status |= FIRMWARE_LOADED;
+                       return 0;       
+                       
+       default:
+#ifdef ISICOM_DEBUG    
+               printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd); 
+#endif
+               return -ENOIOCTLCMD;
+       
+       }
+       
+}
+                               
+
+/*
+ *     ISICOM Driver specific routines ...
+ *
+ */
+static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev, 
+                                       const char * routine)
+{
+#ifdef ISICOM_DEBUG 
+       static const char * badmagic = 
+                       KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
+       static const char * badport = 
+                       KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";           
+       if (!port) {
+               printk(badport, kdevname(dev), routine);
+               return 1;
+       }
+       if (port->magic != ISICOM_MAGIC) {
+               printk(badmagic, kdevname(dev), routine);
+               return 1;
+       }       
+#endif 
+       return 0;
+}
+                       
+extern inline void schedule_bh(struct isi_port * port)
+{
+       queue_task_irq_off(&port->bh_tqueue, &tq_isicom);
+       mark_bh(ISICOM_BH);
+} 
+
+/*     Transmitter     */
+
+static void isicom_tx(unsigned long _data)
+{
+       short count = (BOARD_COUNT-1), card, base;
+       short txcount, wait, wrd;
+       struct isi_port * port;
+       struct tty_struct * tty;
+       unsigned long flags;
+       
+#ifdef ISICOM_DEBUG
+       ++tx_count;
+#endif 
+       
+       /*      find next active board  */
+       card = (prev_card + 1) % 4;
+       while(count-- > 0) {
+               if (isi_card[card].status & BOARD_ACTIVE) 
+                       break;
+               card = (card + 1) % 4;  
+       }
+       if (!(isi_card[card].status & BOARD_ACTIVE))
+               goto sched_again;
+               
+       prev_card = card;
+       
+       count = isi_card[card].port_count;
+       port = isi_card[card].ports;
+       base = isi_card[card].base;
+       for (;count > 0;count--, port++) {
+               /* port not active or tx disabled to force flow control */
+               if (!(port->status & ISI_TXOK))
+                       continue;
+               
+               tty = port->tty;
+               save_flags(flags); cli();
+               txcount = MIN(TX_SIZE, port->xmit_cnt);
+               if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
+                       restore_flags(flags);
+                       continue;
+               }
+               wait = 300;     
+               while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+               if (wait <= 0) {
+                       restore_flags(flags);
+#ifdef ISICOM_DEBUG
+                       printk(KERN_DEBUG "ISICOM: isicom_tx:Card(0x%x) found busy.\n",
+                               card);
+#endif
+                       continue;
+               }
+               if (!(inw(base + 0x02) & (1 << port->channel))) {
+                       restore_flags(flags);
+#ifdef ISICOM_DEBUG                                    
+                       printk(KERN_DEBUG "ISICOM: isicom_tx: cannot tx to 0x%x:%d.\n",
+                                       base, port->channel + 1);
+#endif                                 
+                       continue;               
+               }
+#ifdef ISICOM_DEBUG
+               printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n", 
+                               txcount, port->channel+1); 
+#endif 
+               outw((port->channel << isi_card[card].shift_count) | txcount
+                                       , base);
+               while (1) {
+                       wrd = port->xmit_buf[port->xmit_tail++];
+                       port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+                       port->xmit_cnt--;
+                       if (--txcount > 0) {
+                               wrd |= (port->xmit_buf[port->xmit_tail++] << 8);
+                               port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+                               port->xmit_cnt--;
+                               outw(wrd, base);
+                               if (--txcount <= 0) break;
+                       }
+                       else {
+                               outw(wrd, base);
+                               break;
+                       }
+               }
+               InterruptTheCard(base);
+               if (port->xmit_cnt <= 0)
+                       port->status &= ~ISI_TXOK;
+               if (port->xmit_cnt <= WAKEUP_CHARS)
+                       schedule_bh(port);
+               restore_flags(flags);
+       }       
+
+               /*      schedule another tx for hopefully in about 10ms */      
+sched_again:   
+       if (!re_schedule)       
+               return;
+       init_timer(&tx);
+       tx.expires = jiffies + 1;
+       tx.data = 0;
+       tx.function = isicom_tx;
+       add_timer(&tx);
+       
+       return; 
+}              
+               /*      Interrupt handlers      */
+static void do_isicom_bh(void)
+{
+       run_task_queue(&tq_isicom);
+}
+
+
+static void isicom_bottomhalf(void * data)
+{
+       struct isi_port * port = (struct isi_port *) data;
+       struct tty_struct * tty = port->tty;
+       
+       if (!tty)
+               return;
+       
+       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+           tty->ldisc.write_wakeup)
+               (tty->ldisc.write_wakeup)(tty);
+       wake_up_interruptible(&tty->write_wait);
+}              
+               
+/* main interrupt handler routine */           
+static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+       struct isi_board * card;
+       struct isi_port * port;
+       struct tty_struct * tty;
+       unsigned short base, header, word_count, count;
+       unsigned char channel;
+       short byte_count;
+       
+       card = irq_to_board[irq];
+       if (!card || !(card->status & FIRMWARE_LOADED)) {
+               printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);
+               return;
+       }
+       base = card->base;
+       
+       inw(base);              /* get the dummy word out */
+       header = inw(base);
+       channel = (header & 0x7800) >> card->shift_count;
+       byte_count = header & 0xff;
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM:Intr:(0x%x:%d).\n", base, channel+1);
+#endif 
+       if ((channel+1) > card->port_count) {
+               printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
+                               base, channel+1);
+               ClearInterrupt(base);           
+               return;                 
+       }
+       port = card->ports + channel;
+       if (!(port->flags & ASYNC_INITIALIZED)) {
+               ClearInterrupt(base);
+               return;
+       }       
+               
+       tty = port->tty;
+       
+       if (header & 0x8000) {          /* Status Packet */
+               header = inw(base);
+               switch(header & 0xff) {
+                       case 0: /* Change in EIA signals */
+                               
+                               if (port->flags & ASYNC_CHECK_CD) {
+                                       if (port->status & ISI_DCD) {
+                                               if (!(header & ISI_DCD)) {
+                                               /* Carrier has been lost  */
+#ifdef ISICOM_DEBUG                                            
+                                                       printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
+#endif                                                 
+                                                       port->status &= ~ISI_DCD;
+                                                       if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+                                                               (port->flags & ASYNC_CALLOUT_NOHUP)))
+                                                               queue_task_irq_off(&port->hangup_tq,
+                                                                       &tq_scheduler);
+                                               }
+                                       }
+                                       else {
+                                               if (header & ISI_DCD) {
+                                               /* Carrier has been detected */
+#ifdef ISICOM_DEBUG
+                                                       printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
+#endif                                                 
+                                                       port->status |= ISI_DCD;
+                                                       wake_up_interruptible(&port->open_wait);
+                                               }
+                                       }
+                               }
+                               else {
+                                       if (header & ISI_DCD) 
+                                               port->status |= ISI_DCD;
+                                       else
+                                               port->status &= ~ISI_DCD;
+                               }       
+                               
+                               if (port->flags & ASYNC_CTS_FLOW) {
+                                       if (port->tty->hw_stopped) {
+                                               if (header & ISI_CTS) {
+                                                       port->tty->hw_stopped = 0;
+                                                       /* start tx ing */
+                                                       port->status |= (ISI_TXOK | ISI_CTS);
+                                                       schedule_bh(port);
+                                               }
+                                       }
+                                       else {
+                                               if (!(header & ISI_CTS)) {
+                                                       port->tty->hw_stopped = 1;
+                                                       /* stop tx ing */
+                                                       port->status &= ~(ISI_TXOK | ISI_CTS);
+                                               }
+                                       }
+                               }
+                               else {
+                                       if (header & ISI_CTS) 
+                                               port->status |= ISI_CTS;
+                                       else
+                                               port->status &= ~ISI_CTS;
+                               }
+                               
+                               if (header & ISI_DSR) 
+                                       port->status |= ISI_DSR;
+                               else
+                                       port->status &= ~ISI_DSR;
+                               
+                               if (header & ISI_RI) 
+                                       port->status |= ISI_RI;
+                               else
+                                       port->status &= ~ISI_RI;                                                
+                               
+                               break;
+                               
+                       case 1: /* Received Break !!!    */
+                               if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+                                       break;
+                               *tty->flip.flag_buf_ptr++ = TTY_BREAK;
+                               /* dunno if this is right */    
+                               *tty->flip.char_buf_ptr++ = 0;
+                               tty->flip.count++;
+                               if (port->flags & ASYNC_SAK)
+                                       do_SAK(tty);
+                               queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+                               break;
+                               
+                       case 2: /* Statistics            */
+                               printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");                     
+                               break;
+                               
+                       default:
+                               printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
+                               break;
+               }        
+       }
+       else {                          /* Data   Packet */
+               count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
+#ifdef ISICOM_DEBUG
+               printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
+                                       count, byte_count);
+#endif                 
+               word_count = count >> 1;
+               insw(base, tty->flip.char_buf_ptr, word_count);
+               tty->flip.char_buf_ptr += (word_count << 1);            
+               byte_count -= (word_count << 1);
+               if (count % 2) {
+                       *tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
+                       byte_count -= 2;
+               }       
+               memset(tty->flip.flag_buf_ptr, 0, count);
+               tty->flip.flag_buf_ptr += count;
+               tty->flip.count += count;
+               
+               if (byte_count > 0)
+                       printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
+                                       base, channel+1);
+               while(byte_count > 0) { /* drain out unread xtra data */
+                       inw(base);
+                       byte_count -= 2;
+               }
+               queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+       }
+       ClearInterrupt(base);
+       return;
+} 
+
+ /* called with interrupts disabled */ 
+static void isicom_config_port(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       struct tty_struct * tty;
+       unsigned long baud;
+       unsigned short channel_setup, wait, base = card->base;
+       unsigned short channel = port->channel, shift_count = card->shift_count;
+       unsigned char flow_ctrl;
+       
+       if (!(tty = port->tty) || !tty->termios)
+               return;
+       baud = C_BAUD(tty);
+       if (baud & CBAUDEX) {
+               baud &= ~CBAUDEX;
+               
+               /*  if CBAUDEX bit is on and the baud is set to either 50 or 75
+                *  then the card is programmed for 57.6Kbps or 115Kbps
+                *  respectively.
+                */   
+                
+               if (baud < 1 || baud > 2)
+                       port->tty->termios->c_cflag &= ~CBAUDEX;
+               else
+                       baud += 15;
+       }       
+       if (baud == 15) {
+       
+               /*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set 
+                *  by the set_serial_info ioctl ... this is done by
+                *  the 'setserial' utility.
+                */  
+                       
+               if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+                       baud++;     /*  57.6 Kbps */
+               if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+                       baud +=2;   /*  115  Kbps */     
+       }
+       if (linuxb_to_isib[baud] == -1) {
+               /* hang up */
+               drop_dtr(port);
+               return;
+       }       
+       else  
+               raise_dtr(port);
+               
+       wait = 100;     
+       while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));     
+       if (!wait) {
+               printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at channel setup.\n");
+               return;
+       }                        
+       outw(0x8000 | (channel << shift_count) |0x03, base);
+       outw(linuxb_to_isib[baud] << 8 | 0x03, base);
+       channel_setup = 0;
+       switch(C_CSIZE(tty)) {
+               case CS5:
+                       channel_setup |= ISICOM_CS5;
+                       break;
+               case CS6:
+                       channel_setup |= ISICOM_CS6;
+                       break;
+               case CS7:
+                       channel_setup |= ISICOM_CS7;
+                       break;
+               case CS8:
+                       channel_setup |= ISICOM_CS8;
+                       break;
+       }
+               
+       if (C_CSTOPB(tty))
+               channel_setup |= ISICOM_2SB;
+       
+       if (C_PARENB(tty))
+               channel_setup |= ISICOM_EVPAR;
+       if (C_PARODD(tty))
+               channel_setup |= ISICOM_ODPAR;  
+       outw(channel_setup, base);      
+       InterruptTheCard(base);
+       
+       if (C_CLOCAL(tty))
+               port->flags &= ~ASYNC_CHECK_CD;
+       else
+               port->flags |= ASYNC_CHECK_CD;  
+       
+       /* flow control settings ...*/
+       flow_ctrl = 0;
+       port->flags &= ~ASYNC_CTS_FLOW;
+       if (C_CRTSCTS(tty)) {
+               port->flags |= ASYNC_CTS_FLOW;
+               flow_ctrl |= ISICOM_CTSRTS;
+       }       
+       if (I_IXON(tty))        
+               flow_ctrl |= ISICOM_RESPOND_XONXOFF;
+       if (I_IXOFF(tty))
+               flow_ctrl |= ISICOM_INITIATE_XONXOFF;   
+               
+       wait = 100;     
+       while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));     
+       if (!wait) {
+               printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at flow setup.\n");
+               return;
+       }                        
+       outw(0x8000 | (channel << shift_count) |0x04, base);
+       outw(flow_ctrl << 8 | 0x05, base);
+       outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
+       InterruptTheCard(base);
+       
+       /*      rx enabled -> enable port for rx on the card    */
+       if (C_CREAD(tty)) {
+               card->port_status |= (1 << channel);
+               outw(card->port_status, base + 0x02);
+       }
+               
+}
+/* open et all */ 
+
+extern inline void isicom_setup_board(struct isi_board * bp)
+{
+       int channel;
+       struct isi_port * port;
+       unsigned long flags;
+       
+       if (bp->status & BOARD_ACTIVE) 
+               return;
+       port = bp->ports;
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts start, port_count %d...\n", bp->port_count);
+#endif
+       for(channel = 0; channel < bp->port_count; channel++, port++) {
+               save_flags(flags); cli();
+               drop_dtr_rts(port);
+               restore_flags(flags);
+       }
+#ifdef ISICOM_DEBUG            
+       printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts stop...\n");       
+#endif 
+       
+       bp->status |= BOARD_ACTIVE;
+       MOD_INC_USE_COUNT;
+       return;
+}
+static int isicom_setup_port(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       unsigned long flags;
+       
+       if (port->flags & ASYNC_INITIALIZED)
+               return 0;
+       if (!port->xmit_buf) {
+               unsigned long page;
+               
+               if (!(page = get_free_page(GFP_KERNEL)))
+                       return -ENOMEM;
+               
+               if (port->xmit_buf) {
+                       free_page(page);
+                       return -ERESTARTSYS;
+               }
+               port->xmit_buf = (unsigned char *) page;        
+       }       
+       save_flags(flags); cli();
+       if (port->tty)
+               clear_bit(TTY_IO_ERROR, &port->tty->flags);
+       if (port->count == 1)
+               card->count++;
+               
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       
+       /*      discard any residual data       */
+       kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
+       
+       isicom_config_port(port);
+       port->flags |= ASYNC_INITIALIZED;
+       
+       restore_flags(flags);
+       
+       return 0;               
+} 
+static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
+{
+       int do_clocal = 0, retval;
+       struct wait_queue wait = { current, NULL };
+
+       /* block if port is in the process of being closed */
+
+       if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+#ifdef ISICOM_DEBUG    
+               printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
+#endif         
+               interruptible_sleep_on(&port->close_wait);
+               if (port->flags & ASYNC_HUP_NOTIFY)
+                       return -EAGAIN;
+               else
+                       return -ERESTARTSYS;
+       }
+       
+       /* trying to open a callout device... check for constraints */
+       
+       if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+#ifdef ISICOM_DEBUG
+               printk(KERN_DEBUG "ISICOM: bl_ti_rdy: callout open.\n");        
+#endif         
+               if (port->flags & ASYNC_NORMAL_ACTIVE)
+                       return -EBUSY;
+               if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+                   (port->flags & ASYNC_SESSION_LOCKOUT) &&
+                   (port->session != current->session))
+                       return -EBUSY;
+                       
+               if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+                   (port->flags & ASYNC_PGRP_LOCKOUT) &&
+                   (port->pgrp != current->pgrp))
+                       return -EBUSY;
+               port->flags |= ASYNC_CALLOUT_ACTIVE;
+               cli();
+               raise_dtr_rts(port);
+               sti();
+               return 0;
+       }
+       
+       /* if non-blocking mode is set ... */
+       
+       if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+#ifdef ISICOM_DEBUG    
+               printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
+#endif         
+               if (port->flags & ASYNC_CALLOUT_ACTIVE)
+                       return -EBUSY;
+               port->flags |= ASYNC_NORMAL_ACTIVE;
+               return 0;       
+       }       
+       
+       if (port->flags & ASYNC_CALLOUT_ACTIVE) {
+               if (port->normal_termios.c_cflag & CLOCAL)
+                       do_clocal = 1; 
+       } else {
+               if (C_CLOCAL(tty))
+                       do_clocal = 1;
+       }
+#ifdef ISICOM_DEBUG    
+       if (do_clocal)
+               printk(KERN_DEBUG "ISICOM: block_til_ready: CLOCAL set.\n");
+#endif                 
+       
+       /* block waiting for DCD to be asserted, and while 
+                                               callout dev is busy */
+       retval = 0;
+       add_wait_queue(&port->open_wait, &wait);
+       cli();
+               if (!tty_hung_up_p(filp))
+                       port->count--;
+       sti();
+       port->blocked_open++;
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: block_til_ready: waiting for DCD...\n");
+#endif 
+       while (1) {
+               cli();
+               if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) 
+                       raise_dtr_rts(port);
+               
+               sti();
+               current->state = TASK_INTERRUPTIBLE;
+               if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) {        
+                       if (port->flags & ASYNC_HUP_NOTIFY)
+                               retval = -EAGAIN;
+                       else
+                               retval = -ERESTARTSYS;
+#ifdef ISICOM_DEBUG                            
+                       printk(KERN_DEBUG "ISICOM: block_til_ready: tty_hung_up_p || not init.\n"); 
+#endif                 
+                       break;
+               }       
+               if (!(port->flags & ASYNC_CALLOUT_ACTIVE) &&
+                   !(port->flags & ASYNC_CLOSING) &&
+                   (do_clocal || (port->status & ISI_DCD))) {
+#ifdef ISICOM_DEBUG                
+                       printk(KERN_DEBUG "ISICOM: block_til_ready: do_clocal || DCD.\n");   
+#endif                 
+                       break;
+               }       
+               if (current->signal & ~current->blocked) {
+#ifdef ISICOM_DEBUG            
+                       printk(KERN_DEBUG "ISICOM: block_til_ready: sig blocked.\n");
+#endif                 
+                       retval = -ERESTARTSYS;
+                       break;
+               }
+               schedule();             
+       }
+       current->state = TASK_RUNNING;
+       remove_wait_queue(&port->open_wait, &wait);
+       if (!tty_hung_up_p(filp))
+               port->count++;
+       port->blocked_open--;
+       if (retval)
+               return retval;
+       port->flags |= ASYNC_NORMAL_ACTIVE;
+       return 0;
+}
+static int isicom_open(struct tty_struct * tty, struct file * filp)
+{
+       struct isi_port * port;
+       struct isi_board * card;
+       unsigned int line, board;
+       unsigned long flags;
+       int error;
+
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: open start!!!.\n");
+#endif 
+       line = MINOR(tty->device) - tty->driver.minor_start;
+       
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "line = %d.\n", line);
+#endif 
+       
+       if ((line < 0) || (line > (PORT_COUNT-1)))
+               return -ENODEV;
+       board = BOARD(line);
+       
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "board = %d.\n", board);
+#endif 
+       
+       card = &isi_card[board];
+       if (!(card->status & FIRMWARE_LOADED)) {
+#ifdef ISICOM_DEBUG    
+               printk(KERN_DEBUG"ISICOM: Firmware not loaded to card%d.\n", board);
+#endif         
+               return -ENODEV;
+       }
+       
+       /*  open on higher 8 dev files on a 8 port card !!! */
+       if (card->port_count == 8) 
+               if (line > ((board * 16)+7)) {
+                       printk(KERN_ERR "ISICOM: Opened >8 on a 8 port card.\n");
+                       return -ENODEV;
+               }       
+       port = &isi_ports[line];        
+       if (isicom_paranoia_check(port, tty->device, "isicom_open"))
+               return -ENODEV;
+               
+#ifdef ISICOM_DEBUG            
+       printk(KERN_DEBUG "ISICOM: isicom_setup_board ...\n");          
+#endif 
+       isicom_setup_board(card);               
+       
+       port->count++;
+       tty->driver_data = port;
+       port->tty = tty;
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: isicom_setup_port ...\n");
+#endif 
+       if ((error = isicom_setup_port(port))!=0)
+               return error;
+#ifdef ISICOM_DEBUG            
+       printk(KERN_DEBUG "ISICOM: block_til_ready ...\n");     
+#endif 
+       if ((error = block_til_ready(tty, filp, port))!=0)
+               return error;
+               
+       if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
+               if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+                       *tty->termios = port->normal_termios;
+               else 
+                       *tty->termios = port->callout_termios;
+               save_flags(flags); cli();
+               isicom_config_port(port);
+               restore_flags(flags);           
+       }       
+       
+       port->session = current->session;       
+       port->pgrp = current->pgrp;
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: open end!!!.\n");
+#endif 
+       return 0;               
+}
+/* close et all */
+
+extern inline void isicom_shutdown_board(struct isi_board * bp)
+{
+       int channel;
+       struct isi_port * port;
+       
+       if (!(bp->status & BOARD_ACTIVE))
+               return;
+       bp->status &= ~BOARD_ACTIVE;
+       port = bp->ports;
+       for(channel = 0; channel < bp->port_count; channel++, port++) {
+               drop_dtr_rts(port);
+       }       
+       MOD_DEC_USE_COUNT;
+}
+
+static void isicom_shutdown_port(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       struct tty_struct * tty;        
+       
+       if (!(port->flags & ASYNC_INITIALIZED))
+               return;
+       if (port->xmit_buf) {
+               free_page((unsigned long) port->xmit_buf);
+               port->xmit_buf = NULL;
+       }       
+       if (!(tty = port->tty) || C_HUPCL(tty)) 
+               /* drop dtr on this port */
+               drop_dtr(port);
+               
+       /* any other port uninits  */ 
+       
+       if (tty)
+               set_bit(TTY_IO_ERROR, &tty->flags);
+       port->flags &= ~ASYNC_INITIALIZED;
+       
+       if (--card->count < 0) {
+               printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
+                       card->base, card->count);
+               card->count = 0;        
+       }
+       
+       /* last port was closed , shutdown that boad too */
+       if (!card->count)
+               isicom_shutdown_board(card);
+}
+
+static void isicom_close(struct tty_struct * tty, struct file * filp)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       struct isi_board * card = port->card;
+       unsigned long flags;
+       
+       if (!port)
+               return;
+       if (isicom_paranoia_check(port, tty->device, "isicom_close"))
+               return;
+       
+#ifdef ISICOM_DEBUG            
+       printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
+#endif 
+       
+       save_flags(flags); cli();
+       if (tty_hung_up_p(filp)) {
+               restore_flags(flags);
+               return;
+       }
+       
+       if ((tty->count == 1) && (port->count != 1)) {
+               printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
+                       "tty->count = 1 port count = %d.\n",
+                       card->base, port->count);
+               port->count = 1;
+       }
+       if (--port->count < 0) {
+               printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
+                       "channel%d = %d", card->base, port->channel, 
+                       port->count);
+               port->count = 0;        
+       }
+       
+       if (port->count) {
+               restore_flags(flags);
+               return;
+       }       
+       port->flags |= ASYNC_CLOSING;
+       /* 
+        * save termios struct since callout and dialin termios may be 
+        * different.
+        */     
+       if (port->flags & ASYNC_NORMAL_ACTIVE)
+               port->normal_termios = *tty->termios;
+       if (port->flags & ASYNC_CALLOUT_ACTIVE)
+               port->callout_termios = *tty->termios;
+       
+       tty->closing = 1;
+       if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+               tty_wait_until_sent(tty, port->closing_wait);
+       /* indicate to the card that no more data can be received 
+          on this port */
+       if (port->flags & ASYNC_INITIALIZED) {   
+               card->port_status &= ~(1 << port->channel);
+               outw(card->port_status, card->base + 0x02);
+       }       
+       isicom_shutdown_port(port);
+       if (tty->driver.flush_buffer)
+               tty->driver.flush_buffer(tty);
+       if (tty->ldisc.flush_buffer)
+               tty->ldisc.flush_buffer(tty);
+       tty->closing = 0;
+       port->tty = 0;
+       if (port->blocked_open) {
+               if (port->close_delay) {
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + port->close_delay;
+#ifdef ISICOM_DEBUG                    
+                       printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
+#endif                 
+                       schedule();
+               }
+               wake_up_interruptible(&port->open_wait);
+       }       
+       port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | 
+                       ASYNC_CLOSING);
+       wake_up_interruptible(&port->close_wait);
+       restore_flags(flags);
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: Close end!!!.\n");
+#endif 
+}
+
+/* write et all */
+static int isicom_write(struct tty_struct * tty, int from_user,
+                       const unsigned char * buf, int count)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       unsigned long flags;
+       int cnt, total = 0;
+#ifdef ISICOM_DEBUG
+       printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
+                       port->channel+1, count);
+#endif         
+       if (isicom_paranoia_check(port, tty->device, "isicom_write"))
+               return 0;
+       
+       if (!tty || !port->xmit_buf || !tmp_buf)
+               return 0;
+       if (from_user)
+               down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
+               
+       save_flags(flags);
+       while(1) {      
+               cli();
+               cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                       SERIAL_XMIT_SIZE - port->xmit_head));
+               if (cnt <= 0) 
+                       break;
+               
+               if (from_user) {
+                       /* the following may block for paging... hence 
+                          enabling interrupts but tx routine may have 
+                          created more space in xmit_buf when the ctrl 
+                          gets back here 
+                       sti(); */
+                       memcpy_fromfs(tmp_buf, buf, cnt);
+/*                     cli();*/
+                       cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+                       SERIAL_XMIT_SIZE - port->xmit_head));
+                       memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
+               }       
+               else
+                       memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
+               port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+               port->xmit_cnt += cnt;
+               restore_flags(flags);
+               buf += cnt;
+               count -= cnt;
+               total += cnt;
+       }               
+       if (from_user)
+               up(&tmp_buf_sem);
+       if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
+               port->status |= ISI_TXOK;
+       restore_flags(flags);
+#ifdef ISICOM_DEBUG
+       printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.\n", total);
+#endif         
+       return total;   
+}
+
+/* put_char et all */
+static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       unsigned long flags;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
+               return;
+       
+       if (!tty || !port->xmit_buf)
+               return;
+#ifdef ISICOM_DEBUG
+       printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
+#endif                 
+               
+       save_flags(flags); cli();
+       
+       if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
+               restore_flags(flags);
+               return;
+       }
+       
+       port->xmit_buf[port->xmit_head++] = ch;
+       port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
+       port->xmit_cnt++;
+       restore_flags(flags);
+}
+
+/* flush_chars et all */
+static void isicom_flush_chars(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_flush_chars"))
+               return;
+       
+       if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+           !port->xmit_buf)
+               return;
+               
+       /* this tells the transmitter to consider this port for
+          data output to the card ... that's the best we can do. */
+       port->status |= ISI_TXOK;       
+}
+
+/* write_room et all */
+static int isicom_write_room(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       int free;
+       if (isicom_paranoia_check(port, tty->device, "isicom_write_room"))
+               return 0;
+       
+       free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+       if (free < 0)
+               free = 0;
+       return free;
+}
+
+/* chars_in_buffer et all */
+static int isicom_chars_in_buffer(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       if (isicom_paranoia_check(port, tty->device, "isicom_chars_in_buffer"))
+               return 0;
+       return port->xmit_cnt;
+}
+
+/* ioctl et all */
+extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
+{
+       struct isi_board * card = port->card;
+       short wait = 10;
+       unsigned short base = card->base;       
+       unsigned long flags;
+       
+       save_flags(flags); cli();
+       while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));     
+       if (!wait) {
+               printk(KERN_DEBUG "ISICOM: Card found busy in isicom_send_break.\n");
+               return;
+       }       
+       outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
+       outw((length & 0xff) << 8 | 0x00, base);
+       outw((length & 0xff00), base);
+       InterruptTheCard(base);
+       restore_flags(flags);
+}
+
+static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
+{
+       /* just send the port status */
+       unsigned int info;
+       unsigned short status = port->status;
+       
+       info =  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
+               ((status & ISI_DTR) ? TIOCM_DTR : 0) |
+               ((status & ISI_DCD) ? TIOCM_CAR : 0) |
+               ((status & ISI_DSR) ? TIOCM_DSR : 0) |
+               ((status & ISI_CTS) ? TIOCM_CTS : 0);
+       put_user(info, (unsigned long *) value);
+       return 0;       
+}
+
+static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
+                                       unsigned int * value)
+{
+       unsigned int arg;
+       unsigned long flags;
+       
+       arg = get_user(value);
+       save_flags(flags); cli();
+       switch(cmd) {
+               case TIOCMBIS:
+                       if (arg & TIOCM_RTS) 
+                               raise_rts(port);
+                       if (arg & TIOCM_DTR) 
+                               raise_dtr(port);
+                       break;
+               
+               case TIOCMBIC:
+                       if (arg & TIOCM_RTS)
+                               drop_rts(port);
+                       if (arg & TIOCM_DTR)
+                               drop_dtr(port); 
+                       break;
+                       
+               case TIOCMSET:
+                       if (arg & TIOCM_RTS)
+                               raise_rts(port);
+                       else
+                               drop_rts(port);
+                       
+                       if (arg & TIOCM_DTR)
+                               raise_dtr(port);
+                       else
+                               drop_dtr(port);
+                       break;
+               
+               default:
+                       restore_flags(flags);
+                       return -EINVAL;                 
+       }
+       restore_flags(flags);
+       return 0;
+}                      
+
+static int isicom_set_serial_info(struct isi_port * port,
+                                       struct serial_struct * info)
+{
+       struct serial_struct newinfo;
+       unsigned long flags;
+       int reconfig_port;
+
+       memcpy_fromfs(&newinfo, info, sizeof(newinfo));
+       reconfig_port = ((port->flags & ASYNC_SPD_MASK) != 
+                        (newinfo.flags & ASYNC_SPD_MASK));
+       
+       if (!suser()) {
+               if ((newinfo.close_delay != port->close_delay) ||
+                   (newinfo.closing_wait != port->closing_wait) ||
+                   ((newinfo.flags & ~ASYNC_USR_MASK) != 
+                    (port->flags & ~ASYNC_USR_MASK)))
+                       return -EPERM;
+               port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
+                               (newinfo.flags & ASYNC_USR_MASK));
+       }       
+       else {
+               port->close_delay = newinfo.close_delay;
+               port->closing_wait = newinfo.closing_wait; 
+               port->flags = ((port->flags & ~ASYNC_FLAGS) | 
+                               (newinfo.flags & ASYNC_FLAGS));
+       }
+       if (reconfig_port) {
+               save_flags(flags); cli();
+               isicom_config_port(port);
+               restore_flags(flags);
+       }
+       return 0;                
+}              
+
+static int isicom_get_serial_info(struct isi_port * port, 
+                                       struct serial_struct * info)
+{
+       struct serial_struct out_info;
+       
+       memset(&out_info, 0, sizeof(out_info));
+/*     out_info.type = ? */
+       out_info.line = port - isi_ports;
+       out_info.port = port->card->base;
+       out_info.irq = port->card->irq;
+       out_info.flags = port->flags;
+/*     out_info.baud_base = ? */
+       out_info.close_delay = port->close_delay;
+       out_info.closing_wait = port->closing_wait;
+       memcpy_tofs(info, &out_info, sizeof(out_info));
+       return 0;
+}                                      
+
+static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
+                       unsigned int cmd, unsigned long arg) 
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       int retval, error;
+
+       if (isicom_paranoia_check(port, tty->device, "isicom_ioctl"))
+               return -ENODEV;
+
+       switch(cmd) {
+               case TCSBRK:
+                       retval = tty_check_change(tty);
+                       if (retval)
+                               return retval;
+                       tty_wait_until_sent(tty, 0);
+                       if (!arg)
+                               isicom_send_break(port, HZ/4);
+                       return 0;
+                       
+               case TCSBRKP:   
+                       retval = tty_check_change(tty);
+                       if (retval)
+                               return retval;
+                       tty_wait_until_sent(tty, 0);
+                       isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+                       return 0;
+                       
+               case TIOCGSOFTCAR:
+                       error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long)); 
+                       if (error)
+                               return error;
+                       put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+                       return 0;
+                       
+               case TIOCSSOFTCAR:
+                       error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));   
+                       if (error)
+                               return error;
+                       arg = get_user((unsigned long *) arg);
+                       tty->termios->c_cflag =
+                               ((tty->termios->c_cflag & ~CLOCAL) |
+                               (arg ? CLOCAL : 0));
+                       return 0;       
+                       
+               case TIOCMGET:
+                       error = verify_area(VERIFY_WRITE, (void *) arg, 
+                                       sizeof(unsigned int));             
+                       if (error)
+                               return error;
+                       return isicom_get_modem_info(port, (unsigned int*) arg);
+                       
+               case TIOCMBIS:
+               case TIOCMBIC:
+               case TIOCMSET:  
+                       error = verify_area(VERIFY_READ, (void *) arg, 
+                                       sizeof(unsigned int));             
+                       if (error)
+                               return error;
+                       return isicom_set_modem_info(port, cmd, 
+                                       (unsigned int *) arg);
+               
+               case TIOCGSERIAL:
+                       error = verify_area(VERIFY_WRITE, (void *) arg, 
+                                       sizeof(struct serial_struct));
+                       if (error)
+                               return error;           
+                       return isicom_get_serial_info(port, 
+                                       (struct serial_struct *) arg);
+               
+               case TIOCSSERIAL:
+                       error = verify_area(VERIFY_READ, (void *) arg,
+                                       sizeof(struct serial_struct));                  
+                       if (error)
+                               return error;
+                       return isicom_set_serial_info(port,
+                                       (struct serial_struct *) arg);
+                                       
+               default:
+                       return -ENOIOCTLCMD;                                            
+       }
+       return 0;
+}
+
+/* set_termios et all */
+static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       unsigned long flags;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))
+               return;
+       
+       if (tty->termios->c_cflag == old_termios->c_cflag &&
+           tty->termios->c_iflag == old_termios->c_iflag)
+               return;
+               
+       save_flags(flags); cli();
+       isicom_config_port(port);
+       restore_flags(flags);
+       
+       if ((old_termios->c_cflag & CRTSCTS) &&
+           !(tty->termios->c_cflag & CRTSCTS)) {       
+               tty->hw_stopped = 0;
+               isicom_start(tty);   
+       }    
+}
+
+/* throttle et all */
+static void isicom_throttle(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       struct isi_board * card = port->card;
+       unsigned long flags;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))
+               return;
+       
+       /* tell the card that this port cannot handle any more data for now */
+       save_flags(flags); cli();
+       card->port_status &= ~(1 << port->channel);
+       outw(card->port_status, card->base + 0x02);
+       restore_flags(flags);
+}
+
+/* unthrottle et all */
+static void isicom_unthrottle(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       struct isi_board * card = port->card;
+       unsigned long flags;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))
+               return;
+       
+       /* tell the card that this port is ready to accept more data */
+       save_flags(flags); cli();
+       card->port_status |= (1 << port->channel);
+       outw(card->port_status, card->base + 0x02);
+       restore_flags(flags);
+}
+
+/* stop et all */
+static void isicom_stop(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+
+       if (isicom_paranoia_check(port, tty->device, "isicom_stop"))
+               return;
+       
+       /* this tells the transmitter not to consider this port for
+          data output to the card. */
+       port->status &= ~ISI_TXOK;
+}
+
+/* start et all */
+static void isicom_start(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_start"))
+               return;
+       
+       /* this tells the transmitter to consider this port for
+          data output to the card. */
+       port->status |= ISI_TXOK;
+}
+
+/* hangup et all */
+static void do_isicom_hangup(void * data)
+{
+       struct isi_port * port = (struct isi_port *) data;
+       struct tty_struct * tty;
+       
+       tty = port->tty;
+       if (!tty)
+               return;
+               
+       tty_hangup(tty);        
+}
+
+static void isicom_hangup(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_hangup"))
+               return;
+       
+       isicom_shutdown_port(port);
+       port->count = 0;
+       port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+       port->tty = 0;
+       wake_up_interruptible(&port->open_wait);
+}
+
+/* flush_buffer et all */
+static void isicom_flush_buffer(struct tty_struct * tty)
+{
+       struct isi_port * port = (struct isi_port *) tty->driver_data;
+       unsigned long flags;
+       
+       if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))
+               return;
+       
+       save_flags(flags); cli();
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       restore_flags(flags);
+       
+       wake_up_interruptible(&tty->write_wait);
+       if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+           tty->ldisc.write_wakeup)
+               (tty->ldisc.write_wakeup)(tty);
+}
+
+
+static int register_ioregion(void)
+{
+       int count, done=0;
+       for (count=0; count < BOARD_COUNT; count++ ) {
+               if (isi_card[count].base) {
+                       if (check_region(isi_card[count].base,16)) {
+                               printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
+                                       isi_card[count].base,isi_card[count].base+15,count+1);
+                               isi_card[count].base=0;
+                       }
+                       else {
+                               request_region(isi_card[count].base,16,ISICOM_NAME);
+#ifdef ISICOM_DEBUG                            
+                               printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+#endif                         
+                               done++;
+                       }
+               }       
+       }
+       return done;
+}
+
+static void unregister_ioregion(void)
+{
+       int count;
+       for (count=0; count < BOARD_COUNT; count++ ) 
+               if (isi_card[count].base) {
+                       release_region(isi_card[count].base,16);
+#ifdef ISICOM_DEBUG                    
+                       printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+#endif                 
+               }
+}
+
+static int register_drivers(void)
+{
+       int error;
+
+       /* tty driver structure initialization */
+       memset(&isicom_normal, 0, sizeof(struct tty_driver));
+       isicom_normal.magic     = TTY_DRIVER_MAGIC;
+       isicom_normal.name      = "ttyM";
+       isicom_normal.major     = ISICOM_NMAJOR;
+       isicom_normal.minor_start       = 0;
+       isicom_normal.num       = PORT_COUNT;
+       isicom_normal.type      = TTY_DRIVER_TYPE_SERIAL;
+       isicom_normal.subtype   = SERIAL_TYPE_NORMAL;
+       isicom_normal.init_termios      = tty_std_termios;
+       isicom_normal.init_termios.c_cflag      = 
+                               B9600 | CS8 | CREAD | HUPCL |CLOCAL;
+       isicom_normal.flags     = TTY_DRIVER_REAL_RAW;
+       isicom_normal.refcount  = &isicom_refcount;
+       
+       isicom_normal.table     = isicom_table;
+       isicom_normal.termios   = isicom_termios;
+       isicom_normal.termios_locked    = isicom_termios_locked;
+       
+       isicom_normal.open      = isicom_open;
+       isicom_normal.close     = isicom_close;
+       isicom_normal.write     = isicom_write;
+       isicom_normal.put_char  = isicom_put_char;
+       isicom_normal.flush_chars       = isicom_flush_chars;
+       isicom_normal.write_room        = isicom_write_room;
+       isicom_normal.chars_in_buffer   = isicom_chars_in_buffer;
+       isicom_normal.ioctl     = isicom_ioctl;
+       isicom_normal.set_termios       = isicom_set_termios;
+       isicom_normal.throttle  = isicom_throttle;
+       isicom_normal.unthrottle        = isicom_unthrottle;
+       isicom_normal.stop      = isicom_stop;
+       isicom_normal.start     = isicom_start;
+       isicom_normal.hangup    = isicom_hangup;
+       isicom_normal.flush_buffer      = isicom_flush_buffer;
+       
+       /*      callout device  */
+       
+       isicom_callout  = isicom_normal;
+       isicom_callout.name     = "cum"; 
+       isicom_callout.major    = ISICOM_CMAJOR;
+       isicom_callout.subtype  = SERIAL_TYPE_CALLOUT;
+       
+       if ((error=tty_register_driver(&isicom_normal))!=0) {
+               printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
+                       error);
+               return error;
+       }
+       if ((error=tty_register_driver(&isicom_callout))!=0) {
+               tty_unregister_driver(&isicom_normal);
+               printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%d\n",
+                       error);
+               return error;   
+       }
+       return 0;
+}
+
+static void unregister_drivers(void)
+{
+       int error;
+       if ((error=tty_unregister_driver(&isicom_callout))!=0)
+               printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.\n",error);
+       if (tty_unregister_driver(&isicom_normal))
+               printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+}
+
+static int register_isr(void)
+{
+       int count, done=0;
+       for (count=0; count < BOARD_COUNT; count++ ) {
+               if (isi_card[count].base) {
+                       if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) {
+                               printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",
+                                       isi_card[count].irq, count+1);
+                               release_region(isi_card[count].base,16);
+                               isi_card[count].base=0;
+                       }
+                       else {
+                               printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", 
+                               count+1, isi_card[count].base, isi_card[count].irq); 
+                               
+                               irq_to_board[isi_card[count].irq]=&isi_card[count];
+                               done++;
+                       }
+               }       
+       }
+       return done;
+}
+
+static void unregister_isr(void)
+{
+       int count;
+       for (count=0; count < BOARD_COUNT; count++ ) 
+               if (isi_card[count].base) {
+                       free_irq(isi_card[count].irq, NULL);
+#ifdef ISICOM_DEBUG                    
+                       printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);
+#endif                 
+               }
+}
+
+static int isicom_init(void)
+{
+       int card, channel, base;
+       struct isi_port * port;
+       unsigned long page;
+       
+       if (!tmp_buf) { 
+               page = get_free_page(GFP_KERNEL);
+               if (!page) {
+#ifdef ISICOM_DEBUG            
+                       printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
+#else
+                       printk(KERN_ERR "ISICOM: Not enough memory...\n");
+#endif       
+                       return 0;
+               }       
+               tmp_buf = (unsigned char *) page;
+       }
+       
+       if (!register_ioregion()) 
+       {
+               printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
+               free_page((unsigned long)tmp_buf);
+               return 0;
+       }
+       if (register_drivers()) 
+       {
+               unregister_ioregion();
+               free_page((unsigned long)tmp_buf);
+               return 0;
+       }
+       if (!register_isr()) 
+       {
+               unregister_drivers();
+               /*  ioports already uregistered in register_isr */
+               free_page((unsigned long)tmp_buf);
+               return 0;               
+       }
+       
+       /* initialize bottom half  */
+       init_bh(ISICOM_BH, do_isicom_bh);
+
+
+       memset(isi_ports, 0, sizeof(isi_ports));
+       for (card = 0; card < BOARD_COUNT; card++) {
+               port = &isi_ports[card * 16];
+               isi_card[card].ports = port;
+               base = isi_card[card].base;
+               for (channel = 0; channel < 16; channel++, port++) {
+                       port->magic = ISICOM_MAGIC;
+                       port->card = &isi_card[card];
+                       port->channel = channel;                
+                       port->normal_termios = isicom_normal.init_termios;
+                       port->callout_termios = isicom_callout.init_termios;
+                       port->close_delay = 50 * HZ/100;
+                       port->closing_wait = 3000 * HZ/100;
+                       port->hangup_tq.routine = do_isicom_hangup;
+                       port->hangup_tq.data = port;
+                       port->bh_tqueue.routine = isicom_bottomhalf;
+                       port->bh_tqueue.data = port;
+                       port->status = 0;
+                                               
+                       /*  . . .  */
+               }
+       } 
+       
+       return 1;       
+}
+
+/*
+ *     Insmod can set static symbols so keep these static
+ */
+static int ISIBase1=0, ISIBase2=0, ISIBase3=0, ISIBase4=0; 
+static int Irq1=0, Irq2=0, Irq3=0, Irq4=0;
+
+int init_module(void)
+{
+       int retval, card;
+       
+       isi_card[0].base=ISIBase1;
+       isi_card[1].base=ISIBase2;
+       isi_card[2].base=ISIBase3;
+       isi_card[3].base=ISIBase4;
+                       
+       isi_card[0].irq=Irq1;
+       isi_card[1].irq=Irq2;
+       isi_card[2].irq=Irq3;
+       isi_card[3].irq=Irq4;
+       
+       for (card=0 ;card < BOARD_COUNT; card++) {
+               if (!((isi_card[card].irq==2)||(isi_card[card].irq==3)||
+                   (isi_card[card].irq==4)||(isi_card[card].irq==5)||
+                   (isi_card[card].irq==7)||(isi_card[card].irq==10)||
+                   (isi_card[card].irq==11)||(isi_card[card].irq==12)||
+                   (isi_card[card].irq==15))) {
+                       
+                       if (isi_card[card].base) {
+                               printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
+                                       isi_card[card].irq, card+1);
+                               isi_card[card].base=0;
+                       }       
+               }
+       }       
+       
+       if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
+               printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); 
+               return -EIO;
+       }               
+       retval=misc_register(&isiloader_device);
+       if (retval<0) {
+               printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
+               return -EIO;
+       }
+       
+       if (!isicom_init()) {
+               if (misc_deregister(&isiloader_device)) 
+                       printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+               return -EIO;
+       }
+       
+       init_timer(&tx);
+       tx.expires = jiffies + 1;
+       tx.data = 0;
+       tx.function = isicom_tx;
+       re_schedule = 1;
+       add_timer(&tx);
+       
+       return 0;
+}
+
+void cleanup_module(void)
+{
+       re_schedule = 0;
+       current->state = TASK_INTERRUPTIBLE;
+       current->timeout = jiffies + HZ;
+       schedule();
+       disable_bh(ISICOM_BH);
+       
+#ifdef ISICOM_DEBUG    
+       printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
+#endif 
+
+#ifdef ISICOM_DEBUG
+       printk("ISICOM: uregistering isr ...\n");
+#endif 
+       unregister_isr();
+
+#ifdef ISICOM_DEBUG    
+       printk("ISICOM: unregistering drivers ...\n");
+#endif
+       unregister_drivers();
+       
+#ifdef ISICOM_DEBUG    
+       printk("ISICOM: unregistering ioregion ...\n");
+#endif 
+       unregister_ioregion();  
+       
+#ifdef ISICOM_DEBUG    
+       printk("ISICOM: freeing tmp_buf ...\n");
+#endif 
+       free_page((unsigned long)tmp_buf);
+       
+#ifdef ISICOM_DEBUG            
+       printk("ISICOM: unregistering firmware loader ...\n");  
+#endif
+       if (misc_deregister(&isiloader_device))
+               printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+}
diff --git a/drivers/char/isicom.h b/drivers/char/isicom.h
new file mode 100644 (file)
index 0000000..040d2f0
--- /dev/null
@@ -0,0 +1,300 @@
+#ifndef ISICOM_H
+#define ISICOM_H
+
+/*#define              ISICOM_DEBUG*/
+/*#define              ISICOM_DEBUG_DTR_RTS*/
+
+
+
+/*
+ *     Firmware Loader definitions ...
+ */
+
+#define                ISILOAD_MISC_MINOR      155     /* /dev/isctl */
+#define                ISILOAD_NAME            "ISILoad"
+#define                MultiTech               ('M'<<8)
+#define                MIOCTL_LOAD_FIRMWARE    (MultiTech | 0x01)
+#define         MIOCTL_READ_FIRMWARE    (MultiTech | 0x02)
+#define         MIOCTL_XFER_CTRL       (MultiTech | 0x03)
+#define         MIOCTL_RESET_CARD      (MultiTech | 0x04)
+
+#define                DATA_SIZE       16
+
+typedef        struct  {
+               unsigned short  exec_segment;
+               unsigned short  exec_addr;
+}      exec_record;
+
+typedef        struct  {
+               int             board;          /* Board to load */
+               unsigned short  addr;
+               unsigned short  count;
+}      bin_header;
+
+typedef        struct  {
+               int             board;          /* Board to load */
+               unsigned short  addr;
+               unsigned short  count;
+               unsigned short  segment;
+               unsigned char   bin_data[DATA_SIZE];
+}      bin_frame;
+
+#ifdef __KERNEL__
+
+/*     
+ *  ISICOM Driver definitions ...
+ *
+ */
+
+#define                ISICOM_NAME     "ISICom"
+
+/*
+ *     These are now officially allocated numbers
+ */
+
+#define                ISICOM_NMAJOR   112     /* normal  */
+#define                ISICOM_CMAJOR   113     /* callout */
+#define                ISICOM_MAGIC    (('M' << 8) | 'T')
+
+#define                ISICOM_BH       16      /* bottom half entry # */ 
+#define                WAKEUP_CHARS    256     /* hard coded for now   */ 
+#define                TX_SIZE         254 
+#define                BOARD_COUNT     4
+#define                PORT_COUNT      (BOARD_COUNT*16)
+
+#define                SERIAL_TYPE_NORMAL      1
+#define                SERIAL_TYPE_CALLOUT     2
+
+/*   character sizes  */
+
+#define                ISICOM_CS5              0x0000
+#define                ISICOM_CS6              0x0001
+#define                ISICOM_CS7              0x0002
+#define                ISICOM_CS8              0x0003
+
+/* stop bits */
+
+#define                ISICOM_1SB              0x0000
+#define                ISICOM_2SB              0x0004
+
+/* parity */
+
+#define                ISICOM_NOPAR            0x0000
+#define                ISICOM_ODPAR            0x0008
+#define                ISICOM_EVPAR            0x0018
+
+/* flow control */
+
+#define                ISICOM_CTSRTS           0x03
+#define                ISICOM_INITIATE_XONXOFF 0x04
+#define                ISICOM_RESPOND_XONXOFF  0x08
+
+#define InterruptTheCard(base) (outw(0,(base)+0xc)) 
+#define ClearInterrupt(base) (inw((base)+0x0a))        
+
+#define        BOARD(line)  (((line) >> 4) & 0x3)
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+
+       /*      isi kill queue bitmap   */
+       
+#define                ISICOM_KILLTX           0x01
+#define                ISICOM_KILLRX           0x02
+
+       /* isi_board status bitmap */
+       
+#define                FIRMWARE_LOADED         0x0001
+#define                BOARD_ACTIVE            0x0002
+
+       /* isi_port status bitmap  */
+
+#define                ISI_CTS                 0x1000
+#define                ISI_DSR                 0x2000
+#define                ISI_RI                  0x4000
+#define                ISI_DCD                 0x8000
+#define                ISI_DTR                 0x0100
+#define                ISI_RTS                 0x0200
+
+
+#define                ISI_TXOK                0x0001 
+struct isi_board {
+       unsigned short          base;
+       unsigned char           irq;
+       unsigned char           port_count;
+       unsigned short          status;
+       unsigned short          port_status; /* each bit represents a single port */
+       unsigned short          shift_count;
+       struct isi_port         * ports;
+       signed char             count;
+};
+
+struct isi_port {
+       unsigned short          magic;
+       unsigned int            flags;
+       int                     count;
+       int                     blocked_open;
+       int                     close_delay;
+       unsigned short          channel;
+       unsigned short          status;
+       unsigned short          closing_wait;
+       long                    session;
+       long                    pgrp;
+       struct isi_board        * card;
+       struct tty_struct       * tty;
+       struct wait_queue       * close_wait;
+       struct wait_queue       * open_wait;
+       struct tq_struct        hangup_tq;
+       struct tq_struct        bh_tqueue;
+       unsigned char           * xmit_buf;
+       int                     xmit_head;
+       int                     xmit_tail;
+       int                     xmit_cnt;
+       struct termios          normal_termios;
+       struct termios          callout_termios;
+};
+
+
+/*
+ *  ISI Card specific ops ...
+ */
+extern inline void raise_dtr(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG_DTR_RTS    
+       printk(KERN_DEBUG "ISICOM: raise_dtr.\n");
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw(0x0504, base);
+       InterruptTheCard(base);
+       port->status |= ISI_DTR;
+}
+extern inline void drop_dtr(struct isi_port * port)
+{      
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG_DTR_RTS    
+       printk(KERN_DEBUG "ISICOM: drop_dtr.\n");
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw(0x0404, base);
+       InterruptTheCard(base); 
+       port->status &= ~ISI_DTR;
+}
+extern inline void raise_rts(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG_DTR_RTS    
+       printk(KERN_DEBUG "ISICOM: raise_rts.\n");
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw(0x0a04, base);
+       InterruptTheCard(base); 
+       port->status |= ISI_RTS;
+}
+extern inline void drop_rts(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG_DTR_RTS    
+       printk(KERN_DEBUG "ISICOM: drop_rts.\n");
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw(0x0804, base);
+       InterruptTheCard(base); 
+       port->status &= ~ISI_RTS;
+}
+extern inline void raise_dtr_rts(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG_DTR_RTS    
+       printk(KERN_DEBUG "ISICOM: raise_dtr_rts.\n");
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw(0x0f04, base);
+       InterruptTheCard(base);
+       port->status |= (ISI_DTR | ISI_RTS);
+}
+extern inline void drop_dtr_rts(struct isi_port * port)
+{
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG_DTR_RTS    
+       printk(KERN_DEBUG "ISICOM: drop_dtr_rts.\n");
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw(0x0c04, base);
+       InterruptTheCard(base); 
+       port->status &= ~(ISI_RTS | ISI_DTR);
+}
+
+extern inline void kill_queue(struct isi_port * port, short queue)
+{
+       struct isi_board * card = port->card;
+       unsigned short base = card->base;
+       unsigned char channel = port->channel;
+       short wait=300;
+       while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+       if (wait <= 0) {
+               printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
+               return;
+       }
+#ifdef ISICOM_DEBUG    
+       printk(KERN_DEBUG "ISICOM: kill_queue 0x%x.\n", queue);
+#endif 
+       outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+       outw((queue << 8) | 0x06, base);
+       InterruptTheCard(base); 
+}
+
+#endif /*      __KERNEL__      */
+
+#endif /*      ISICOM_H        */
\ No newline at end of file
index 96fe95824f821f88327a05877c3a038d1cfb095f..d1b8edd71f38a58ef7516f76309399754ba42950 100644 (file)
@@ -89,12 +89,18 @@ static inline int lp_char_polled(char lpchar, int minor)
        while(wait != LP_WAIT(minor)) wait++;
        /* control port takes strobe high */
        outb_p(( LP_PSELECP | LP_PINITP | LP_PSTROBE ), ( LP_C( minor )));
-       /* Wait until NBUSY line goes high */
-       count = 0;
-       do {
-               status = LP_S(minor);
-               count++;
-       } while (LP_READY(minor, status) && (count<LP_CHAR(minor)));
+       
+       if(LP_F(minor)&LP_STRICT)
+       {
+               /* Wait until NBUSY line goes high */
+               count = 0;
+               do {
+                       status = LP_S(minor);
+                       count++;
+               } while (LP_READY(minor, status) && (count<LP_CHAR(minor)));
+       }
+       else while(wait) wait--;
+       
        /* take strobe low */
        outb_p(( LP_PSELECP | LP_PINITP ), ( LP_C( minor )));
        /* update waittime statistics */
@@ -434,6 +440,12 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        else
                                LP_F(minor) &= ~LP_CAREFUL;
                        break;
+               case LPSTRICT:
+                       if (arg)
+                               LP_F(minor) |= LP_STRICT;
+                       else
+                               LP_F(minor) &= ~LP_STRICT;
+                       break;
                case LPWAIT:
                        LP_WAIT(minor) = arg;
                        break;
index 6691b728a14d0d4bd4c374badcd450b2f5f8a152..64e2a6974e311b7526a9a379903711fb6e5d1689 100644 (file)
@@ -7,11 +7,11 @@ if [ "$CONFIG_INET" != "n" ]; then
     bool 'Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
     bool 'Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
   fi
-  bool 'Support dynamic timeout-rules' CONFIG_ISDN_TIMEOUT_RULES
-  if [ "$CONFIG_ISDN_TIMEOUT_RULES" != "n" ]; then
-    bool 'Use masqueraded addresses for rule-matching' CONFIG_ISDN_TIMRU_USE_MASQ
-  fi
-  bool 'Support budget-accounting' CONFIG_ISDN_BUDGET
+  #bool 'Support dynamic timeout-rules' CONFIG_ISDN_TIMEOUT_RULES
+  #if [ "$CONFIG_ISDN_TIMEOUT_RULES" != "n" ]; then
+  #  bool 'Use masqueraded addresses for rule-matching' CONFIG_ISDN_TIMRU_USE_MASQ
+  #fi
+  #bool 'Support budget-accounting' CONFIG_ISDN_BUDGET
 fi
 bool 'Support audio via ISDN' CONFIG_ISDN_AUDIO
 dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
index 55ed55217d4f60769a19fad767d80c1cd7af9aef..c8668ebb7e457807fed966f5bbe0ffdc7495586a 100644 (file)
@@ -815,6 +815,7 @@ const char *pci_strvendor(unsigned int vendor)
              case PCI_VENDOR_ID_3DFX:          return "3Dfx";
              case PCI_VENDOR_ID_SIGMADES:      return "Sigma Designs";
              case PCI_VENDOR_ID_OPTIBASE:      return "Optibase";
+             case PCI_VENDOR_ID_NVIDIA_SGS:    return "NVidia/SGS Thomson";
              case PCI_VENDOR_ID_SYMPHONY:      return "Symphony";
              case PCI_VENDOR_ID_TEKRAM:        return "Tekram";
              case PCI_VENDOR_ID_3DLABS:        return "3Dlabs";
index e45d80f4e754724f84275c9e82436dc6a38f2a61..08e8855ea324d07b66e720da7005fa95f45a95d6 100644 (file)
@@ -119,6 +119,8 @@ static int partsize(struct buffer_head *bh, unsigned long capacity,
        end_head = largest->end_head;
        end_sector = largest->end_sector & 0x3f;
 
+        if( end_head + 1 == 0 || end_sector == 0 ) return -1;
+
 #ifdef DEBUG
        printk ("scsicam_bios_param : end at h = %d, c = %d, s = %d\n",
            end_head, end_cyl, end_sector);
index d5dfa70aedc0f584bd701717800a431b334b30b9..9e856fdb9f8ee5faefbe3b01df8dc2c2b3716f05 100644 (file)
@@ -146,11 +146,10 @@ sound.o: local.h $(FIXEDOBJS) sound.a
        $(LD) -r -o sound.o $(FIXEDOBJS) sound.a
 
 modules: local.h sound.o
-       ln -fs `pwd`/sound.o $(TOPDIR)/modules/sound.o
-
+       ln -fs ../drivers/sound/sound.o $(TOPDIR)/modules/sound.o
 
 lowlevel/lowlevel.o: dummy
-               cd lowlevel;make
+       cd lowlevel; make
 
 ifdef USE_DEPEND
 #
index e8506e6f3d6218a3f8a78ae9283cd58fd74ff0e1..ee279b39bdd1e03a77d7b6d720bcb52e720e34fb 100644 (file)
@@ -16,6 +16,7 @@
  *
  *     Changes:
  *
+ *     R. Drahtmueller :       Set IFF_MULTICAST in dev->flags if applicable.
  *     Alan Cox        :       Removed get_address name clash with FPU.
  *     Alan Cox        :       Reformatted a bit.
  *     Gero Kuhlmann   :       Code cleanup
@@ -179,7 +180,11 @@ static int root_dev_open(void)
                    (!user_dev_name[0] || !strcmp(dev->name, user_dev_name))) {
                        /* First up the interface */
                        old_flags = dev->flags;
+#ifdef CONFIG_IP_MULTICAST
+                       dev->flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING | IFF_MULTICAST;
+#else
                        dev->flags = IFF_UP | IFF_BROADCAST | IFF_RUNNING;
+#endif
                        if (!(old_flags & IFF_UP) && dev_open(dev)) {
                                dev->flags = old_flags;
                                continue;
index 8ce98f5b5eaa9a17a3ae2278f40006a876f0bbd2..34c4b5e64313da05d7e7a901743f712aa8bd947b 100644 (file)
@@ -754,6 +754,13 @@ struct cyclades_port {
 #define CyTBPR         (0x72*2)
 #define CyTCOR         (0x76*2)
 
+/* Custom Registers */
+
+#define        CyPLX_VER       (0x3400)
+#define        PLX_9050        0x11
+#define        PLX_9060        0x12
+#define        PLX_9080        0x13
+
 /***************************************************************************/
 
 #endif /* __KERNEL__ */
index 1b5e989aea6ac28f3260ed469cb97fa60cfe70bd..9ac441707cac940efbb6cf9da3ba7c45d72e9443 100644 (file)
@@ -131,9 +131,6 @@ struct ip_fw
 #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
 #define IP_FW_AUTOFW           5
 #endif
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-#define IP_FW_PORTFW           6
-#endif
 
 #define IP_FW_INSERT           (IP_FW_BASE_CTL)
 #define IP_FW_APPEND           (IP_FW_BASE_CTL+1)
@@ -180,12 +177,6 @@ struct ip_fw
 #define IP_AUTOFW_FLUSH        (IP_FW_FLUSH  | (IP_FW_AUTOFW << IP_FW_SHIFT))
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
 
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-#define IP_PORTFW_ADD          (IP_FW_APPEND | (IP_FW_PORTFW << IP_FW_SHIFT))
-#define IP_PORTFW_DEL          (IP_FW_DELETE | (IP_FW_PORTFW << IP_FW_SHIFT))
-#define IP_PORTFW_FLUSH        (IP_FW_FLUSH  | (IP_FW_PORTFW << IP_FW_SHIFT))
-#endif /* CONFIG_IP_MASQUERADE_IPPFVS */
-
 struct ip_fwpkt
 {
        struct iphdr fwp_iph;                   /* IP header */
@@ -228,9 +219,6 @@ extern int ip_fw_ctl(int, void *, int);
 #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW
 extern int ip_autofw_ctl(int, void *, int);
 #endif
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-extern int ip_portfw_ctl(int, void *, int);
-#endif
 #ifdef CONFIG_IP_ACCT
 extern struct ip_fw *ip_acct_chain;
 extern int ip_acct_ctl(int, void *, int);
@@ -265,42 +253,4 @@ struct ip_autofw {
        struct timer_list timer;
 };
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
-
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-
-#define IP_PORTFW_PORT_MIN 1
-#define IP_PORTFW_PORT_MAX 60999
-#define SERVER_WEIGHT_MIN   1
-#define SERVER_WEIGHT_MAX   1000
-
-/* contains info about a real server */
-struct server {
-        struct server *next;     /* next real server for the virtual server */
-        __u32  ip;               /* ip address of the real server */
-        __u16  port;             /* port number of service on the real server */
-        int connections;         /* number of alive connections (TCP only) */
-        short weight;            /* to indicate server's processing capacity */
-};
-
-
-struct ip_portfw {
-        struct ip_portfw *next;
-        __u32           laddr;
-        __u16           lport;
-        struct server   *sr_lst;       /* server list */
-        struct server   *curr_sr;      /* current server used in simple round-robbin scheduling algorithm */
-};
-
-struct ip_portfw_edits {
-       __u16           protocol;       /* Which protocol are we talking? */
-       __u32           laddr, raddr;   /* Local and remote address */
-       __u16           lport, rport;   /* Local and remote port */
-       short           weight;         /* Server weight */
-};
-#endif /* CONFIG_IP_MASQUERADE_IPPFVS */
 #endif /* _IP_FW_H */
-
-
-
-
-
index 2a1282c8add2b0dcb69376a98a6222166daa43eb..c34df2cc55cf008af016f097070cc62afebfdf3d 100644 (file)
@@ -20,6 +20,7 @@
 #define LP_ABORT 0x0040
 #define LP_CAREFUL 0x0080
 #define LP_ABORTOPEN 0x0100
+#define LP_STRICT 0x0200
 
 /* timeout for each character.  This is relative to bus cycles -- it
  * is the count in a busy loop.  THIS IS THE VALUE TO CHANGE if you
@@ -70,6 +71,7 @@
 #define LPRESET     0x060c  /* reset printer */
 #define LPGETSTATS  0x060d  /* get statistics (struct lp_stats) */
 #define LPGETFLAGS  0x060e  /* get status flags */
+#define LPSTRICT    0x060f  /* enable/disable strict compliance */
 
 /* timeout for printk'ing a timeout, in jiffies (100ths of a second).
    This is also used for re-checking error conditions if LP_ABORT is
index 998809741154c8e466188024ebe800d6d5b811f6..fc1a4b8f5a9ba248e20f61cdb4db8c6e042fd654 100644 (file)
@@ -105,7 +105,6 @@ enum net_directory_inos {
        PROC_NET_STRIP_STATUS,
        PROC_NET_STRIP_TRACE,
        PROC_NET_IPAUTOFW,
-       PROC_NET_IPPORTFW,
        PROC_NET_RS_NODES,
        PROC_NET_RS_NEIGH,
        PROC_NET_RS_ROUTES,
index 416b2b4b698053ff27d8a7ef5230384b542bd8c7..ccfb646c38b29f1b413235a45fef2320ee737b9b 100644 (file)
@@ -84,9 +84,6 @@ struct ip_masq {
        void            *app_data;      /* Application private data */
        unsigned  flags;                /* status flags */
        struct ip_masq  *control;       /* Corresponding control connection */
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-        struct server   *real_server;   /* Which real server is chosen? */
-#endif /* CONFIG_IP_MASQUERADE_IPPFVS */
 };
 
 /*
index 2acbb5adfe1ebe4c96f1914ec4e1e04d4d62d16f..3d1ac2cfb96f633613184a68723f2e227b1b7ad0 100644 (file)
@@ -16,7 +16,6 @@ if [ "$CONFIG_FIREWALL" = "y" ]; then
         comment 'Protocol-specific masquerading support will be built as modules.'
         if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then      
           bool 'IP: ipautofw masquerading (EXPERIMENTAL)' CONFIG_IP_MASQUERADE_IPAUTOFW
-          bool 'IP: ipportfw masq & virtual server support' CONFIG_IP_MASQUERADE_IPPFVS
         fi
         bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP
       fi
index 4665bf4178630bf7fbb166d75a1a6996b2ee08b0..63f6ebd19486eb7ba97ac64ad1f9860bf98c4c63 100644 (file)
@@ -977,170 +977,6 @@ int ip_autofw_ctl(int stage, void *m, int len)
 
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
 
-
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-extern struct ip_portfw *ipportfw_lst[2];
-
-int ip_portfw_del(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr)
-{
-    int prot = (protocol == IPPROTO_TCP);
-    struct ip_portfw *pf;
-    struct ip_portfw **pf_p;
-
-    if (!ipportfw_lst[prot])
-       return 1;
-
-    for (pf_p = &ipportfw_lst[prot]; *pf_p; pf_p = &(*pf_p)->next) {
-       pf = *pf_p;
-       if (pf->lport == lport && pf->laddr == laddr) {
-           struct server *s;
-           struct server **sp;
-           for (sp = &pf->sr_lst; *sp; sp = &(*sp)->next) {
-               s = *sp;
-               if (s->ip == raddr && s->port == rport) {
-                   *sp = s->next;
-                   kfree_s(s, sizeof(*s));
-                   if (!pf->sr_lst) {
-                       /* No real server exists now, and remove the entry in the port forwarding table */
-                       *pf_p = pf->next;
-                       kfree_s(pf, sizeof(*pf));
-                   }
-                   return 0;
-               }
-           }
-       }
-    }
-
-    /* Entry not found so return an error */
-    return 1;
-}
-
-void ip_portfw_flush(void)
-{
-    int prot;
-    struct ip_portfw *c, *n;
-    struct server *s, *sn;
-
-    for (prot = 0; prot < 2; prot++) {
-       c = ipportfw_lst[prot];
-       ipportfw_lst[prot] = NULL;
-       for (; c; c = n) {
-           n = c->next;
-           s = c->sr_lst;
-           while (s) {
-               sn = s->next;
-               kfree_s(s, sizeof(*s));
-               s = sn;
-           }
-           kfree_s(c, sizeof(*c));
-       }
-    }
-}
-
-int ip_portfw_add(__u16 protocol, __u16 lport, __u32 laddr, __u16 rport, __u32 raddr, short weight)
-{
-    struct ip_portfw *pf, *newportfw;
-    struct server *s, *newserv;
-    int prot = (protocol == IPPROTO_TCP);
-
-    for (pf = ipportfw_lst[prot]; pf; pf = pf->next) {
-       if (lport == pf->lport && laddr == pf->laddr) {
-           for (s = pf->sr_lst; s; s = s->next) {
-               if (s->ip == raddr && s->port == rport) {
-                    s->weight = weight;
-                   return 0;
-                }
-           }
-           newserv = (struct server *) kmalloc(sizeof(struct server), GFP_ATOMIC);
-           if (!newserv)
-               return 1;
-
-           newserv->ip = raddr;
-           newserv->port = rport;
-           newserv->weight = weight;
-            newserv->connections = 0;
-
-           /* insert the new real server in the server list */
-           newserv->next = pf->sr_lst;
-           pf->sr_lst = newserv;
-           return 0;
-       }
-    }
-
-    newserv = (struct server *) kmalloc(sizeof(struct server), GFP_ATOMIC);
-    if (!newserv)
-       return 1;
-
-    newserv->ip = raddr;
-    newserv->port = rport;
-    newserv->weight = weight;
-    newserv->connections = 0;
-    newserv->next = NULL;
-
-    newportfw = (struct ip_portfw *)
-       kmalloc(sizeof(struct ip_portfw), GFP_ATOMIC);
-
-    if (!newportfw)
-       return 1;
-
-    newportfw->laddr = laddr;
-    newportfw->lport = lport;
-    newportfw->sr_lst = newserv;
-    newportfw->curr_sr = NULL;
-
-    /* insert the new entry into the port forwarding table */
-    newportfw->next = ipportfw_lst[prot];
-    ipportfw_lst[prot] = newportfw;
-    return 0;
-}
-
-int ip_portfw_ctl(int cmd, void *m, int len)
-{
-    unsigned long flags;
-    int failed;
-    struct ip_portfw_edits *mm = (struct ip_portfw_edits *) m;
-
-    /* Don't trust the lusers - plenty of error checking! */
-
-    if (cmd != IP_PORTFW_ADD && cmd != IP_PORTFW_DEL
-       && cmd != IP_PORTFW_FLUSH)
-       return (EINVAL);
-
-    if (cmd != IP_PORTFW_FLUSH) {
-       if (mm->lport < IP_PORTFW_PORT_MIN || mm->lport > IP_PORTFW_PORT_MAX)
-           return (EINVAL);
-
-       if (mm->protocol != IPPROTO_TCP && mm->protocol != IPPROTO_UDP)
-           return (EINVAL);
-    }
-    if (cmd == IP_PORTFW_ADD) {
-       save_flags(flags);
-       cli();
-       failed = ip_portfw_add(mm->protocol,
-                              htons(mm->lport), htonl(mm->laddr),
-                              htons(mm->rport), htonl(mm->raddr),
-                               mm->weight);
-       restore_flags(flags);
-       return (failed ? ENOMEM : 0);
-    } else if (cmd == IP_PORTFW_DEL) {
-       save_flags(flags);
-       cli();
-       failed = ip_portfw_del(mm->protocol,
-                              htons(mm->lport), htonl(mm->laddr),
-                              htons(mm->rport), htonl(mm->raddr));
-       restore_flags(flags);
-       return (failed ? EINVAL : 0);
-    } else if (cmd == IP_PORTFW_FLUSH) {
-       save_flags(flags);
-       cli();
-       ip_portfw_flush();
-       restore_flags(flags);
-       return 0;
-    } else
-       return (EINVAL);        /* This should have avoided in ip_sockglue.c */
-}
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
-
 #ifdef CONFIG_IP_FIREWALL
 int ip_fw_ctl(int stage, void *m, int len)
 {
index e21c451bf00d6a6426602d0e57efd7958df2d522..6c485e45842efbdd5a2df325b975ec9f12d886a2 100644 (file)
@@ -20,8 +20,6 @@
  *     Delian Delchev          :       Added support for ICMP requests and replys
  *     Nigel Metheringham      :       ICMP in ICMP handling, tidy ups, bug fixes, made ICMP optional
  *     Juan Jose Ciarlante     :       re-assign maddr if no packet received from outside
- *      Steven Clarke           :       Added Port Forwarding
- *      Wensong Zhang           :       Added virtual server support
  *     
  */
 
 #include <net/ip_masq.h>
 #include <linux/ip_fw.h>
 
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-/* 
- * Use a big hash table size for virtual server, which will reduce conflicts 
- * in the hash table when there are thousands of masqueraded connections.
- */
-#define IP_MASQ_TAB_SIZE 2048
-#else
 #define IP_MASQ_TAB_SIZE 256    /* must be power of 2 */
-#endif /* CONFIG_IP_MASQUERADE_IPPFVS */
 
 /*
  *     Implement IP packet masquerading
@@ -259,64 +249,6 @@ void ip_autofw_update_in (__u32 where, __u16 port, __u16 protocol)
 
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
 
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-
-struct ip_portfw *ipportfw_lst[2];
-
-struct server *ip_portfw_lookup(__u16 protocol, __u16 lport, __u32 laddr)
-{
-    int prot = (protocol == IPPROTO_TCP);
-    struct ip_portfw *n;
-    unsigned long flags;
-    int least_load, curr_load;
-    struct server *least, *curr;
-
-    save_flags(flags);
-    cli();
-    for (n = ipportfw_lst[prot]; n; n = n->next) {
-       if (lport == n->lport && laddr == n->laddr) {
-            /* Weighted Round-Robin Scheduling Algorithm */
-           least = n->sr_lst;
-           least_load = least->connections / least->weight;
-
-           for(curr = least->next; curr; curr=curr->next) {
-               curr_load = curr->connections / curr->weight;
-               if(curr_load < least_load) {
-                   least_load = curr_load;
-                   least = curr;
-               }
-           }
-
-           least->connections++;
-
-           restore_flags(flags);
-           return least;
-       }
-    }
-    restore_flags(flags);
-    return NULL;
-}
-
-int ip_portfw_check(__u16 protocol, __u16 lport, __u32 laddr)
-{
-    int prot = (protocol == IPPROTO_TCP);
-    struct ip_portfw *n;
-    unsigned long flags;
-    int found = 0;
-
-    save_flags(flags);
-    cli();
-    for (n = ipportfw_lst[prot]; n; n = n->next) {
-       if (lport == n->lport && laddr == n->laddr) {
-           found = 1;
-           break;
-       }
-    }
-    restore_flags(flags);
-    return found;
-}
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
-
 /*
  *     Returns hash value
  */
@@ -640,12 +572,6 @@ static void masq_expire(unsigned long data)
                 ip_masq_free_ports[masq_proto_num(ms->protocol)]++;
                 if (ms->protocol != IPPROTO_ICMP)
                              ip_masq_unbind_app(ms);
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-               /* if not null, decrease the real server's alive connection count */
-               if (ms->real_server)
-                       ms->real_server->connections--;
-#endif /* CONFIG_IP_MASQUERADE_IPPFVS */
-
                 kfree_s(ms,sizeof(*ms));
         }
 
@@ -773,58 +699,6 @@ struct ip_masq * ip_masq_new(struct device *dev, int proto, __u32 saddr, __u16 s
        return (ip_masq_new_enh(dev, proto, saddr, sport, daddr, dport, mflags, 0) );
 }
 
-
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-
-/*  
- * New form of ip_masq creation which creates masqs for Port Forwarding &
- * Virtual Server. The routine is sufficiently different to ip_masq_new 
- * to require its own function.
- */
-
-struct ip_masq *ip_masq_new_pfvs(struct device *dev, int proto,
-                                struct server *rserver,
-                                __u32 saddr, __u16 sport,
-                                __u32 laddr, __u16 lport)
-{
-    struct ip_masq *ms;
-    static int n_fails = 0;
-    unsigned long flags;
-
-    ms = (struct ip_masq *) kmalloc(sizeof(struct ip_masq), GFP_ATOMIC);
-    if (ms == NULL) {
-       if (++n_fails < 5)
-           printk("ip_masq_new_s(proto=%s): no memory available.\n", masq_proto_name(proto));
-       return NULL;
-    }
-    memset(ms, 0, sizeof(*ms));
-    init_timer(&ms->timer);
-    ms->timer.data = (unsigned long) ms;
-    ms->timer.function = masq_expire;
-    ms->protocol = proto;
-    ms->saddr = rserver->ip;
-    ms->sport = rserver->port;
-    ms->daddr = saddr;
-    ms->dport = sport;
-    ms->maddr = laddr;
-    ms->mport = lport;
-    ms->flags = 0;
-    ms->app_data = NULL;
-    ms->control = NULL;
-    ms->real_server = rserver;
-
-    ip_masq_free_ports[masq_proto_num(proto)]++;
-
-    save_flags(flags);
-    cli();
-    ip_masq_hash(ms);
-    restore_flags(flags);
-
-    return ms;
-}
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
-
-
 /*
  *     Set masq expiration (deletion) and adds timer,
  *     if timeout==0 cancel expiration.
@@ -1491,10 +1365,6 @@ int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
        struct ip_autofw *af;
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
 
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-        struct server   *rserver;   /* real server chosen for this connection */
-#endif /* CONFIG_IP_MASQUERADE_IPPFVS */
-
        switch (iph->protocol) {
        case IPPROTO_ICMP:
                return(ip_fw_demasq_icmp(skb_p, dev));
@@ -1510,9 +1380,6 @@ int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
                    && !ip_autofw_check_direct(portptr[1], iph->protocol)
                    && !ip_autofw_check_port(portptr[1], iph->protocol)
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-                    && !ip_portfw_check(iph->protocol, portptr[1], iph->daddr)
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
                        )
                        return 0;
 
@@ -1581,24 +1448,6 @@ int ip_fw_demasquerade(struct sk_buff **skb_p, struct device *dev)
         }
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
 
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-       /* If no entry exists in the masquerading table, and the port is 
-          involved in port forwarding & virtual server table, 
-          create a new entry in the masquerading table */
-       if ((ms == NULL) &&
-           (iph->protocol == IPPROTO_TCP || iph->protocol == IPPROTO_UDP) &&
-           (rserver = ip_portfw_lookup(iph->protocol, portptr[1], iph->daddr))) {
-#ifdef DEBUG_CONFIG_IP_MASQUERADE
-               printk("ippfvs: Forwarding %s %1X:%X ==> %1X:%X\n",
-                      masq_proto_name(iph->protocol),
-                      ntohl(iph->daddr), ntohs(portptr[1]),
-                      ntohl(rserver->raddr), ntohs(rserver->rport));
-#endif
-               ms = ip_masq_new_pfvs(dev, iph->protocol, rserver,
-                                     iph->saddr, portptr[0], iph->daddr, portptr[1]);
-       }
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
-
         if (ms != NULL)
         {
 #ifdef CONFIG_IP_MASQUERADE_IPAUTOFW 
@@ -1753,71 +1602,6 @@ static int ip_autofw_procinfo(char *buffer, char **start, off_t offset,
 }
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
 
-
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-static int ip_portfw_procinfo(char *buffer, char **start, off_t offset,
-                             int length, int unused)
-{
-    off_t pos = 0, begin = 0;
-    struct ip_portfw *pf;
-    struct server *s;
-    unsigned long flags;
-    int ind, raddr, laddr;
-    int len = 0, last_len = 0;
-
-    len = sprintf(buffer, "IP Port Forwarding & Virtual Server Table\n");
-    len += sprintf(buffer + len, "Protocol Local Addr:Port ==> \n");
-    len += sprintf(buffer + len, "\t\t\tRemote Addr:Port \tWeight \tConnections\n");
-    len += sprintf(buffer + len, "\t\t\t...\n");
-
-    save_flags(flags);
-    cli();
-
-    for (ind = 0; ind < 2; ind++) {
-       for (pf = ipportfw_lst[ind]; pf; pf = pf->next) {
-           laddr = ntohl(pf->laddr);
-           len += sprintf(buffer + len, "%s      %d.%d.%d.%d:%d ==>\n",
-                          strProt[ind],
-                          (laddr >> 24) & 255, (laddr >> 16) & 255,
-                          (laddr >> 8) & 255, laddr & 255,
-                          ntohs(pf->lport));
-           if (len >= length)
-               goto done;
-
-           for (s = pf->sr_lst; s; s = s->next) {
-               raddr = ntohl(s->ip);
-               len += sprintf(buffer + len, 
-                              "\t\t\t%d.%d.%d.%d:%d    \t%d\t%d\n",
-                              (raddr >> 24) & 255, (raddr >> 16) & 255,
-                              (raddr >> 8) & 255, raddr & 255,
-                               ntohs(s->port), s->weight, s->connections);
-               if (len >= length)
-                   goto done;
-           }
-
-           pos = begin + len;
-           if (pos < offset) {
-               len = 0;
-               begin = pos;
-           } else if (pos > offset + length) {
-               len = last_len;
-               break;
-           }
-           last_len = len;
-
-       }
-    }
-  done:
-    restore_flags(flags);
-    *start = buffer + (offset - begin);
-    len -= (offset - begin);
-    if (len > length)
-       len = length;
-    return len;
-}
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
-
-
 static int ip_msqhst_procinfo(char *buffer, char **start, off_t offset,
                              int length, int unused)
 {
@@ -1903,14 +1687,6 @@ int ip_masq_init(void)
                ip_autofw_procinfo
        });
 #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-    proc_net_register(&(struct proc_dir_entry) {
-                     PROC_NET_IPPORTFW, 9, "ip_portfw",
-                     S_IFREG | S_IRUGO, 1, 0, 0,
-                     0, &proc_net_inode_operations,
-                     ip_portfw_procinfo
-                     });
-#endif                         /* CONFIG_IP_MASQUERADE_IPPFVS */
 #endif 
         ip_masq_app_init();
 
index 0552d348ed777c7464d0973900a1029478ec1b35..6784ca56b963f6ee4fa46eaa377d016bb2168504 100644 (file)
@@ -423,22 +423,6 @@ int ip_setsockopt(struct sock *sk, int level, int optname, char *optval, int opt
                        err=ip_autofw_ctl(optname, &tmp_fw,optlen);
                        return -err;    /* -0 is 0 after all */
                        
-#endif
-#ifdef CONFIG_IP_MASQUERADE_IPPFVS
-               case IP_PORTFW_ADD:
-               case IP_PORTFW_DEL:
-               case IP_PORTFW_FLUSH:
-                       if(!suser())
-                               return -EPERM;
-                       if(optlen>sizeof(tmp_fw) || optlen<1)
-                               return -EINVAL;
-                       err=verify_area(VERIFY_READ,optval,optlen);
-                       if(err)
-                               return err;
-                       memcpy_fromfs(&tmp_fw,optval,optlen);
-                       err=ip_portfw_ctl(optname, &tmp_fw,optlen);
-                       return -err;    /* -0 is 0 after all */
-                       
 #endif
 #ifdef CONFIG_IP_ACCT
                case IP_ACCT_INSERT:
index 22ae4bfc45cc2b1255355b5d07a710dc1eb11c49..12310ac8131630ed5ea49bf59896ed76c9ad15b1 100644 (file)
@@ -546,7 +546,10 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
        /* If the socket is dead, don't accept the connection. */
        if (!sk->dead) 
        {
-               sk->data_ready(sk,0);
+               /*
+                * This must wait for 3 way completion.
+                * sk->data_ready(sk,0);
+                */
        }
        else 
        {
@@ -889,7 +892,7 @@ static int tcp_conn_request_fake(struct sock *sk, struct sk_buff *skb,
        /* If the socket is dead, don't accept the connection. */
        if (!sk->dead) 
        {
-               sk->data_ready(sk,0);
+               /*sk->data_ready(sk,0); */
        }
        else 
        {