]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.16 1.3.16
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:09 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:09 +0000 (15:10 -0500)
91 files changed:
Makefile
arch/alpha/config.in
arch/i386/config.in
arch/i386/kernel/setup.c
arch/i386/mm/init.c
arch/mips/config.in
arch/sparc/config.in
drivers/block/blk.h
drivers/block/genhd.c
drivers/block/hd.c
drivers/block/ide.c
drivers/char/console.c
drivers/char/keyboard.c
drivers/char/scc.c
drivers/char/tty_io.c
drivers/char/vt.c
drivers/net/Space.c
drivers/net/at1700.c
drivers/net/atp.c
drivers/net/de4x5.c
drivers/net/hp100.c
drivers/net/ibmtr.c
drivers/net/lance.c
drivers/net/net_init.c
drivers/net/ni52.c
drivers/net/ni65.c
drivers/net/sk_g16.c
drivers/net/slip.c
drivers/net/slip.h
drivers/net/znet.c
drivers/pci/pci.c
drivers/scsi/aha152x.c
drivers/scsi/aic7xxx.c
drivers/scsi/buslogic.c
drivers/scsi/constants.h
drivers/scsi/eata_dma_proc.c
drivers/scsi/eata_pio.c
drivers/scsi/eata_pio.h
drivers/scsi/eata_pio_proc.c
drivers/scsi/hosts.h
drivers/scsi/scsi.c
drivers/scsi/scsi.h
drivers/scsi/sg.c
drivers/scsi/sr_ioctl.c
fs/binfmt_elf.c
fs/buffer.c
fs/ext2/truncate.c
fs/file_table.c
fs/minix/truncate.c
fs/msdos/inode.c
fs/open.c
fs/smbfs/inode.c
fs/smbfs/proc.c
fs/super.c
fs/sysv/dir.c
fs/umsdos/namei.c
include/asm-i386/page.h
include/asm-i386/pgtable.h
include/asm-i386/string.h
include/linux/etherdevice.h
include/linux/fs.h
include/linux/ip_fw.h
include/linux/mm.h
include/linux/net.h
include/linux/netdevice.h
include/linux/pci.h
include/linux/scc.h
include/linux/socket.h
include/linux/uio.h [new file with mode: 0644]
include/linux/xd.h
include/net/af_unix.h [new file with mode: 0644]
include/net/sock.h
include/net/unix.h [deleted file]
init/main.c
kernel/itimer.c
kernel/ksyms.c
kernel/sched.c
mm/memory.c
net/Changes
net/appletalk/ddp.c
net/core/Makefile
net/core/iovec.c [new file with mode: 0644]
net/ipv4/ip.c
net/ipv4/ip_fw.c
net/ipv4/rarp.c
net/protocols.c
net/socket.c
net/unix/Makefile
net/unix/af_unix.c [new file with mode: 0644]
net/unix/proc.c [deleted file]
net/unix/sock.c [deleted file]

index ccb3eaac93c88b0e24134027ec35fa60885f8d54..3e3d828d8cc77eb32a79a744204f325b3222f1ce 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 15
+SUBLEVEL = 16
 
 ARCH = i386
 
index df71673c356f9135f153fccc06435d25a4464bdf..95276a3a8431ee84567f78f85e21c1e6ebc35fb2 100644 (file)
@@ -122,7 +122,6 @@ bool 'Dummy net driver support' CONFIG_DUMMY n
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
 if [ "$CONFIG_PPP" = "y" ]; then
index afe0a061ba689bc6aae56c10c498d1070f48366a..4e870552ba0322a85c550e90dcd05f71a0d37e66 100644 (file)
@@ -132,7 +132,6 @@ bool 'Dummy net driver support' CONFIG_DUMMY y
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
 if [ "$CONFIG_PPP" = "y" ]; then
index 785aa33817cfd109b00e919f49454b20f6b6b893..a577225a792946b09edc8f39cd64afcdfee4fb7a 100644 (file)
@@ -39,7 +39,7 @@ int fdiv_bug = 0;             /* set if Pentium(TM) with FP bug */
 char x86_vendor_id[13] = "Unknown";
 
 char ignore_irq13 = 0;         /* set if exception 16 works */
-char wp_works_ok = 0;          /* set if paging hardware honours WP */ 
+char wp_works_ok = -1;         /* set if paging hardware honours WP */ 
 char hlt_works_ok = 1;         /* set if the "hlt" instruction works */
 
 /*
index c4bb3ee8b3dfd2ab7cab854eada147680b827066..d1742e1fa04ed1ec4abc9e36a20e97d0b35ed554 100644 (file)
@@ -114,11 +114,36 @@ unsigned long paging_init(unsigned long start_mem, unsigned long end_mem)
  */
 #if 0
        memset((void *) 0, 0, PAGE_SIZE);
+#endif
+#ifdef CONFIG_TEST_VERIFY_AREA
+       wp_works_ok = 0;
 #endif
        start_mem = PAGE_ALIGN(start_mem);
        address = 0;
        pg_dir = swapper_pg_dir;
        while (address < end_mem) {
+#ifdef CONFIG_PENTIUM_MM
+               if (address <= end_mem + 4*1024*1024 &&
+                   (x86_capability & 8)) {
+#ifdef GAS_KNOWS_CR4
+                       __asm__("movl %%cr4,%%eax\n\t"
+                               "orl $16,%%eax\n\t"
+                               "movl %%eax,%%cr4"
+                               : : :"ax");
+#else
+                       __asm__(".byte 0x0f,0x20,0xe0\n\t"
+                               "orl $16,%%eax\n\t"
+                               ".byte 0x0f,0x22,0xe0"
+                               : : :"ax");
+#endif
+                       wp_works_ok = 1;
+                       pgd_val(pg_dir[0]) = _PAGE_TABLE | _PAGE_4M | address;
+                       pgd_val(pg_dir[768]) = _PAGE_TABLE | _PAGE_4M | address;
+                       pg_dir++;
+                       address += 4*1024*1024;
+                       continue;
+               }
+#endif
                /* map the memory at virtual addr 0xC0000000 */
                pg_table = (pte_t *) (PAGE_MASK & pgd_val(pg_dir[768]));
                if (!pg_table) {
@@ -202,17 +227,15 @@ void mem_init(unsigned long start_mem, unsigned long end_mem)
                reservedpages << (PAGE_SHIFT-10),
                datapages << (PAGE_SHIFT-10));
 /* test if the WP bit is honoured in supervisor mode */
-       wp_works_ok = -1;
-       pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
-       invalidate();
-       __asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory");
-       pg0[0] = 0;
-       invalidate();
-       if (wp_works_ok < 0)
-               wp_works_ok = 0;
-#ifdef CONFIG_TEST_VERIFY_AREA
-       wp_works_ok = 0;
-#endif
+       if (wp_works_ok < 0) {
+               pg0[0] = pte_val(mk_pte(0, PAGE_READONLY));
+               invalidate();
+               __asm__ __volatile__("movb 0,%%al ; movb %%al,0": : :"ax", "memory");
+               pg0[0] = 0;
+               invalidate();
+               if (wp_works_ok < 0)
+                       wp_works_ok = 0;
+       }
        return;
 }
 
index 43fb922602226add85f2a192cdbf67bb4efc5c5c..3891b71913e2b9ac70df063bb1b4d84fa3e5c113 100644 (file)
@@ -108,7 +108,6 @@ bool 'Dummy net driver support' CONFIG_DUMMY n
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
index 6fab6963db180519c331bae20f9e5a0f8cf9ee74..6c66331a3d4079964b964d9eb5094382930b6ee8 100644 (file)
@@ -76,7 +76,6 @@ bool 'Dummy net driver support' CONFIG_DUMMY n
 bool 'SLIP (serial line) support' CONFIG_SLIP n
 if [ "$CONFIG_SLIP" = "y" ]; then
   bool ' CSLIP compressed headers' SL_COMPRESSED y
-  bool ' 16 channels instead of 4' SL_SLIP_LOTS n
 #  bool ' SLIP debugging on' SL_DUMP y
 fi
 bool 'PPP (point-to-point) support' CONFIG_PPP n
index c3e4558e4b08435df554d7253e96dd1eab00daa4..0559579fb5474817c1be9992511708c86bdad493 100644 (file)
@@ -80,7 +80,9 @@ extern void rd_load(void);
 extern long rd_init(long mem_start, int length);
 extern int ramdisk_size;
 
+#ifdef CONFIG_BLK_DEV_XD
 extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end);
+#endif
 
 #define RO_IOCTLS(dev,where) \
   case BLKROSET: if (!suser()) return -EACCES; \
index f68db26f38dd440841cbe4bf480ec0192650307a..6b255be88ddc4aa10f7509e14b8c27f9610bc1bc 100644 (file)
@@ -113,12 +113,15 @@ done:
 
 static int msdos_partition(struct gendisk *hd, unsigned int dev, unsigned long first_sector)
 {
-       int i, minor = current_minor, tested_for_dm6 = 0;
+       int i, minor = current_minor;
        struct buffer_head *bh;
        struct partition *p;
        int mask = (1 << hd->minor_shift) - 1;
+#ifdef CONFIG_BLK_DEV_IDE
+       int tested_for_dm6 = 0;
 
 read_mbr:
+#endif
        if (!(bh = bread(dev,0,1024))) {
                printk(" unable to read partition table\n");
                return -1;
index f6561f57458b642a65283061b907c96514ee54e5..8970d2c59e09050a63d4c35825f67b15beae8082 100644 (file)
@@ -128,7 +128,7 @@ void hd_setup(char *str, int *ints)
        NR_HD = hdind+1;
 }
 
-static void dump_status (char *msg, unsigned int stat)
+static void dump_status (const char *msg, unsigned int stat)
 {
        unsigned long flags;
        char devc;
index fb771a907ef073886e38e981d05a1fdc5c73c308..bf4f0a5a8b4acb7de4e824bf8c8ec6f702d5cbac 100644 (file)
@@ -1753,8 +1753,9 @@ static void do_identify (ide_dev_t *dev, byte cmd)
        bswap = 1;
        if (cmd == WIN_PIDENTIFY) {
                if ((id->model[0] == 'N' && id->model[1] == 'E')
-                || (id->model[0] == 'F' && id->model[1] == 'X'))
-                       bswap = 0;      /* NEC and *some* Mitsumi units */
+                || (id->model[0] == 'F' && id->model[1] == 'X')
+                || (id->model[0] == 'P' && id->model[1] == 'i'))
+                       bswap = 0;      /* NEC, Pioneer and *some* Mitsumi units */
        }                               /* Vertos drives may still be weird */
        fixstring (id->model,     sizeof(id->model),     bswap);
        fixstring (id->fw_rev,    sizeof(id->fw_rev),    bswap);
index 25056cd236798a206dff9b00bc3613127294c2f0..17c7a1ef501d8de61ae472ccce5e7df52f24535e 100644 (file)
@@ -154,7 +154,6 @@ extern void register_console(void (*proc)(const char *));
 extern void vesa_blank(void);
 extern void vesa_unblank(void);
 extern void compute_shiftstate(void);
-extern int conv_uni_to_pc(long ucs);
 extern void reset_palette (int currcons) ;
 extern void set_palette (void) ;
 
index 500247e534667b98ba1846aa14fbc0b4a6823e90..32336af4c71984dfbdeb844de4d79fd0f0618bcd 100644 (file)
@@ -73,7 +73,6 @@ extern void reset_vc(unsigned int new_console);
 extern void change_console(unsigned int new_console);
 extern void scrollback(int);
 extern void scrollfront(int);
-extern int vc_cons_allocated(unsigned int);
 
 #ifdef __i386__
 #define fake_keyboard_interrupt() __asm__ __volatile__("int $0x21")
index 5a6658dce6f8e241a8cb7ea103608d6b52d86083..e7d445f6830a4e6029ddaccf491ec03f559a9dd2 100644 (file)
 #include <asm/segment.h>
 #include <asm/bitops.h>
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <time.h>
 #include <linux/kernel.h>
 
 
-long scc_init(long kmem_start);
-
 int scc_open(struct tty_struct *tty, struct file *filp);
 static void scc_close(struct tty_struct *tty, struct file *filp);
 int scc_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
index 992af730a9c2c7c8d0a4ec6ba31a0ca732ec9b4f..f2c5681e98c6995b0efd9e39f3b746a8a2b5b94d 100644 (file)
@@ -73,7 +73,6 @@
 #define CHECK_TTY_COUNT
 
 extern void do_blank_screen(int nopowersave);
-extern void do_unblank_screen(void);
 extern void set_vesa_blanking(const unsigned long arg);
 
 struct termios tty_std_termios;                /* for the benefit of tty drivers  */
index 53d96e625ba1c60fa00f8b084b1009bde8c4f8ba..5a50ef1655f539d7d185fdabfd860ebd32f46a92 100644 (file)
@@ -29,7 +29,6 @@
 #include "selection.h"
 
 extern struct tty_driver console_driver;
-extern int sel_cons;
 
 #define VT_IS_IN_USE(i)        (console_driver.table[i] && console_driver.table[i]->count)
 #define VT_BUSY(i)     (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
@@ -58,7 +57,6 @@ extern void change_console(unsigned int new_console);
 extern void complete_change_console(unsigned int new_console);
 extern int vt_waitactive(void);
 extern void do_blank_screen(int nopowersave);
-extern void do_unblank_screen(void);
 
 extern unsigned int keymap_count;
 
index d40ee071fbd0e7eb7b2c603fd8c7d7720e403cb0..f1fccbb806d51924a192b47a76c6dac581f7a2fb 100644 (file)
@@ -241,76 +241,13 @@ static struct device eth0_dev = {
 #endif  /* PLIP */
 
 #if defined(SLIP) || defined(CONFIG_SLIP)
-    extern int slip_init(struct device *);
-    
-#ifdef SL_SLIP_LOTS
-
-    static struct device slip15_dev={"sl15",0,0,0,0,15,0,0,0,0,NEXT_DEV,slip_init};
-    static struct device slip14_dev={"sl14",0,0,0,0,14,0,0,0,0,&slip15_dev,slip_init};
-    static struct device slip13_dev={"sl13",0,0,0,0,13,0,0,0,0,&slip14_dev,slip_init};
-    static struct device slip12_dev={"sl12",0,0,0,0,12,0,0,0,0,&slip13_dev,slip_init};
-    static struct device slip11_dev={"sl11",0,0,0,0,11,0,0,0,0,&slip12_dev,slip_init};
-    static struct device slip10_dev={"sl10",0,0,0,0,10,0,0,0,0,&slip11_dev,slip_init};
-    static struct device slip9_dev={"sl9",0,0,0,0,9,0,0,0,0,&slip10_dev,slip_init};
-    static struct device slip8_dev={"sl8",0,0,0,0,8,0,0,0,0,&slip9_dev,slip_init};
-    static struct device slip7_dev={"sl7",0,0,0,0,7,0,0,0,0,&slip8_dev,slip_init};
-    static struct device slip6_dev={"sl6",0,0,0,0,6,0,0,0,0,&slip7_dev,slip_init};
-    static struct device slip5_dev={"sl5",0,0,0,0,5,0,0,0,0,&slip6_dev,slip_init};
-    static struct device slip4_dev={"sl4",0,0,0,0,4,0,0,0,0,&slip5_dev,slip_init};
-#   undef      NEXT_DEV
-#   define     NEXT_DEV        (&slip4_dev)
-#endif /* SL_SLIP_LOTS */
-    
-    static struct device slip3_dev = {
-       "sl3",                  /* Internal SLIP driver, channel 3      */
-       0x0,                    /* recv memory end                      */
-       0x0,                    /* recv memory start                    */
-       0x0,                    /* memory end                           */
-       0x0,                    /* memory start                         */
-       0x3,                    /* base I/O address                     */
-       0,                      /* IRQ                                  */
-       0, 0, 0,                /* flags                                */
-       NEXT_DEV,               /* next device                          */
-       slip_init               /* slip_init should set up the rest     */
-    };
-    static struct device slip2_dev = {
-       "sl2",                  /* Internal SLIP driver, channel 2      */
-       0x0,                    /* recv memory end                      */
-       0x0,                    /* recv memory start                    */
-       0x0,                    /* memory end                           */
-       0x0,                    /* memory start                         */
-       0x2,                    /* base I/O address                     */
-       0,                      /* IRQ                                  */
-       0, 0, 0,                /* flags                                */
-       &slip3_dev,             /* next device                          */
-       slip_init               /* slip_init should set up the rest     */
-    };
-    static struct device slip1_dev = {
-       "sl1",                  /* Internal SLIP driver, channel 1      */
-       0x0,                    /* recv memory end                      */
-       0x0,                    /* recv memory start                    */
-       0x0,                    /* memory end                           */
-       0x0,                    /* memory start                         */
-       0x1,                    /* base I/O address                     */
-       0,                      /* IRQ                                  */
-       0, 0, 0,                /* flags                                */
-       &slip2_dev,             /* next device                          */
-       slip_init               /* slip_init should set up the rest     */
-    };
-    static struct device slip0_dev = {
-       "sl0",                  /* Internal SLIP driver, channel 0      */
-       0x0,                    /* recv memory end                      */
-       0x0,                    /* recv memory start                    */
-       0x0,                    /* memory end                           */
-       0x0,                    /* memory start                         */
-       0x0,                    /* base I/O address                     */
-       0,                      /* IRQ                                  */
-       0, 0, 0,                /* flags                                */
-       &slip1_dev,             /* next device                          */
-       slip_init               /* slip_init should set up the rest     */
-    };
-#   undef      NEXT_DEV
-#   define     NEXT_DEV        (&slip0_dev)
+       /* To be exact, this node just hooks the initialization
+          routines to the device structures.                   */
+extern int slip_init_ctrl_dev(struct device *);
+static struct device slip_bootstrap = {
+  "slip_proto", 0x0, 0x0, 0x0, 0x0, 0, 0, 0, 0, 0, NEXT_DEV, slip_init_ctrl_dev, };
+#undef NEXT_DEV
+#define NEXT_DEV (&slip_bootstrap)
 #endif /* SLIP */
   
 #if defined(CONFIG_PPP)
@@ -388,7 +325,6 @@ struct device eql_dev = {
 #   define     NEXT_DEV        (&ibmtr_dev1)
 
 
-    extern int tok_probe(struct device *dev);
     static struct device ibmtr_dev0 = {
        "tr0",                  /* IBM Token Ring (Non-DMA) Interface */
        0x0,                    /* recv memory end                      */
index 45128b29dd44e2c68817103cdaa31238754dc5e1..da01976de2e4f5c6d6ec164458883c82e41b3267 100644 (file)
@@ -571,7 +571,6 @@ net_rx(struct device *dev)
 /* The inverse routine to net_open(). */
 static int net_close(struct device *dev)
 {
-       struct net_local *lp = (struct net_local *)dev->priv;
        int ioaddr = dev->base_addr;
 
        dev->tbusy = 1;
index bf097a705d5ea4a81fc1202e23cd530e01ad1115..2750e28a2e620263554b6ff97df7a85cb5ea9450 100644 (file)
@@ -213,7 +213,7 @@ static int atp_probe1(struct device *dev, short ioaddr)
        /* Read the station address PROM.  */
        get_node_ID(dev);
 
-       printk("%s: Pocket adapter found at %#3x, IRQ %d, SAPROM "
+       printk("%s: Pocket adapter found at %#3lx, IRQ %d, SAPROM "
                   "%02X:%02X:%02X:%02X:%02X:%02X.\n", dev->name, dev->base_addr,
                   dev->irq, dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
                   dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
index ea33135ba0b7bf952bac235c4232cddb766fdf89..c43608203ced18cd7b035a41b1f130c84f131054 100644 (file)
@@ -1380,8 +1380,8 @@ static void load_packet(struct device *dev, char *buf, u32 flags, struct sk_buff
 }
 /*
 ** Set or clear the multicast filter for this adaptor.
-** num_addrs == -1     Promiscuous mode, receive all packets - not supported.
-**                      Use the ioctls.
+** num_addrs == -1     Promiscuous mode, receive all packets - now supported.
+**                      Can also use the ioctls.
 ** num_addrs == 0      Normal mode, clear multicast list
 ** num_addrs > 0       Multicast mode, receive normal and MC packets, and do
 **                     best-effort filtering.
@@ -1409,6 +1409,11 @@ set_multicast_list(struct device *dev, int num_addrs, void *addrs)
       lp->tx_new = (++lp->tx_new) % lp->txRingSize;
       outl(POLL_DEMAND, DE4X5_TPD);                /* Start the TX */
       dev->trans_start = jiffies;
+    } else { /* set promiscuous mode */
+      u32 omr;
+      omr = inl(DE4X5_OMR);
+      omr |= OMR_PR;
+      outl(omr, DE4X5_OMR);
     }
   }
 
@@ -1472,6 +1477,9 @@ static void SetMulticastFilter(struct device *dev, int num_addrs, char *addrs)
       }
     }
   }
+
+  if (num_addrs == 0)
+    omr &= ~OMR_PR;
   outl(omr, DE4X5_OMR);
 
   return;
index 3db397c636747e0e27c054e27b500eb80edbae3d..e7fc09975d9b9e868478d7d83822bbb93e89d51c 100644 (file)
  *
  *   Variable                   Description
  *
- *   hp100_default_rx_ratio    Range 1-99 - onboard memory used for RX 
+ *   hp100_rx_ratio            Range 1-99 - onboard memory used for RX
  *                              packets in %.
+ *   hp100_priority_tx         If this variable is nonzero - all outgoing
+ *                              packets will be transmitted as priority.
  *   hp100_port                        Adapter port (for example 0x380).
  *
  * ----------------------------------------------------------------------------
  * TO DO:
  * ======
  *       - ioctl handling - some runtime setup things
- *       - high priority communications support
- *       - memory mapped access support for PCI cards
+ *       - 100Mb/s Voice Grade AnyLAN network adapter/hub services support
+ *             - 802.5 frames
+ *             - promiscuous mode
+ *             - bridge mode
+ *             - cascaded repeater mode
+ *             - 100Mbit MAC
  *
  * Revision history:
  * =================
@@ -70,6 +76,9 @@
  *      0.12    14-Jul-95   Link down is now handled better.
  *      0.20    01-Aug-95   Added PCI support for HP J2585A card.
  *                          Statistics bug fixed.
+ *      0.21    04-Aug-95   Memory mapped access support for PCI card.
+ *                          Added priority transmit support for 100Mb/s
+ *                          Voice Grade AnyLAN network.
  *
  */
 
 #define HP100_MAX_PACKET_SIZE  (1536+4)
 #define HP100_MIN_PACKET_SIZE  60
 
-#ifndef HP100_RX_RATIO
+#ifndef HP100_DEFAULT_RX_RATIO
 /* default - 65% onboard memory on the card are used for RX packets */
-#define HP100_RX_RATIO         65
+#define HP100_DEFAULT_RX_RATIO 65
+#endif
+
+#ifndef HP100_DEFAULT_PRIORITY_TX
+/* default - don't enable transmit outgoing packets as priority */
+#define HP100_DEFAULT_PRIORITY_TX 0
 #endif
 
 /*
@@ -130,9 +144,11 @@ struct hp100_private {
   struct hp100_eisa_id *id;
   u_short soft_model;
   u_int memory_size;
-  u_short rx_ratio;
+  u_short rx_ratio;                /* 1 - 99 */
+  u_short priority_tx;             /* != 0 - priority tx */
   short mem_mapped;                /* memory mapped access */
-  u_char *mem_ptr;                 /* pointer to memory mapped area */
+  u_char *mem_ptr_virt;                    /* virtual memory mapped area, maybe NULL */
+  u_char *mem_ptr_phys;                    /* physical memory mapped area */
   short lan_type;                  /* 10Mb/s, 100Mb/s or -1 (error) */
   int hub_status;                  /* login to hub was successfull? */
   u_char mac1_mode;
@@ -166,9 +182,8 @@ static struct hp100_eisa_id hp100_eisa_ids[] = {
   { 0x01030103c, "HP J2585",      HP100_BUS_PCI },
 };
 
-#ifdef MODULE
-int hp100_default_rx_ratio = HP100_RX_RATIO;
-#endif
+int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
+int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
 
 /*
  *  prototypes
@@ -292,7 +307,7 @@ static int hp100_probe1( struct device *dev, int ioaddr, int bus )
   u_char uc, uc_1;
   u_int eisa_id;
   short mem_mapped;
-  u_char *mem_ptr;
+  u_char *mem_ptr_phys, *mem_ptr_virt;
   struct hp100_private *lp;
   struct hp100_eisa_id *eid;
 
@@ -366,30 +381,30 @@ static int hp100_probe1( struct device *dev, int ioaddr, int bus )
   hp100_page( HW_MAP );
   mem_mapped = ( hp100_inw( OPTION_LSW ) & 
                  ( HP100_MEM_EN | HP100_BM_WRITE | HP100_BM_READ ) ) != 0;
-  mem_ptr = NULL;
+  mem_ptr_phys = mem_ptr_virt = NULL;
   if ( mem_mapped )
     {
-      mem_ptr = (u_char *)( hp100_inw( MEM_MAP_LSW ) | 
-                            ( hp100_inw( MEM_MAP_MSW ) << 16 ) );
-      (u_int)mem_ptr &= ~0x1fff;       /* 8k aligment */
-      if ( bus == HP100_BUS_ISA && ( (u_int)mem_ptr & ~0xfffff ) != 0 )
+      mem_ptr_phys = (u_char *)( hp100_inw( MEM_MAP_LSW ) | 
+                               ( hp100_inw( MEM_MAP_MSW ) << 16 ) );
+      (u_int)mem_ptr_phys &= ~0x1fff;  /* 8k aligment */
+      if ( bus == HP100_BUS_ISA && ( (u_long)mem_ptr_phys & ~0xfffff ) != 0 )
         {
-          mem_ptr = NULL;
+          mem_ptr_phys = NULL;
           mem_mapped = 0;
         }
       if ( mem_mapped && bus == HP100_BUS_PCI )
         {
-#if 0
-          printk( "writeb !!!\n" );
-          writeb( 0, mem_ptr );
-#endif
-          mem_ptr = NULL;
-          mem_mapped = 0;
+          if ( ( mem_ptr_virt = vremap( (u_long)mem_ptr_phys, 0x2000 ) ) == NULL )
+            {
+              printk( "hp100: vremap for high PCI memory at 0x%lx failed\n", (u_long)mem_ptr_phys );
+              mem_ptr_phys = NULL;
+              mem_mapped = 0;
+            }
         }
     }
 #else
   mem_mapped = 0;
-  mem_ptr = NULL;
+  mem_ptr_phys = mem_ptr_virt = NULL;
 #endif
 
   if ( ( dev -> priv = kmalloc( sizeof( struct hp100_private ), GFP_KERNEL ) ) == NULL )
@@ -399,7 +414,8 @@ static int hp100_probe1( struct device *dev, int ioaddr, int bus )
   lp = (struct hp100_private *)dev -> priv;
   lp -> id = eid;
   lp -> mem_mapped = mem_mapped;
-  lp -> mem_ptr = mem_ptr;
+  lp -> mem_ptr_phys = mem_ptr_phys;
+  lp -> mem_ptr_virt = mem_ptr_virt;
   hp100_page( ID_MAC_ADDR );
   lp -> soft_model = hp100_inb( SOFT_MODEL );
   lp -> mac1_mode = HP100_MAC1MODE3;
@@ -410,11 +426,7 @@ static int hp100_probe1( struct device *dev, int ioaddr, int bus )
   dev -> irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQ_MASK;
   if ( dev -> irq == 2 ) dev -> irq = 9;
   lp -> memory_size = 0x200 << ( ( hp100_inb( SRAM ) & 0xe0 ) >> 5 );
-#ifndef MODULE
-  lp -> rx_ratio = HP100_RX_RATIO;
-#else
-  lp -> rx_ratio = hp100_default_rx_ratio;
-#endif
+  lp -> rx_ratio = hp100_rx_ratio;
 
   dev -> open = hp100_open;
   dev -> stop = hp100_close;
@@ -446,8 +458,13 @@ static int hp100_probe1( struct device *dev, int ioaddr, int bus )
   printk( " bus, %dk SRAM (rx/tx %d%%).\n",
     lp -> memory_size >> ( 10 - 4 ), lp -> rx_ratio );
   if ( mem_mapped )
-    printk( "%s: Memory mapped access used at 0x%x-0x%x.\n", 
-               dev -> name, (u_int)mem_ptr, (u_int)mem_ptr + 0x1fff );
+    {
+      printk( "%s: Memory area at 0x%lx-0x%lx",
+               dev -> name, (u_long)mem_ptr_phys, (u_long)mem_ptr_phys + 0x1fff );
+      if ( mem_ptr_virt )
+        printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt );
+      printk( ".\n" );
+    }
   printk( "%s: ", dev -> name );
   if ( lp -> lan_type != HP100_LAN_ERR )
     printk( "Adapter is attached to " );
@@ -507,12 +524,9 @@ static int hp100_open( struct device *dev )
               HP100_IO_EN | HP100_SET_LB, OPTION_LSW );
   hp100_outw( HP100_DEBUG_EN | HP100_RX_HDR | HP100_EE_EN | HP100_RESET_HB |
               HP100_FAKE_INT | HP100_RESET_LB, OPTION_LSW );
-#if 0
-  hp100_outw( HP100_PRIORITY_TX | HP100_ADV_NXT_PKT | 
-              HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW );
-#else
-  hp100_outw( HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB, OPTION_MSW );
-#endif
+  hp100_outw( HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB |
+                HP100_PRIORITY_TX | ( hp100_priority_tx ? HP100_SET_HB : HP100_RESET_HB ),
+              OPTION_MSW );
                                        
   hp100_page( MAC_ADDRESS );
   for ( i = 0; i < 6; i++ )
@@ -569,7 +583,7 @@ static int hp100_close( struct device *dev )
 
 static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
 {
-  int i;
+  int i, ok_flag;
   int ioaddr = dev -> base_addr;
   u_short val;
   struct hp100_private *lp = (struct hp100_private *)dev -> priv;
@@ -653,39 +667,31 @@ static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
 #ifdef HP100_DEBUG_TX
   printk( "hp100_start_xmit: irq_status = 0x%x, len = %d\n", val, (int)skb -> len );
 #endif
+  ok_flag = skb -> len >= HP100_MIN_PACKET_SIZE;
+  i = ok_flag ? skb -> len : HP100_MIN_PACKET_SIZE;
+  hp100_outw( i, DATA32 );             /* length to memory manager */
+  hp100_outw( i, FRAGMENT_LEN );
   if ( lp -> mem_mapped )
     {
-      if ( skb -> len >= HP100_MIN_PACKET_SIZE )
+      if ( lp -> mem_ptr_virt )
         {
-          hp100_outw( skb -> len, DATA32 );    /* length to memory manager */
-          hp100_outw( skb -> len, FRAGMENT_LEN );
-          memcpy_toio( lp -> mem_ptr, skb -> data, skb -> len );
+          memcpy( lp -> mem_ptr_virt, skb -> data, skb -> len );
+          if ( !ok_flag )
+            memset( lp -> mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb -> len );
         }
        else
         {
-          hp100_outw( HP100_MIN_PACKET_SIZE, DATA32 ); /* length to memory manager */
-          hp100_outw( HP100_MIN_PACKET_SIZE, FRAGMENT_LEN );
-          memcpy_toio( lp -> mem_ptr, skb -> data, skb -> len );
-          memset_io( lp -> mem_ptr, 0, HP100_MIN_PACKET_SIZE - skb -> len );
+          memcpy_toio( lp -> mem_ptr_phys, skb -> data, skb -> len );
+          if ( !ok_flag )
+            memset_io( lp -> mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb -> len );
         }
     }
    else
     {
-      if ( skb -> len >= HP100_MIN_PACKET_SIZE )
-        {
-          hp100_outw( skb -> len, DATA32 );    /* length to memory manager */
-          hp100_outw( skb -> len, FRAGMENT_LEN );
-          outsl( ioaddr + HP100_REG_DATA32, skb -> data, ( skb -> len + 3 ) >> 2 );
-        }
-       else
-        {
-          hp100_outw( HP100_MIN_PACKET_SIZE, DATA32 ); /* length to memory manager */
-          hp100_outw( HP100_MIN_PACKET_SIZE, FRAGMENT_LEN );
-          i = skb -> len + 3;
-          outsl( ioaddr + HP100_REG_DATA32, skb -> data, i >> 2 );
-          for ( i &= ~3; i < HP100_MIN_PACKET_SIZE; i += 4 ) 
-            hp100_outl( 0, DATA32 );
-        }
+      outsl( ioaddr + HP100_REG_DATA32, skb -> data, ( skb -> len + 3 ) >> 2 );
+      if ( !ok_flag )
+        for ( i = ( skb -> len + 3 ) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4 )
+          hp100_outl( 0, DATA32 );
     }
   hp100_outw( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */
   lp -> stats.tx_packets++;
@@ -735,7 +741,15 @@ static void hp100_rx( struct device *dev )
           printk( "hp100_rx: busy, remaining packets = %d\n", packets );
 #endif    
         }
-      header = lp -> mem_mapped ? readl( lp -> mem_ptr ) : hp100_inl( DATA32 );
+      if ( lp -> mem_mapped )
+        {
+          if ( lp -> mem_ptr_virt )
+            header = *(__u32 *)lp -> mem_ptr_virt;
+           else
+            header = readl( lp -> mem_ptr_phys );
+        }
+       else
+        header = hp100_inl( DATA32 );
       pkt_len = header & HP100_PKT_LEN_MASK;
 #ifdef HP100_DEBUG_RX
       printk( "hp100_rx: new packet - length = %d, errors = 0x%x, dest = 0x%x\n",
@@ -761,7 +775,12 @@ static void hp100_rx( struct device *dev )
           skb -> dev = dev;
           ptr = (u_char *)skb_put( skb, pkt_len );
           if ( lp -> mem_mapped )
-            memcpy_fromio( ptr, lp -> mem_ptr, ( pkt_len + 3 ) & ~3 );
+            {
+              if ( lp -> mem_ptr_virt )
+                memcpy( ptr, lp -> mem_ptr_virt, ( pkt_len + 3 ) & ~3 );
+               else
+                memcpy_fromio( ptr, lp -> mem_ptr_phys, ( pkt_len + 3 ) & ~3 );
+            }
            else
             insl( ioaddr + HP100_REG_DATA32, ptr, ( pkt_len + 3 ) >> 2 );
           skb -> protocol = eth_type_trans( skb, dev );
@@ -869,7 +888,7 @@ static void hp100_set_multicast_list( struct device *dev, int num_addrs, void *a
       lp -> mac1_mode = HP100_MAC1MODE5;  /* broadcasts and all multicasts */
     }
    else
-     {
+    {
       lp -> mac2_mode = HP100_MAC2MODE3;  /* normal mode, packets for me */
       lp -> mac1_mode = HP100_MAC1MODE3;  /* and broadcasts */
     }
@@ -1116,8 +1135,10 @@ static struct device dev_hp100 = {
 
 int init_module( void )
 {
-  if ( hp100_port > 0 ) dev_hp100.base_addr = hp100_port;
-  if ( register_netdev( &dev_hp100 ) != 0 ) return -EIO;
+  if ( hp100_port > 0 )
+    dev_hp100.base_addr = hp100_port;
+  if ( register_netdev( &dev_hp100 ) != 0 )
+    return -EIO;
   return 0;
 }         
 
@@ -1125,6 +1146,8 @@ void cleanup_module( void )
 {
   unregister_netdev( &dev_hp100 );
   release_region( dev_hp100.base_addr, HP100_REGION_SIZE );
+  if ( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt )
+    vfree( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt );
   kfree_s( dev_hp100.priv, sizeof( struct hp100_private ) );
   dev_hp100.priv = NULL;
 }
index bfdfabb5eeb11b25a17b8c577291f55686ea99c3..f2ca91ee65db2c2816da2b8dc10306976db69837 100644 (file)
@@ -349,7 +349,10 @@ int tok_probe(struct device *dev) {
   ti->page_mask=0;
   if (ti->shared_ram_paging == 0xf) { /* No paging in adapter */
     ti->mapped_ram_size = ti->avail_shared_ram;
-  } else { unsigned char pg_size;
+  } else {
+#ifdef ENABLE_PAGING
+    unsigned char pg_size;
+#endif
 
        DPRINTK("shared ram page size: %dK\n",ti->mapped_ram_size/2);
 #ifdef ENABLE_PAGING
index d10c96a62203383088f2704b66bb3e0e0b317883..b78994c3fb08c3ab5b4e17b5b94f4704c8bd02f4 100644 (file)
@@ -285,7 +285,7 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
                printk("lance.c: PCI bios is present, checking for devices...\n");
                for (pci_index = 0; pci_index < 8; pci_index++) {
                        unsigned char pci_bus, pci_device_fn;
-                       unsigned long pci_ioaddr;
+                       unsigned int pci_ioaddr;
                        unsigned short pci_command;
 
                        if (pcibios_find_device (PCI_VENDOR_ID_AMD,
@@ -310,7 +310,7 @@ unsigned long lance_init(unsigned long mem_start, unsigned long mem_end)
                                pcibios_write_config_word(pci_bus, pci_device_fn,
                                                                                  PCI_COMMAND, pci_command);
                        }
-                       printk("Found PCnet/PCI at %#lx, irq %d (mem_start is %#lx).\n",
+                       printk("Found PCnet/PCI at %#x, irq %d (mem_start is %#lx).\n",
                                   pci_ioaddr, pci_irq_line, mem_start);
                        mem_start = lance_probe1(pci_ioaddr, mem_start);
                        pci_irq_line = 0;
index 7e3fd03213c045997436f475ce223d18e1e10904..87d13b2b65b900dc5f7cfa35e74598ebdf575791 100644 (file)
@@ -314,33 +314,37 @@ void unregister_netdev(struct device *dev)
 
        printk("unregister_netdev: device ");
 
-       if (dev == NULL) {
+       if (dev == NULL) 
+       {
                printk("was NULL\n");
                restore_flags(flags);
                return;
        }
        /* else */
        if (dev->start)
-               printk("'%s' busy\n", dev->name);
-       else {
-               if (dev_base == dev)
-                       dev_base = dev->next;
-               else {
-                       while (d && (d->next != dev))
-                               d = d->next;
-
-                       if (d && (d->next == dev)) {
-                               d->next = dev->next;
-                               printk("'%s' unlinked\n", dev->name);
-                       }
-                       else {
-                               printk("'%s' not found\n", dev->name);
-                               restore_flags(flags);
-                               return;
-                       }
+               printk("ERROR '%s' busy and not MOD_IN_USE.\n", dev->name);
+       if (dev_base == dev)
+               dev_base = dev->next;
+       else 
+       {
+               while (d && (d->next != dev))
+                       d = d->next;
+                       
+               if (d && (d->next == dev)) 
+               {
+                       d->next = dev->next;
+                       printk("'%s' unlinked\n", dev->name);
+               }
+               else 
+               {
+                       printk("'%s' not found\n", dev->name);
+                       restore_flags(flags);
+                       return;
                }
-               for (i = 0; i < MAX_ETH_CARDS; ++i) {
-                       if (ethdev_index[i] == dev) {
+               for (i = 0; i < MAX_ETH_CARDS; ++i) 
+               {
+                       if (ethdev_index[i] == dev) 
+                       {
                                ethdev_index[i] = NULL;
                                break;
                        }
index c8961868d075b07e3ad889fe79ca2ffb2219b0f2..4ba45e7a131c8ddfb8e3752902d7bf136983c4f2 100644 (file)
@@ -146,9 +146,6 @@ sizeof(nop_cmd) = 8;
       printk("%s: scb_cmd timed out .. resetting i82586\n",dev->name); \
       ni_reset586(); } } }
 
-extern void autoirq_setup(int waittime);
-extern int  autoirq_report(int waittime);
-extern void *irq2dev_map[16];
 
 #define NI52_TOTAL_SIZE 16
 #define NI52_ADDR0 0x02
@@ -357,7 +354,7 @@ static int ni52_probe1(struct device *dev,int ioaddr)
                                     || dev->dev_addr[2] != NI52_ADDR2)
     return ENODEV;
 
-  printk("%s: Ni52 found at %#3x, ",dev->name,dev->base_addr);
+  printk("%s: Ni52 found at %#3lx, ",dev->name,dev->base_addr);
 
   request_region(ioaddr,NI52_TOTAL_SIZE,"ni52");
 
index bf07ef9826ca621adfbc5e28682ea6242f803605..342a48d1845f7f3da83548ac7cc6430e60ff0e46 100644 (file)
@@ -123,8 +123,6 @@ static struct enet_statistics *ni65_get_stats(struct device *);
 
 static void set_multicast_list(struct device *dev, int num_addrs, void *addrs);
 
-extern void *irq2dev_map[16];
-
 struct priv 
 {
   struct init_block ib; 
@@ -223,7 +221,7 @@ static int ni65_probe1(struct device *dev,int ioaddr)
   if(dev->dma == 0)  
     dev->dma = dmatab[inw(PORT+L_CONFIG)&3];
 
-  printk("%s: %s found at %#3x, IRQ %d DMA %d.\n", dev->name,
+  printk("%s: %s found at %#3lx, IRQ %d DMA %d.\n", dev->name,
            "network card", dev->base_addr, dev->irq,dev->dma);
 
   {        
index 4cd79401aef896808fa03f09510b28e7d2119c3c..0924fd350d90b92e53b567ac0d6f701dacd339f4 100644 (file)
@@ -465,7 +465,7 @@ struct priv
 
 /* IRQ map used to reserve a IRQ (see SK_open()) */
 
-extern void *irq2dev_map[16]; 
+/* extern void *irq2dev_map[16]; */ /* Declared in <linux/ioport.h> */
 
 /* static variables */
 
@@ -2045,10 +2045,10 @@ void SK_print_dev(struct device *dev, char *text)
     else
     {
        printk("## %s: Device Structure. %s\n", SK_NAME, text);
-       printk("## Device Name: %s Base Address: %#06x IRQ: %d\n", 
+       printk("## Device Name: %s Base Address: %#06lx IRQ: %d\n", 
                dev->name, dev->base_addr, dev->irq);
               
-       printk("##   FLAGS: start: %d tbusy: %d int: %d\n", 
+       printk("##   FLAGS: start: %d tbusy: %ld int: %d\n", 
                dev->start, dev->tbusy, dev->interrupt);
 
        printk("## next device: %#08x init function: %#08x\n", 
index 8fb0ba9e88a9fe04e1465599b33199d3221f0f28..467628d91186c9cac008d8a7c539b8ce138777a8 100644 (file)
  *                                      if it really needed.
  *             Alan Cox        :       Free slhc buffers in the right place.
  *             Alan Cox        :       Allow for digipeated IP over AX.25
+ *             Matti Aarnio    :       Dynamic SLIP devices, with ideas taken
+ *                                     from Jim Freeman's <jfree@caldera.com>
+ *                                     dynamic PPP devices.  We do NOT kfree()
+ *                                     device entries, just reg./unreg. them
+ *                                     as they are needed.  We kfree() them
+ *                                     at module cleanup.
+ *                                     With MODULE-loading ``insmod'', user can
+ *                                     issue parameter:   slip_maxdev=1024
+ *                                     (Or how much he/she wants.. Default is 256)
  *
- *
- *
- *     FIXME:  This driver still makes some IP'ish assumptions. It should build cleanly KISS TNC only without
- *     CONFIG_INET defined.
- *      I hope now it is fixed ;)
  */
 
 #define SL_CHECK_TRANSMIT
 #endif
 
 
-static struct slip     sl_ctrl[SL_NRUNIT];
+typedef struct slip_ctrl {
+       char            if_name[8];     /* "sl0\0" .. "sl99999\0"       */
+       struct slip     ctrl;           /* SLIP things                  */
+       struct device   dev;            /* the device                   */
+} slip_ctrl_t;
+static slip_ctrl_t     **slip_ctrls = NULL;
+int slip_maxdev = SL_NRUNIT;           /* Can be overridden with insmod! */
+
 static struct tty_ldisc        sl_ldisc;
-static int             already = 0;
 
 static int slip_esc(unsigned char *p, unsigned char *d, int len);
 static void slip_unesc(struct slip *sl, unsigned char c);
@@ -102,15 +112,67 @@ static void slip_unesc6(struct slip *sl, unsigned char c);
 static inline struct slip *
 sl_alloc(void)
 {
-       struct slip *sl;
+       slip_ctrl_t *slp;
        int i;
 
-       for (i = 0; i < SL_NRUNIT; i++) {
-               sl = &sl_ctrl[i];
-               if (!set_bit(SLF_INUSE, &sl->flags)) {
-                       return sl;
-               }
+       if (slip_ctrls == NULL) return NULL;    /* Master array missing ! */
+
+       for (i = 0; i < slip_maxdev; i++) {
+         slp = slip_ctrls[i];
+         /* Not allocated ? */
+         if (slp == NULL)
+           break;
+         /* Not in use ? */
+         if (!set_bit(SLF_INUSE, &slp->ctrl.flags))
+           break;
+       }
+       /* SLP is set.. */
+
+       /* Sorry, too many, all slots in use */
+       if (i >= slip_maxdev) return NULL;
+
+       /* If no channels are available, allocate one */
+       if (!slp &&
+           (slip_ctrls[i] = (slip_ctrl_t *)kmalloc(sizeof(slip_ctrl_t),
+                                                   GFP_KERNEL)) != NULL) {
+         slp = slip_ctrls[i];
+         memset(slp, 0, sizeof(slip_ctrl_t));
+
+         /* Initialize channel control data */
+         set_bit(SLF_INUSE, &slp->ctrl.flags);
+         slp->ctrl.tty         = NULL;
+         sprintf(slp->if_name, "sl%d", i);
+         slp->dev.name         = slp->if_name;
+         slp->dev.base_addr    = i;
+         slp->dev.priv         = (void*)&(slp->ctrl);
+         slp->dev.next         = NULL;
+         slp->dev.init         = slip_init;
+/* printk(KERN_INFO "slip: kmalloc()ed SLIP control node for line %s\n",
+   slp->if_name); */
        }
+       if (slp != NULL) {
+
+         /* register device so that it can be ifconfig'ed       */
+         /* slip_init() will be called as a side-effect         */
+         /* SIDE-EFFECT WARNING: slip_init() CLEARS slp->ctrl ! */
+
+         if (register_netdev(&(slp->dev)) == 0) {
+           /* (Re-)Set the INUSE bit.   Very Important! */
+           set_bit(SLF_INUSE, &slp->ctrl.flags);
+           slp->ctrl.dev = &(slp->dev);
+           slp->dev.priv = (void*)&(slp->ctrl);
+
+/* printk(KERN_INFO "slip: linked in netdev %s for active use\n",
+   slp->if_name); */
+
+           return (&(slp->ctrl));
+
+         } else {
+           clear_bit(SLF_INUSE,&(slp->ctrl.flags));
+           printk("sl_alloc() - register_netdev() failure.\n");
+         }
+       }
+
        return NULL;
 }
 
@@ -150,9 +212,9 @@ sl_free(struct slip *sl)
        }
 }
 
-/* MTU has been changed by the IP layer. Unfortunately we are not told about this, but
-   we spot it ourselves and fix things up. We could be in an upcall from the tty
-   driver, or in an ip packet queue. */
+/* MTU has been changed by the IP layer. Unfortunately we are not told
+   about this, but we spot it ourselves and fix things up. We could be
+   in an upcall from the tty driver, or in an ip packet queue. */
 
 static void sl_changedmtu(struct slip *sl)
 {
@@ -418,7 +480,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
 static int
 sl_xmit(struct sk_buff *skb, struct device *dev)
 {
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
 
        if (!dev->start)  {
                printk("%s: xmit call when iface is down\n", dev->name);
@@ -473,7 +535,7 @@ sl_header(struct sk_buff *skb, struct device *dev, unsigned short type,
 {
 #ifdef CONFIG_AX25
 #ifdef CONFIG_INET
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
 
        if (((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) && type != htons(ETH_P_AX25))  {
                return ax25_encapsulate(skb, dev, type, daddr, saddr, len);
@@ -491,7 +553,7 @@ sl_rebuild_header(void *buff, struct device *dev, unsigned long raddr,
 {
 #ifdef CONFIG_AX25
 #ifdef CONFIG_INET
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
 
        if ((sl->mode & SL_MODE_AX25) || (sl->mode & SL_MODE_AX25VC)) {
                return ax25_rebuild_header(buff, dev, raddr, skb);
@@ -506,7 +568,7 @@ sl_rebuild_header(void *buff, struct device *dev, unsigned long raddr,
 static int
 sl_open(struct device *dev)
 {
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
        unsigned long len;
 
        if (sl->tty == NULL) {
@@ -590,7 +652,7 @@ norbuff:
 static int
 sl_close(struct device *dev)
 {
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
 
        if (sl->tty == NULL) {
                return -EBUSY;
@@ -729,6 +791,7 @@ slip_close(struct tty_struct *tty)
        tty->disc_data = 0;
        sl->tty = NULL;
        sl_free(sl);
+       unregister_netdev(sl->dev);
 #ifdef MODULE
        MOD_DEC_USE_COUNT;
 #endif
@@ -739,7 +802,7 @@ static struct enet_statistics *
 sl_get_stats(struct device *dev)
 {
        static struct enet_statistics stats;
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
 #ifdef SL_INCLUDE_CSLIP
        struct slcompress *comp;
 #endif
@@ -948,7 +1011,7 @@ sl_set_dev_mac_address(struct device *dev, void *addr)
 
 int sl_get_ax25_mode(struct device *dev)
 {
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
 
        return sl->mode & SL_MODE_AX25VC;
 }
@@ -1049,17 +1112,82 @@ slip_ioctl(struct tty_struct *tty, void *file, int cmd, void *arg)
 
 static int sl_open_dev(struct device *dev)
 {
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
        if(sl->tty==NULL)
                return -ENODEV;
        return 0;
 }
 
+/* Initialize SLIP control device -- register SLIP line discipline */
+#ifdef MODULE
+static int slip_init_ctrl_dev()
+#else  /* !MODULE */
+int
+slip_init_ctrl_dev(struct device *dummy)
+#endif /* !MODULE */
+{
+       int status;
+
+       if (slip_maxdev < 4) slip_maxdev = 4; /* Sanity */
+
+       printk("SLIP: version %s (dynamic channels, max=%d)"
+#ifdef CONFIG_SLIP_MODE_SLIP6
+              " (6 bit encapsulation enabled)"
+#endif
+              "\n",
+              SLIP_VERSION, slip_maxdev );
+#if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
+       printk("CSLIP: code copyright 1989 Regents of the University of California\n");
+#endif
+#ifdef CONFIG_AX25
+       printk("AX25: KISS encapsulation enabled\n");
+#endif
+
+       slip_ctrls = (slip_ctrl_t **) kmalloc(sizeof(void*)*slip_maxdev, GFP_KERNEL);
+       if (slip_ctrls == NULL) {
+         printk("SLIP: Can't allocate slip_ctrls[] array!  Uaargh! (-> No SLIP available)\n");
+         return -ENOMEM;
+       }
+       
+       /* Clear the pointer array, we allocate devices when we need them */
+       memset(slip_ctrls, 0, sizeof(void*)*slip_maxdev); /* Pointers */
+
+       /* Fill in our line protocol discipline, and register it */
+       memset(&sl_ldisc, 0, sizeof(sl_ldisc));
+       sl_ldisc.magic  = TTY_LDISC_MAGIC;
+       sl_ldisc.flags  = 0;
+       sl_ldisc.open   = slip_open;
+       sl_ldisc.close  = slip_close;
+       sl_ldisc.read   = NULL;
+       sl_ldisc.write  = NULL;
+       sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
+                                  unsigned int, unsigned long)) slip_ioctl;
+       sl_ldisc.select = NULL;
+       sl_ldisc.receive_buf = slip_receive_buf;
+       sl_ldisc.receive_room = slip_receive_room;
+       sl_ldisc.write_wakeup = slip_write_wakeup;
+       if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
+         printk("SLIP: can't register line discipline (err = %d)\n", status);
+       }
+
+
+       /* If not loadable module, a bootstrap Space.c slip_proto dev
+        *  now needs to be unregistered.
+        */
+#ifndef MODULE
+       printk("SLIP: Unregistering bootstrap device "
+              "'slip_proto' - slip OK\n");
+       unregister_netdev(dummy);
+#endif
+       return status;
+      }
+
+
 /* Initialize the SLIP driver.  Called by DDI. */
 int
 slip_init(struct device *dev)
 {
-       struct slip *sl = &sl_ctrl[dev->base_addr];
+       struct slip *sl = (struct slip*)(dev->priv);
        int i;
 #ifdef CONFIG_AX25
        static char ax25_bcast[AX25_ADDR_LEN] =
@@ -1068,39 +1196,8 @@ slip_init(struct device *dev)
                {'L'<<1,'I'<<1,'N'<<1,'U'<<1,'X'<<1,' '<<1,'1'<<1};
 #endif
 
-       if (already++ == 0) {
-               printk("SLIP: version %s (%d channels) %s\n",
-                      SLIP_VERSION, SL_NRUNIT,
-#ifdef CONFIG_SLIP_MODE_SLIP6
-                      "(6 bit encapsulation enabled)"
-#else
-                      ""
-#endif
-                      );
-#if defined(SL_INCLUDE_CSLIP) && !defined(MODULE)
-               printk("CSLIP: code copyright 1989 Regents of the University of California\n");
-#endif
-#ifdef CONFIG_AX25
-               printk("AX25: KISS encapsulation enabled\n");
-#endif
-               /* Fill in our LDISC request block. */
-               memset(&sl_ldisc, 0, sizeof(sl_ldisc));
-               sl_ldisc.magic  = TTY_LDISC_MAGIC;
-               sl_ldisc.flags  = 0;
-               sl_ldisc.open   = slip_open;
-               sl_ldisc.close  = slip_close;
-               sl_ldisc.read   = NULL;
-               sl_ldisc.write  = NULL;
-               sl_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
-                                          unsigned int, unsigned long)) slip_ioctl;
-               sl_ldisc.select = NULL;
-               sl_ldisc.receive_buf = slip_receive_buf;
-               sl_ldisc.receive_room = slip_receive_room;
-               sl_ldisc.write_wakeup = slip_write_wakeup;
-               if ((i = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0)  {
-                       printk("SLIP: can't register line discipline (err = %d)\n", i);
-               }
-       }
+       if (sl == NULL)         /* Allocation failed ?? */
+         return -ENODEV;
 
        /* Set up the "SLIP Control Block". (And clear statistics) */
        
@@ -1149,47 +1246,10 @@ slip_init(struct device *dev)
 #ifdef MODULE
 char kernel_version[] = UTS_RELEASE;
 
-static struct device dev_slip[SL_NRUNIT] =  {
-       {
-               "sl0",          /* slip */
-               0, 0, 0, 0,     /* memory */
-               0, 0,           /* base, irq */
-               0, 0, 0, NULL, slip_init,
-       },
-       { "sl1" , 0, 0, 0, 0,  1, 0, 0, 0, 0, NULL, slip_init },
-       { "sl2" , 0, 0, 0, 0,  2, 0, 0, 0, 0, NULL, slip_init },
-       { "sl3" , 0, 0, 0, 0,  3, 0, 0, 0, 0, NULL, slip_init },
-#ifdef SL_SLIP_LOTS
-       { "sl4" , 0, 0, 0, 0,  4, 0, 0, 0, 0, NULL, slip_init },
-       { "sl5" , 0, 0, 0, 0,  5, 0, 0, 0, 0, NULL, slip_init },
-       { "sl6" , 0, 0, 0, 0,  6, 0, 0, 0, 0, NULL, slip_init },
-       { "sl7" , 0, 0, 0, 0,  7, 0, 0, 0, 0, NULL, slip_init },
-       { "sl8" , 0, 0, 0, 0,  8, 0, 0, 0, 0, NULL, slip_init },
-       { "sl9" , 0, 0, 0, 0,  9, 0, 0, 0, 0, NULL, slip_init },
-       { "sl10", 0, 0, 0, 0, 10, 0, 0, 0, 0, NULL, slip_init },
-       { "sl11", 0, 0, 0, 0, 11, 0, 0, 0, 0, NULL, slip_init },
-       { "sl12", 0, 0, 0, 0, 12, 0, 0, 0, 0, NULL, slip_init },
-       { "sl13", 0, 0, 0, 0, 13, 0, 0, 0, 0, NULL, slip_init },
-       { "sl14", 0, 0, 0, 0, 14, 0, 0, 0, 0, NULL, slip_init },
-       { "sl15", 0, 0, 0, 0, 15, 0, 0, 0, 0, NULL, slip_init },
-#endif /* SL_SLIP_LOTS */
-};
-
 int
 init_module(void)
 {
-       int err;
-       int i;
-
-       for (i = 0; i < SL_NRUNIT; i++)  {
-               if ((err = register_netdev(&dev_slip[i])))  {
-                       if (err == -EEXIST)  {
-                               printk("SLIP: devices already present. Module not loaded.\n");
-                       }
-                       return err;
-               }
-       }
-       return 0;
+       return slip_init_ctrl_dev();
 }
 
 void
@@ -1201,12 +1261,18 @@ cleanup_module(void)
                printk("SLIP: device busy, remove delayed\n");
                return;
        }
-       for (i = 0; i < SL_NRUNIT; i++)  {
-               unregister_netdev(&dev_slip[i]);
+       if (slip_ctrls != NULL) {
+         for (i = 0; i < slip_maxdev; i++)  {
+           if (slip_ctrls[i] != NULL) {
+             unregister_netdev(&(slip_ctrls[i]->dev));
+             kfree(slip_ctrls[i]);
+           }
+         }
+         kfree(slip_ctrls);
+         slip_ctrls = NULL;
        }
        if ((i = tty_register_ldisc(N_SLIP, NULL)))  {
-               printk("SLIP: can't unregister line discipline (err = %d)\n", i);
+         printk("SLIP: can't unregister line discipline (err = %d)\n", i);
        }
-       already = 0;
 }
 #endif /* MODULE */
index efeff53d068b4e8b28c3c41ae3b23274c255da48..2f1fe06f17c3df8ab4dc1c81f00badae2a3e743e 100644 (file)
 #endif
 
 /* SLIP configuration. */
-#ifndef SL_SLIP_LOTS
-#define SL_NRUNIT      4               /* number of SLIP channels      */
-#else
-#define SL_NRUNIT      16
-#endif
+#define SL_NRUNIT      256             /* MAX number of SLIP channels;
+                                          This can be overridden with
+                                          insmod -oslip_maxdev=nnn     */
 #define SL_MTU         296             /* 296; I am used to 600- FvK   */
 
 /* SLIP protocol characters. */
index df6a47d10999a418352b4873582c7ff3aa3f14fb..492842c5c022254675b6ca4bbe6daded5282b9b3 100644 (file)
@@ -219,7 +219,7 @@ int znet_probe(struct device *dev)
        dev->base_addr = netinfo->iobase1;
        dev->irq = netinfo->irq1;
 
-       printk(KERN_INFO "%s: ZNET at %#3x,", dev->name, dev->base_addr);
+       printk(KERN_INFO "%s: ZNET at %#3lx,", dev->name, dev->base_addr);
 
        /* The station address is in the "netidblk" at 0x0f0000. */
        for (i = 0; i < 6; i++)
@@ -319,7 +319,7 @@ static int znet_send_packet(struct sk_buff *skb, struct device *dev)
        int ioaddr = dev->base_addr;
 
        if (znet_debug > 4)
-               printk(KERN_DEBUG "%s: ZNet_send_packet(%d).\n", dev->name, dev->tbusy);
+               printk(KERN_DEBUG "%s: ZNet_send_packet(%ld).\n", dev->name, dev->tbusy);
 
        /* Transmitter timeout, likely just recovery after suspending the machine. */
        if (dev->tbusy) {
index cd59d103193c8407de8b5b52dd3d23f5195c3050..10cb736f393282de4f86778d9d4e21daaab8b418 100644 (file)
@@ -76,6 +76,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( INTEL,          INTEL_82371,    "82471 Triton"),
        DEVICE( INTEL,          INTEL_82438,    "82438"),
        DEVICE( INTEL,          INTEL_7116,     "SAA7116"),
+       DEVICE( INTEL,          INTEL_82865,    "82865"),
        DEVICE( SMC,            SMC_37C665,     "FDC 37C665"),
        DEVICE( ATI,            ATI_M32,        "Mach 32"),
        DEVICE( ATI,            ATI_M64,        "Mach 64"),
@@ -93,6 +94,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( AL,             AL_M1445,       "M1445"),
        DEVICE( AL,             AL_M1449,       "M1449"),
        DEVICE( AL,             AL_M1451,       "M1451"),
+       DEVICE( AL,             AL_M1461,       "M1461"),
        DEVICE( AL,             AL_M4803,       "M4803"),
        DEVICE( TSENG,          TSENG_W32P_2,   "ET4000W32P"),
        DEVICE( TSENG,          TSENG_W32P_b,   "ET4000W32P rev B"),
@@ -259,11 +261,13 @@ const char *pci_strclass (unsigned int class)
              case PCI_CLASS_STORAGE_IDE:               return "IDE controller";
              case PCI_CLASS_STORAGE_FLOPPY:            return "Floppy disk controller";
              case PCI_CLASS_STORAGE_IPI:               return "IPI bus controller";
+             case PCI_CLASS_STORAGE_RAID:              return "RAID bus controller";
              case PCI_CLASS_STORAGE_OTHER:             return "Unknown mass storage controller";
 
              case PCI_CLASS_NETWORK_ETHERNET:          return "Ethernet controller";
              case PCI_CLASS_NETWORK_TOKEN_RING:        return "Token ring network controller";
              case PCI_CLASS_NETWORK_FDDI:              return "FDDI network controller";
+             case PCI_CLASS_NETWORK_ATM:               return "ATM network controller";
              case PCI_CLASS_NETWORK_OTHER:             return "Network controller";
 
              case PCI_CLASS_DISPLAY_VGA:               return "VGA compatible controller";
@@ -284,8 +288,40 @@ const char *pci_strclass (unsigned int class)
              case PCI_CLASS_BRIDGE_MC:                 return "MicroChannel bridge";
              case PCI_CLASS_BRIDGE_PCI:                return "PCI bridge";
              case PCI_CLASS_BRIDGE_PCMCIA:             return "PCMCIA bridge";
+             case PCI_CLASS_BRIDGE_NUBUS:              return "NuBus bridge";
+             case PCI_CLASS_BRIDGE_CARDBUS:            return "CardBus bridge";
              case PCI_CLASS_BRIDGE_OTHER:              return "Bridge";
 
+             case PCI_CLASS_COMMUNICATION_SERIAL:      return "Serial controller";
+             case PCI_CLASS_COMMUNICATION_PARALLEL:    return "Parallel controller";
+             case PCI_CLASS_COMMUNICATION_OTHER:       return "Communication controller";
+
+             case PCI_CLASS_SYSTEM_PIC:                return "PIC";
+             case PCI_CLASS_SYSTEM_DMA:                return "DMA controller";
+             case PCI_CLASS_SYSTEM_TIMER:              return "Timer";
+             case PCI_CLASS_SYSTEM_RTC:                return "RTC";
+             case PCI_CLASS_SYSTEM_OTHER:              return "System peripheral";
+
+             case PCI_CLASS_INPUT_KEYBOARD:            return "Keyboard controller";
+             case PCI_CLASS_INPUT_PEN:                 return "Digitizer Pen";
+             case PCI_CLASS_INPUT_MOUSE:               return "Mouse controller";
+             case PCI_CLASS_INPUT_OTHER:               return "Input device controller";
+
+             case PCI_CLASS_DOCKING_GENERIC:           return "Generic Docking Station";
+             case PCI_CLASS_DOCKING_OTHER:             return "Docking Station";
+
+             case PCI_CLASS_PROCESSOR_386:             return "386";
+             case PCI_CLASS_PROCESSOR_486:             return "486";
+             case PCI_CLASS_PROCESSOR_PENTIUM:         return "Pentium";
+             case PCI_CLASS_PROCESSOR_ALPHA:           return "Alpha";
+             case PCI_CLASS_PROCESSOR_POWERPC:         return "Power PC";
+             case PCI_CLASS_PROCESSOR_CO:              return "Co-processor";
+
+             case PCI_CLASS_SERIAL_FIREWIRE:           return "FireWire (IEEE 1394)";
+             case PCI_CLASS_SERIAL_ACCESS:             return "ACCESS Bus";
+             case PCI_CLASS_SERIAL_SSA:                return "SSA";
+             case PCI_CLASS_SERIAL_FIBER:              return "Fiber Channel";
+
              default:                                  return "Unknown class";
        }
 }
index 2f998bd02a54ba9eca0666af6f1fad0f70d463a2..7846d8960a508ff2b1275f350d8355488f425271 100644 (file)
 
 /* For PCMCIA cards, always use AUTOCONF */
 #if defined(PCMCIA) || defined(MODULE)
+#if !defined(AUTOCONF)
 #define AUTOCONF
 #endif
+#endif
 
 /* If auto configuration is disabled, IRQ, SCSI_ID and RECONNECT have to
    be predefined */
index cf57ac026d1203da5e7698073010650d6d419404..6eaf31e8677ad5fad000a9f4c9f6f5c55dce1581 100644 (file)
@@ -940,7 +940,6 @@ static int num_aic7xxx_syncrates =
     sizeof(aic7xxx_syncrates) / sizeof(aic7xxx_syncrates[0]);
 
 #ifdef AIC7XXX_DEBUG
-extern int vsprintf(char *, const char *, va_list);
 
 static void
 debug(const char *fmt, ...)
index 61cd47a14edcd84226fa78f5ef71896817996708..298b63a674c28401a78c839139cb5c41e80078dc 100644 (file)
@@ -192,7 +192,7 @@ static int restart(struct Scsi_Host *shpnt);
 
 #if defined(MODULE) && !defined(GFP_DMA)
 # define CHECK_DMA_ADDR(isa, addr, badstmt) \
-    do { if ((isa) && (addr) > (void *)ISA_DMA_THRESHOLD) badstmt; } while (0)
+    do { if ((isa) && ((const void *)addr) > (const void *)ISA_DMA_THRESHOLD) badstmt; } while (0)
 #else
 # define CHECK_DMA_ADDR(isa, addr, badstmt)
 #endif
index 9e5c5a67972df9e6fcebd3a373ab1f17176ac802..e10527ea5e4a9927d3f05d52ec9a0545a9ae80ff 100644 (file)
@@ -1,8 +1,6 @@
 #ifndef _CONSTANTS_H
 #define _CONSTANTS_H
-extern void print_command(unsigned char *);
 extern int print_msg(unsigned char *);
-/* extern void print_sense(const char *,  Scsi_Cmnd *); */
 extern void print_status(int);
 extern void print_Scsi_Cmnd (Scsi_Cmnd *);
 #endif /* def _CONSTANTS_H */
index a5847a4a67d94fced71afd4e60768819043ed595..ea62b7a2470e634099e2256af96adea61427089c 100644 (file)
@@ -1,6 +1,3 @@
-extern void proc_print_scsidevice(Scsi_Device *scd, char *buffer, 
-                                 int *size, int len);
-
 
 void swap_statistics(u8 *p)
 {
index ae7ca38a8383a22b4b6b0d63aa20e1f58eec8550..c6c561a46b3817cdffb8790512e6e5f87ab34768 100644 (file)
@@ -32,7 +32,7 @@
  *  Cambridge, MA 02139, USA.                               *
  *                                                          *
  ************************************************************
- *  last change: 95/07/13                  OS: Linux 1.3.9  *
+ *  last change: 95/08/04                 OS: Linux 1.3.15  *
  ************************************************************/
 
 /* Look in eata_pio.h for configuration information */
@@ -71,8 +71,6 @@ static unchar reg_IRQ[] =
 static unchar reg_IRQL[] =
 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
-static uint internal_command_finished = TRUE;
-
 static ulong int_counter = 0;
 static ulong queue_counter = 0;
 
@@ -90,10 +88,6 @@ void hprint(const char *str)
        hptr3[z*2]=' ';
 }
 
-void eata_pio_scsi_done (Scsi_Cmnd * SCpnt)
-{
-    return;
-}   
 
 #include "eata_pio_proc.c"
  
@@ -256,8 +250,7 @@ void eata_pio_int_handler(int irq, struct pt_regs * regs)
        cp->status = FREE;   /* now we can release the slot  */
        
        restore_flags(flags);
-       if(cmd->scsi_done != eata_pio_scsi_done) cmd->scsi_done(cmd);
-       else internal_command_finished = TRUE;
+       cmd->scsi_done(cmd);
        save_flags(flags);
        cli();
     }
@@ -293,13 +286,6 @@ int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
     
     queue_counter++;
     
-    if (done == (void *)eata_pio_scsi_done) { 
-       if (internal_command_finished == TRUE)
-           internal_command_finished = FALSE;
-       else 
-           cmd->result = (DID_ERROR << 16) + QUEUE_FULL;
-    }
-    
     hd = HD(cmd);
     sh = cmd->host;
     base = (uint) sh->base;
@@ -351,8 +337,8 @@ int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
        cp->DataIn = TRUE;  /* Input mode  */
     }
     
-    cp->Interpret = (cmd->target==hd->hostid);
-    cp->cp_datalen=htonl((ulong)cmd->request_bufflen);
+    cp->Interpret = (cmd->target == hd->hostid);
+    cp->cp_datalen = htonl((ulong)cmd->request_bufflen);
     cp->Auto_Req_Sen = FALSE;
     cp->cp_reqDMA = htonl(0);
     cp->reqlen = 0;
@@ -369,36 +355,34 @@ int eata_pio_queue(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
     cp->cmd = cmd;
     cmd->host_scribble = (char *)&hd->ccb[y];   
     
-    if (cmd->use_sg==0)
+    if (cmd->use_sg == 0)
     { 
        cmd->SCp.buffers_residual=1;
-       cmd->SCp.ptr=cmd->request_buffer;
-       cmd->SCp.this_residual=cmd->request_bufflen;
-       cmd->SCp.buffer=NULL;
-    }
-    else
-    {
-       cmd->SCp.buffer=cmd->request_buffer;
-       cmd->SCp.buffers_residual=cmd->use_sg;
-       cmd->SCp.ptr=cmd->SCp.buffer->address;
-       cmd->SCp.this_residual=cmd->SCp.buffer->length;
+       cmd->SCp.ptr = cmd->request_buffer;
+       cmd->SCp.this_residual = cmd->request_bufflen;
+       cmd->SCp.buffer = NULL;
+    } else {
+       cmd->SCp.buffer = cmd->request_buffer;
+       cmd->SCp.buffers_residual = cmd->use_sg;
+       cmd->SCp.ptr = cmd->SCp.buffer->address;
+       cmd->SCp.this_residual = cmd->SCp.buffer->length;
     }
-    cmd->SCp.Status=(cmd->SCp.this_residual!=0);  /* TRUE as long as bytes 
-                                                    are to transfer */ 
+    cmd->SCp.Status = (cmd->SCp.this_residual != 0);  /* TRUE as long as bytes 
+                                                       * are to transfer */ 
     
     if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) 
     {
        cmd->result = DID_ERROR << 16;
-       printk("eata_pio_queue target %d, pid %ld, HBA busy, returning DID_ERROR, done.\n",
-              cmd->target, cmd->pid);
+       printk("eata_pio_queue target %d, pid %ld, HBA busy, returning "
+               "DID_ERROR, done.\n", cmd->target, cmd->pid);
        restore_flags(flags);
-       if(done != (void *)eata_pio_scsi_done) done(cmd);
+        done(cmd);
        return (0);
     }
     while (!(inb(base + HA_RSTATUS) & HA_SDRQ));
     outsw(base + HA_RDATA, cp, hd->cplen);
     outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
-    for (x=0; x<hd->cppadlen; x++) outw(0, base + HA_RDATA);
+    for (x = 0; x < hd->cppadlen; x++) outw(0, base + HA_RDATA);
     
     DBG(DBG_QUEUE,printk("Queued base %#.4lx pid: %ld target: %x lun: %x "
                         "slot %d irq %d\n", (long)sh->base, cmd->pid, 
@@ -417,8 +401,9 @@ int eata_pio_abort(Scsi_Cmnd * cmd)
     save_flags(flags);
     cli();
     
-    DBG(DBG_ABNORM, printk("eata_pio_abort called pid: %ld target: %x lun: %x reason %x\n",
-                          cmd->pid, cmd->target, cmd->lun, cmd->abort_reason));
+    DBG(DBG_ABNORM, printk("eata_pio_abort called pid: %ld target: %x lun: %x"
+                           " reason %x\n", cmd->pid, cmd->target, cmd->lun, 
+                           cmd->abort_reason));
     DBG(DBG_ABNORM && DBG_DELAY, DEL2(500));
     
     
@@ -566,11 +551,12 @@ char * get_pio_board_data(ulong base, uint irq, uint id, ulong cplen, ushort cpp
     cp.cp_cdb[4] = 254;
     cp.cp_cdb[5] = 0;
     
-    if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP)) return (NULL);
+    if (eata_pio_send_command((uint) base, EATA_CMD_PIO_SEND_CP)) 
+        return (NULL);
     while (!(inb(base + HA_RSTATUS) & HA_SDRQ));
     outsw(base + HA_RDATA, &cp, cplen);
     outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND);
-    for (z=0; z<cppadlen; z++) outw(0, base + HA_RDATA);
+    for (z = 0; z < cppadlen; z++) outw(0, base + HA_RDATA);
     
     while (inb(base + HA_RSTATUS) & HA_SBUSY);
     if (inb(base + HA_RSTATUS) & HA_SERROR)
@@ -580,7 +566,7 @@ char * get_pio_board_data(ulong base, uint irq, uint id, ulong cplen, ushort cpp
     else
     {
        insw(base+HA_RDATA, &buff, 127);
-       while (inb(base+HA_RSTATUS)&HA_SDRQ) inw(base+HA_RDATA);
+       while (inb(base + HA_RSTATUS)&HA_SDRQ) inw(base + HA_RDATA);
        return (buff);
     }
 }
@@ -606,7 +592,7 @@ int get_pio_conf_PIO(u32 base, struct get_conf *buf)
 
     loop = R_LIMIT;
     for (p = (ushort *) buf; 
-        (long)p <= ((long)buf + (sizeof(struct get_conf)/ 2)); p++) {
+        (long)p <= ((long)buf + (sizeof(struct get_conf) / 2)); p++) {
        while (!(inb(base + HA_RSTATUS) & HA_SDRQ))
            if (--loop == 0)
                return (FALSE);
@@ -661,23 +647,23 @@ static uint print_selftest(uint base)
 #endif
     
     printk("eata_pio: executing controller self test & setup...\n");
-    while (inb(base+HA_RSTATUS)&HA_SBUSY);
-    outb(EATA_CMD_PIO_SETUPTEST,base+HA_WCOMMAND);
+    while (inb(base + HA_RSTATUS) & HA_SBUSY);
+    outb(EATA_CMD_PIO_SETUPTEST, base + HA_WCOMMAND);
     do {
-       while (inb(base+HA_RSTATUS)&HA_SBUSY)
+       while (inb(base + HA_RSTATUS) & HA_SBUSY)
            /* nothing */ ;
-       if (inb(base+HA_RSTATUS)&HA_SDRQ)
+       if (inb(base + HA_RSTATUS) & HA_SDRQ)
        {
-           insw(base+HA_RDATA,&buffer,256);
+           insw(base + HA_RDATA, &buffer, 256);
 #ifdef VERBOSE_SETUP
            /* no beeps please... */
-           for (z=0; z < 511 && buffer[z]; z++)
+           for (z = 0; z < 511 && buffer[z]; z++)
                if (buffer[z] != 7) printk("%c", buffer[z]);
 #endif
        }
-    } while (inb(base+HA_RSTATUS)&(HA_SBUSY|HA_SDRQ));
+    } while (inb(base+HA_RSTATUS) & (HA_SBUSY|HA_SDRQ));
     
-    return (!(inb(base+HA_RSTATUS)&HA_SERROR)); 
+    return (!(inb(base+HA_RSTATUS) & HA_SERROR)); 
 }
 
 int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
@@ -751,6 +737,7 @@ int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
     SD(sh)->revision[3] = '.';
     SD(sh)->revision[4] = buff[35];
     SD(sh)->revision[5] = 0;
+
     switch (ntohl(gc->len)) {
     case 0x1c:
        SD(sh)->EATA_revision = 'a';
@@ -761,9 +748,28 @@ int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
     case 0x22:
        SD(sh)->EATA_revision = 'c';
        break;
+    case 0x24:
+       SD(sh)->EATA_revision = 'z';            
     default:
        SD(sh)->EATA_revision = '?';
     }
+
+    if(ntohl(gc->len) >= 0x22) {
+       if (gc->is_PCI == TRUE)
+           hd->bustype = IS_PCI;
+       else if (gc->is_EISA == TRUE)
+           hd->bustype = IS_EISA;
+       else
+           hd->bustype = IS_ISA;
+    } else {
+       if (buff[21] == '4')
+           hd->bustype = IS_PCI;
+       else if (buff[21] == '2')
+           hd->bustype = IS_EISA;
+       else
+           hd->bustype = IS_ISA;
+    }
+  
     SD(sh)->cplen=cplen;
     SD(sh)->cppadlen=cppadlen;
     SD(sh)->hostid=gc->scsi_id[3];
@@ -781,22 +787,6 @@ int register_pio_HBA(long base, struct get_conf *gc, Scsi_Host_Template * tpnt)
     
     hd->channel = 0;
     
-    if(ntohl(gc->len) >= 0x22) {
-       if (gc->is_PCI == TRUE)
-           hd->bustype = IS_PCI;
-       else if (gc->is_EISA == TRUE)
-           hd->bustype = IS_EISA;
-       else
-           hd->bustype = IS_ISA;
-    } else {
-       if (buff[21] == '4')
-           hd->bustype = IS_PCI;
-       else if (buff[21] == '2')
-           hd->bustype = IS_EISA;
-       else
-           hd->bustype = IS_ISA;
-    }
-  
     sh->max_id = 8;
     sh->max_lun = 8;
 
@@ -1002,15 +992,18 @@ int eata_pio_detect(Scsi_Host_Template * tpnt)
               VER_MAJOR, VER_MINOR, VER_SUB);
        
        printk("Registered HBAs:\n");
-       printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr: QS: SG: CPL:\n");
+       printk("HBA no. Boardtype: Revis: EATA: Bus: BaseIO: IRQ: Ch: ID: Pr:"
+               " QS: SG: CPL:\n");
        for (i = 1; i <= registered_HBAs; i++) {
-           printk("scsi%-2d: %.10s v%s 2.0%c  %s %#.4x   %2d   %d   %d   %c  %2d  %2d  %2d\n", 
+           printk("scsi%-2d: %.10s v%s 2.0%c  %s %#.4x   %2d   %d   %d   %c"
+                   "  %2d  %2d  %2d\n", 
                   HBA_ptr->host_no, SD(HBA_ptr)->name, SD(HBA_ptr)->revision,
                   SD(HBA_ptr)->EATA_revision, (SD(HBA_ptr)->bustype == 'P')?
                   "PCI ":(SD(HBA_ptr)->bustype == 'E')?"EISA":"ISA ",
-                  (uint) HBA_ptr->base, HBA_ptr->irq, 
-                  SD(HBA_ptr)->channel, HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', 
-                  HBA_ptr->can_queue, HBA_ptr->sg_tablesize, HBA_ptr->cmd_per_lun);
+                  (uint) HBA_ptr->base, HBA_ptr->irq, SD(HBA_ptr)->channel, 
+                   HBA_ptr->this_id, (SD(HBA_ptr)->primary == TRUE)?'Y':'N', 
+                  HBA_ptr->can_queue, HBA_ptr->sg_tablesize, 
+                   HBA_ptr->cmd_per_lun);
            HBA_ptr = SD(HBA_ptr)->next;
        }
     }
index 4ff5dcea4542ad12bcbf740aeab449df81c9dcfa..f56f1bad0afab113cb2664705105c3f0cf0433e0 100644 (file)
@@ -19,7 +19,7 @@
 
 #define VER_MAJOR 0
 #define VER_MINOR 0
-#define VER_SUB          "1a"
+#define VER_SUB          "1b"
 
 /************************************************************************
  * Here you can switch parts of the code on and of                     *
@@ -112,7 +112,6 @@ int eata_pio_release(struct Scsi_Host *);
  * c-label-offset: -4
  * c-continued-statement-offset: 4
  * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
  * tab-width: 8
  * End:
  */
index 936282705482e559a750889ba48de6801a4f272c..b54800918e510b778df4e509d4b8cb1a0d6ebc46 100644 (file)
@@ -28,19 +28,23 @@ int eata_pio_set_info(char *buffer, int length, struct Scsi_Host *HBA_ptr)
 
 /*
  * eata_proc_info
- * inout : decides on the direction of the dataflow and the meaning of the variables
+ * inout : decides on the direction of the dataflow and the meaning of the 
+ *         variables
  * buffer: If inout==FALSE data is beeing written to it else read from it
  * *start: If inout==FALSE start of the valid data in the buffer
- * offset: If inout==FALSE offset from the beginning of the imaginary file from which we start writing into the buffer
- * length: If inout==FALSE max number of bytes to be written into the buffer else number of bytes in the buffer
+ * offset: If inout==FALSE offset from the beginning of the imaginary file 
+ *         from which we start writing into the buffer
+ * length: If inout==FALSE max number of bytes to be written into the buffer 
+ *         else number of bytes in the buffer
  */
-int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
+int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, 
+                      int hostno, int inout)
 {
 
     Scsi_Device *scd;
     struct Scsi_Host *HBA_ptr;
     static u8 buff[512];
-    int i, x
+    int i; 
     int   size, len = 0;
     off_t begin = 0;
     off_t pos = 0;
@@ -101,40 +105,7 @@ int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, int
     
     while (scd) {
        if (scd->host == HBA_ptr) {
-           
-           size = sprintf(buffer + len, "Channel: %02d Id: %02d Lun: %02d\n  Vendor: ",
-                          scd->channel, scd->id, scd->lun);
-           for (x = 0; x < 8; x++) {
-               if (scd->vendor[x] >= 0x20)
-                   size += sprintf(buffer + len + size, "%c", scd->vendor[x]);
-               else
-                   size += sprintf(buffer + len + size," ");
-           }
-           size += sprintf(buffer + len + size, " Model: ");
-           for (x = 0; x < 16; x++) {
-               if (scd->model[x] >= 0x20)
-                   size +=  sprintf(buffer + len + size, "%c", scd->model[x]);
-               else
-                   size += sprintf(buffer + len + size, " ");
-           }
-           size += sprintf(buffer + len + size, " Rev: ");
-           for (x = 0; x < 4; x++) {
-               if (scd->rev[x] >= 0x20)
-                   size += sprintf(buffer + len + size, "%c", scd->rev[x]);
-               else
-                   size += sprintf(buffer + len + size, " ");
-           }
-           size += sprintf(buffer + len + size, "\n");
-           
-           size += sprintf(buffer + len + size, "  Type:   %s ",
-                           scd->type < MAX_SCSI_DEVICE_CODE ? 
-                           pio_scsi_dev_types[(int)scd->type] : "Unknown          " );
-           size += sprintf(buffer + len + size, "               ANSI"
-                           " SCSI revision: %02x", (scd->scsi_level < 3)?1:2);
-           if (scd->scsi_level == 2)
-               size += sprintf(buffer + len + size, " CCS\n");
-           else
-               size += sprintf(buffer + len + size, "\n");
+           proc_print_scsidevice(scd, buffer, &size, len);
            len += size; 
            pos = begin + len;
            
@@ -173,7 +144,7 @@ int eata_pio_proc_info(char *buffer, char **start, off_t offset, int length, int
  * c-label-offset: -4
  * c-continued-statement-offset: 4
  * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
  * tab-width: 8
  * End:
  */
+
index 88452f911513cc07034fbf08855e7ba7fd1f8482..62b2c9b726d368b180d4c7c04149fd2523ec41a7 100644 (file)
@@ -328,7 +328,6 @@ extern int scsi_loadable_module_flag;
 unsigned int scsi_init(void);
 extern struct Scsi_Host * scsi_register(Scsi_Host_Template *, int j);
 extern void scsi_unregister(struct Scsi_Host * i);
-extern int scsicam_bios_param (Disk *, int, int *);
 
 #define BLANK_HOST {"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 
index a3adf94806b8255a598c91bf803f8c41661f409e..0a63c63c43f95f84cf6f8a030d8cb18dd4cd238a 100644 (file)
@@ -111,8 +111,6 @@ extern int (* dispatch_scsi_info_ptr)(int ino, char *buffer, char **start,
 extern int dispatch_scsi_info(int ino, char *buffer, char **start, 
                               off_t offset, int length, int inout); 
 
-extern void proc_print_scsidevice(Scsi_Device *scd, char *buffer, 
-                                  int *size, int len);
 
 /*
  *  As the scsi do command functions are intelligent, and may need to
index fa7291db4062f2e7d24b3b6629657af5f56aac93..98d6cb8e47b99d6dbd18363d6920fca71c702756 100644 (file)
@@ -555,8 +555,6 @@ extern void build_proc_dir_entries(void);
 extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
 
 
-extern int kernel_scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
-extern int       scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
 extern void print_command(unsigned char *);
 extern void print_sense(const char *,   Scsi_Cmnd *);
 
index fa9a658776a7b2a018df03a1f88f36a1048e4fe1..e22a7d285547fa642f32eeda0636d2ebdd6093dd 100644 (file)
@@ -77,7 +77,7 @@ static int sg_ioctl(struct inode * inode,struct file * file,
     switch(cmd_in)
     {
     case SG_SET_TIMEOUT:
-        result = verify_area(VERIFY_READ, arg, sizeof(long));
+        result = verify_area(VERIFY_READ, (const void *)arg, sizeof(long));
         if (result) return result;
 
        scsi_generics[dev].timeout=get_user((int *) arg);
index 80521f0f6588fd00a566770f161777d457680b6e..ce5f3e6cd1f46b75bd34633c8a5a7764ead831b8 100644 (file)
@@ -24,8 +24,6 @@
 /* In fact, it is very slow if it has to spin up first */
 #define IOCTL_TIMEOUT 3000
 
-extern int scsi_ioctl (Scsi_Device *dev, int cmd, void *arg);
-
 static void sr_ioctl_done(Scsi_Cmnd * SCpnt)
 {
     struct request * req;
index c33427d27105563b8df15b3876f148134660c4fa..b7326613a86b6d4fca7731919ceb189d43e120e7 100644 (file)
@@ -50,7 +50,6 @@ extern sysfun_p sys_call_table[];
 
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_elf_library(int fd);
-extern int aout_core_dump(long signr, struct pt_regs * regs);
 static int elf_core_dump(long signr, struct pt_regs * regs);
 extern int dump_fpu (elf_fpregset_t *);
 
index 06b4d22489b4db3b26a47cb613311e6632137c60..87a9f4c4708b3ae27d672a815671434adfe0974a 100644 (file)
@@ -720,8 +720,9 @@ repeat:
        bh->b_dirt=0;
        bh->b_lock=0;
        bh->b_uptodate=0;
-       bh->b_flushtime = 0;
+       bh->b_flushtime=0;
        bh->b_req=0;
+       bh->b_reuse=0;
        bh->b_dev=dev;
        bh->b_blocknr=block;
        insert_into_queues(bh);
@@ -788,6 +789,15 @@ void brelse(struct buffer_head * buf)
                if (--buf->b_count)
                        return;
                wake_up(&buffer_wait);
+               if (buf->b_reuse) {
+                       if (!buf->b_lock && !buf->b_dirt && !buf->b_wait) {
+                               buf->b_reuse = 0;
+                               if(buf->b_dev == 0xffff) panic("brelse: Wrong list");
+                               remove_from_queues(buf);
+                               buf->b_dev = 0xffff;
+                               put_last_free(buf);
+                       }
+               }
                return;
        }
        printk("VFS: brelse: Trying to free free buffer\n");
index ed594aab9026736e166df51d739550ac0766d250..4bfcae3009cb46dfede42691a5b39b141e6a2996 100644 (file)
@@ -85,6 +85,10 @@ repeat:
                        memset(bh->b_data, RANDOM_INT, inode->i_sb->s_blocksize);
                        mark_buffer_dirty(bh, 1);
                }
+               else if (bh) {
+                       mark_buffer_clean(bh);
+                       bh->b_reuse = 1;
+               }
                brelse (bh);
                if (free_count == 0) {
                        block_to_free = tmp;
@@ -160,6 +164,10 @@ repeat:
                        memset(bh->b_data, RANDOM_INT, inode->i_sb->s_blocksize);
                        mark_buffer_dirty(bh, 1);
                }
+               else if (bh) {
+                       mark_buffer_clean(bh);
+                       bh->b_reuse = 1;
+               }
                brelse (bh);
                if (free_count == 0) {
                        block_to_free = tmp;
@@ -185,6 +193,7 @@ repeat:
                if (ind_bh->b_count != 1)
                        retry = 1;
                else {
+                       ind_bh->b_reuse = 1;
                        tmp = *p;
                        *p = 0;
                        inode->i_blocks -= blocks;
@@ -245,6 +254,7 @@ repeat:
                if (dind_bh->b_count != 1)
                        retry = 1;
                else {
+                       dind_bh->b_reuse = 1;
                        tmp = *p;
                        *p = 0;
                        inode->i_blocks -= blocks;
@@ -304,6 +314,7 @@ repeat:
                if (tind_bh->b_count != 1)
                        retry = 1;
                else {
+                       tind_bh->b_reuse = 1;
                        tmp = *p;
                        *p = 0;
                        inode->i_blocks -= blocks;
index 6438162a0c7df456abb5c8884301ab660718d21c..14ba6fdd9e69b261a4adcb80cca22e5ae4319fc2 100644 (file)
@@ -8,11 +8,20 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 
-struct file * first_file;
+/*
+ * first_file points to a doubly linked list of all file structures in
+ *            the system.
+ * nr_files   holds the length of this list.
+ */
+struct file * first_file = NULL;
 int nr_files = 0;
 
+/*
+ * Insert a new file structure at the head of the list of available ones.
+ */
 static void insert_file_free(struct file *file)
 {
+       file->f_count = 0;
        file->f_next = first_file;
        file->f_prev = first_file->f_prev;
        file->f_next->f_prev = file;
@@ -20,71 +29,93 @@ static void insert_file_free(struct file *file)
        first_file = file;
 }
 
+/*
+ * Remove a file structure from the list of available ones.
+ */
 static void remove_file_free(struct file *file)
 {
        if (first_file == file)
                first_file = first_file->f_next;
-       if (file->f_next)
-               file->f_next->f_prev = file->f_prev;
-       if (file->f_prev)
-               file->f_prev->f_next = file->f_next;
+       file->f_next->f_prev = file->f_prev;
+       file->f_prev->f_next = file->f_next;
        file->f_next = file->f_prev = NULL;
 }
 
+/*
+ * Insert a file structure at the end of the list of available ones.
+ */
 static void put_last_free(struct file *file)
 {
-       remove_file_free(file);
        file->f_prev = first_file->f_prev;
        file->f_prev->f_next = file;
        file->f_next = first_file;
        file->f_next->f_prev = file;
 }
 
-void grow_files(void)
+/*
+ * Allocate a new memory page for file structures and
+ * insert the new structures into the global list.
+ * Returns 0, if there is no more memory, 1 otherwise.
+ */
+static int grow_files(void)
 {
        struct file * file;
        int i;
 
-       file = (struct file *) get_free_page(GFP_KERNEL);
+       /*
+        * We don't have to clear the page because we only look into
+        * f_count, f_prev and f_next and they get initialized in
+        * insert_file_free.  The rest of the file structure is cleared
+        * by get_empty_filp before it is returned.
+        */
+       file = (struct file *) __get_free_page(GFP_KERNEL);
 
        if (!file)
-               return;
+               return 0;
 
-       nr_files+=i= PAGE_SIZE/sizeof(struct file);
+       nr_files += i = PAGE_SIZE/sizeof(struct file);
 
        if (!first_file)
-               file->f_next = file->f_prev = first_file = file++, i--;
+               file->f_count = 0,
+               file->f_next = file->f_prev = first_file = file++,
+               i--;
 
        for (; i ; i--)
                insert_file_free(file++);
+
+       return 1;
 }
 
 unsigned long file_table_init(unsigned long start, unsigned long end)
 {
-       first_file = NULL;
        return start;
 }
 
+/*
+ * Find an unused file structure and return a pointer to it.
+ * Returns NULL, if there are no more free file structures or
+ * we run out of memory.
+ */
 struct file * get_empty_filp(void)
 {
        int i;
        struct file * f;
 
-       if (!first_file)
-               grow_files();
-repeat:
-       for (f = first_file, i=0; i < nr_files; i++, f = f->f_next)
-               if (!f->f_count) {
-                       remove_file_free(f);
-                       memset(f,0,sizeof(*f));
-                       put_last_free(f);
-                       f->f_count = 1;
-                       f->f_version = ++event;
-                       return f;
-               }
-       if (nr_files < NR_FILE) {
-               grow_files();
-               goto repeat;
-       }
+       /* if the return is taken, we are in deep trouble */
+       if (!first_file && !grow_files())
+               return NULL;
+
+       do {
+               for (f = first_file, i=0; i < nr_files; i++, f = f->f_next)
+                       if (!f->f_count) {
+                               remove_file_free(f);
+                               memset(f,0,sizeof(*f));
+                               put_last_free(f);
+                               f->f_count = 1;
+                               f->f_version = ++event;
+                               return f;
+                       }
+       } while (nr_files < NR_FILE && grow_files());
+
        return NULL;
 }
index 503c7caabdd00cd543d16379913c8cd0227e2695..3ed7e2f07c933fab4ca391889469e147711ff2a1 100644 (file)
@@ -52,7 +52,10 @@ repeat:
                }
                *p = 0;
                inode->i_dirt = 1;
-               brelse(bh);
+               if (bh) {
+                       mark_buffer_clean(bh);
+                       brelse(bh);
+               }
                minix_free_block(inode->i_sb,tmp);
        }
        return retry;
index 9302de2a9f2601b9642cd3c075090a0dec437d68..d878c4ad51a6d9a6cbb559276c6a57fe42119e4f 100644 (file)
@@ -28,8 +28,6 @@
 
 #include <asm/segment.h>
 
-extern int *blksize_size[];
-
 void msdos_put_inode(struct inode *inode)
 {
        struct inode *depend;
index bc9d83c5b4dc63ff6e49241d1c07fcb002b581ca..7ab4a7e4f749423a52e93948769cc50be0a86b68 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
 
 extern void locks_remove_locks(struct task_struct *, struct file *);
 
-asmlinkage int sys_ustat(int dev, struct ustat * ubuf)
-{
-       return -ENOSYS;
-}
-
 asmlinkage int sys_statfs(const char * path, struct statfs * buf)
 {
        struct inode * inode;
index 335ddd8395b29ff369b59b2d94aeb02c1fdd9a71..90e6f696863a4ec504eba3d1e4f683c7f8c78b37 100644 (file)
@@ -31,7 +31,6 @@
 
 extern int close_fp(struct file *filp);
 
-int smb_notify_change(struct inode *, struct iattr *);
 static void smb_put_inode(struct inode *);
 static void smb_read_inode(struct inode *);
 static void smb_put_super(struct super_block *);
index 15dcb2f9e35120a42c49662085faa8131cf51801..708bd3784ce413e2271e98c45cdbc2ccd3c31627 100644 (file)
@@ -37,7 +37,6 @@
 #define LO_WORD(l) ((word)(l % 0xFFFF))
 
 void smb_printerr(int class, int num);
-int smb_request(struct smb_server *);
 static int smb_request_ok(struct smb_server *s, int command, int wct, int bcc);
 
 /*****************************************************************************/
index 7ed9ad025c6430a673a084bb3b4d627868afd872..6cfd256f8e8fc2d75fdad90efe63fd82df206761 100644 (file)
@@ -254,6 +254,38 @@ void put_super(dev_t dev)
                sb->s_op->put_super(sb);
 }
 
+asmlinkage int sys_ustat(dev_t dev, struct ustat * ubuf)
+{
+        struct super_block *s;
+        struct ustat tmp;
+        struct statfs sbuf;
+        unsigned long old_fs;
+        int error;
+
+        s = get_super(dev);
+        if (s == NULL)
+                return -EINVAL;
+
+        if (!(s->s_op->statfs))
+                return -ENOSYS;
+
+        error = verify_area(VERIFY_WRITE,ubuf,sizeof(struct ustat));
+        if (error)
+                return error;
+
+        old_fs = get_fs();
+        set_fs(get_ds());
+        s->s_op->statfs(s,&sbuf,sizeof(struct statfs));
+        set_fs(old_fs);
+
+        memset(&tmp,0,sizeof(struct ustat));
+        tmp.f_tfree = sbuf.f_bfree;
+        tmp.f_tinode = sbuf.f_ffree;
+
+        memcpy_tofs(ubuf,&tmp,sizeof(struct ustat));
+        return 0;
+}
+
 static struct super_block * read_super(dev_t dev,const char *name,int flags,
                                       void *data, int silent)
 {
index cfd85993e7dcfe957735381c965c5fc08fdf4c6f..3e97711424c68b02e04cb6ca60382dca784b7f90 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/fs.h>
 #include <linux/sysv_fs.h>
 #include <linux/stat.h>
+#include <linux/string.h>
 
 static int sysv_dir_read(struct inode * inode, struct file * filp, char * buf, int count)
 {
index 897f8b0a71b6b59cf9ea38723ecd30100d881609..1b1c8937cdfff45c273cca5c418bf0c6d28da08c 100644 (file)
@@ -126,7 +126,6 @@ void umsdos_startlookup (struct inode *dir)
        while (umsdos_waitcreate (dir) != 0);
        dir->u.umsdos_i.u.dir_info.looking++;
 }
-void check_page_tables(void);
 
 /*
        Unlock the directory.
index 16eed3f5891bb4ff6a5787f8ff0e7d1428167a91..86cbf5584a43b0218699c331de9245b1071ec03f 100644 (file)
@@ -50,9 +50,25 @@ typedef unsigned long pgprot_t;
 
 #endif
 
+/*
+ * TLB invalidation:
+ *
+ *  - invalidate() invalidates the current task TLBs
+ *  - invalidate_all() invalidates all processes TLBs
+ *  - invalidate_task(task) invalidates the specified tasks TLB's
+ *  - invalidate_page(task, vmaddr) invalidates one page
+ *
+ * ..but the i386 has somewhat limited invalidation capabilities.
+ */
 #define invalidate() \
 __asm__ __volatile__("movl %%cr3,%%eax\n\tmovl %%eax,%%cr3": : :"ax")
 
+#define invalidate_all() invalidate()
+#define invalidate_task(task) \
+do { if ((task)->mm == current->mm) invalidate(); } while (0)
+#define invalidate_page(task,addr) \
+do { if ((task)->mm == current->mm) invalidate(); } while (0)
+
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)       (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
index 76e279dc4f927d0c95086798da31920a51d936dc..7ea1845bcc89f92e079d685aee35572bf64cab99 100644 (file)
@@ -1,6 +1,12 @@
 #ifndef _I386_PGTABLE_H
 #define _I386_PGTABLE_H
 
+/*
+ * Define CONFIG_PENTIUM_MM if you want the 4MB page table optimizations.
+ * This works only on a intel Pentium.
+ */
+#define CONFIG_PENTIUM_MM 1
+
 /*
  * The Linux memory management assumes a three-level page table setup. On
  * the i386, we use that, but "fold" the mid level into the top-level page
 #define VMALLOC_START ((high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) (TASK_SIZE + (unsigned long)(x))
 
+/*
+ * The 4MB page is guessing..  Detailed in the infamous "Chapter H"
+ * of the Pentium details, but assuming intel did the straigtforward
+ * thing, this bit set in the page directory entry just means that
+ * the page directory entry points directly to a 4MB-aligned block of
+ * memory. 
+ */
 #define _PAGE_PRESENT  0x001
 #define _PAGE_RW       0x002
 #define _PAGE_USER     0x004
 #define _PAGE_PCD      0x010
 #define _PAGE_ACCESSED 0x020
 #define _PAGE_DIRTY    0x040
+#define _PAGE_4M       0x080   /* 4 MB page, Pentium+.. */
 #define _PAGE_COW      0x200   /* implemented in software (one of the AVL bits) */
 
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
@@ -127,8 +141,6 @@ do { \
                __asm__ __volatile__("movl %0,%%cr3": :"a" ((tsk)->tss.cr3)); \
 } while (0)
 
-extern unsigned long high_memory;
-
 extern inline int pte_none(pte_t pte)          { return !pte_val(pte); }
 extern inline int pte_present(pte_t pte)       { return pte_val(pte) & _PAGE_PRESENT; }
 extern inline int pte_inuse(pte_t *ptep)       { return mem_map[MAP_NR(ptep)] != 1; }
@@ -142,7 +154,11 @@ extern inline void pte_reuse(pte_t * ptep)
 extern inline int pmd_none(pmd_t pmd)          { return !pmd_val(pmd); }
 extern inline int pmd_bad(pmd_t pmd)           { return (pmd_val(pmd) & ~PAGE_MASK) != _PAGE_TABLE || pmd_val(pmd) > high_memory; }
 extern inline int pmd_present(pmd_t pmd)       { return pmd_val(pmd) & _PAGE_PRESENT; }
+#ifdef CONFIG_PENTIUM_MM
+extern inline int pmd_inuse(pmd_t *pmdp)       { return (pmd_val(*pmdp) & _PAGE_4M) != 0; }
+#else
 extern inline int pmd_inuse(pmd_t *pmdp)       { return 0; }
+#endif
 extern inline void pmd_clear(pmd_t * pmdp)     { pmd_val(*pmdp) = 0; }
 extern inline void pmd_reuse(pmd_t * pmdp)     { }
 
@@ -261,6 +277,7 @@ extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
  */
 extern inline void pmd_free_kernel(pmd_t * pmd)
 {
+       pmd_val(*pmd) = 0;
 }
 
 extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
@@ -302,6 +319,7 @@ extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
  */
 extern inline void pmd_free(pmd_t * pmd)
 {
+       pmd_val(*pmd) = 0;
 }
 
 extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
index c5c0347bc5829441260c0bdc60553555aeb543dd..8170facfea50bc1214d178d1797b53fd4444ec98 100644 (file)
@@ -288,8 +288,6 @@ __asm__ __volatile__(
 return __res;
 }
 
-extern char * ___strtok;
-
 #define __HAVE_ARCH_STRTOK
 extern inline char * strtok(char * s,const char * ct)
 {
index 8319d3fe496ddb4b41e11261fe24393aece1d4ec..07dcc568d3491ab14e3e4fc9827ca80813171f8a 100644 (file)
@@ -37,7 +37,7 @@ extern unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev);
 extern void            eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
 extern void            eth_copy_and_sum(struct sk_buff *dest,
                                unsigned char *src, int length, int base);
-extern void            eth_header_cache(struct device *dev, struct sock *sk, unsigned long saddr, unsigned long daddr);
+
 
 #endif
 
index 97a8a3e71e776fe47777256bc2fb3eaa6f1623d7..da7ef21cfad7fa40b296adfa65ccc4ce92e8a699 100644 (file)
@@ -138,8 +138,7 @@ struct buffer_head {
        unsigned char b_lock;           /* 0 - ok, 1 -locked */
        unsigned char b_req;            /* 0 if the buffer has been invalidated */
        unsigned char b_list;           /* List that this buffer appears */
-       unsigned char b_retain;         /* Expected number of times this will
-                                          be used.  Put on freelist when 0 */
+       unsigned char b_reuse;          /* 0 - normal, 1 - better reused for something else */
        unsigned long b_flushtime;      /* Time when this (dirty) buffer should be written */
        unsigned long b_lru_time;       /* Time when this buffer was last used. */
        struct wait_queue * b_wait;
index 29bafa34f4fc43473f31e5b3defc078b29b03917..1000d9c4c368f2f1c033a687b24f0d0884889988 100644 (file)
@@ -87,7 +87,8 @@ struct ip_fw
 #define IP_FW_F_TCPSYN 0x080   /* For tcp packets-check SYN only     */
 #define IP_FW_F_ICMPRPL 0x100  /* Send back icmp unreachable packet  */
 #define IP_FW_F_MASQ   0x200   /* Masquerading                       */
-#define IP_FW_F_MASK   0x3FF   /* All possible flag bits mask        */
+#define IP_FW_F_TCPACK 0x400   /* For tcp-packets match if ACK is set*/
+#define IP_FW_F_MASK   0x7FF   /* All possible flag bits mask        */
 
 /*    
  *     New IP firewall options for [gs]etsockopt at the RAW IP level.
index 41bed3681106c546bacc0de8573e10515aee9c85..24ae6f4ed974945f0fc300ffcb8d5b818d9f06b4 100644 (file)
@@ -193,6 +193,7 @@ extern void si_meminfo(struct sysinfo * val);
 /* vmalloc.c */
 
 extern void * vmalloc(unsigned long size);
+extern void * vremap(unsigned long offset, unsigned long size);
 extern void vfree(void * addr);
 extern int vread(char *buf, char *addr, int count);
 
index 85ded6a618a29e4e356db27c8ec9a619a91df2b6..e1117d1e5fa46897f6c35d588ad60e8795c7d2ad 100644 (file)
@@ -43,6 +43,8 @@
 #define SYS_SHUTDOWN   13              /* sys_shutdown(2)              */
 #define SYS_SETSOCKOPT 14              /* sys_setsockopt(2)            */
 #define SYS_GETSOCKOPT 15              /* sys_getsockopt(2)            */
+#define SYS_SENDMSG    16              /* sys_sendmsg(2)               */
+#define SYS_RECVMSG    17              /* sys_recvmsg(2)               */
 
 
 typedef enum {
@@ -124,6 +126,8 @@ struct proto_ops {
                         char *optval, int *optlen);
   int  (*fcntl)        (struct socket *sock, unsigned int cmd,
                         unsigned long arg);    
+  int   (*sendmsg)     (struct socket *sock, struct msghdr *m, int total_len, int nonblock, int flags);
+  int   (*recvmsg)     (struct socket *sock, struct msghdr *m, int total_len, int nonblock, int flags, int *addr_len);
 };
 
 struct net_proto {
index d3c1f7dcc04c1eaa88f82c15370e45f5e3d749a3..25f31303498e45e7e5a6fc7e5cf646916efaffa5 100644 (file)
@@ -215,6 +215,45 @@ extern int         dev_ioctl(unsigned int cmd, void *);
 
 extern void            dev_init(void);
 
+/* Locking protection for page faults during outputs to devices unloaded during the fault */
+
+extern int             dev_lockct;
+
+/*
+ *     These two dont currently need to be interrupt safe
+ *     but they may do soon. Do it properly anyway.
+ */
+
+extern __inline__ void  dev_lock_list(void)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+       dev_lockct++;
+       restore_flags(flags);
+}
+
+extern __inline__ void  dev_unlock_list(void)
+{
+       unsigned long flags;
+       save_flags(flags);
+       cli();
+       dev_lockct--;
+       restore_flags(flags);
+}
+
+/*
+ *     This almost never occurs, isnt in performance critical paths
+ *     and we can thus be relaxed about it
+ */
+extern __inline__ void dev_lock_wait(void)
+{
+       while(dev_lockct)
+               schedule();
+}
+
+
 /* These functions live elsewhere (drivers/net/net_init.c, but related) */
 
 extern void            ether_setup(struct device *dev);
index a59f2ee5d75a85f012cbc9b638d5c5626eb8efbc..978128f55ec2caf18d0dd8e03ecef70e367148f5 100644 (file)
@@ -58,6 +58,9 @@
 #define  PCI_COMMAND_FAST_BACK 0x200   /* Enable back-to-back writes */
 
 #define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF                0x40    /* Support User Definable Features */
+
 #define  PCI_STATUS_FAST_BACK  0x80    /* Accept fast-back to back */
 #define  PCI_STATUS_PARITY     0x100   /* Detected parity error */
 #define  PCI_STATUS_DEVSEL_MASK        0x600   /* DEVSEL timing */
 #define  PCI_BASE_ADDRESS_IO_MASK      (~0x03)
 /* bit 1 is reserved if address_space = 1 */
 
-/* 0x28-0x2f are reserved */
+#define PCI_CARDBUS_CIS                0x28
+#define PCI_SUBSYSTEM_ID       0x2c
+#define PCI_SUBSYSTEM_VENDOR_ID        0x2e  
 #define PCI_ROM_ADDRESS                0x30    /* 32 bits */
 #define  PCI_ROM_ADDRESS_ENABLE        0x01    /* Write 1 to enable ROM,
                                           bits 31..11 are address,
 #define PCI_CLASS_STORAGE_IDE          0x0101
 #define PCI_CLASS_STORAGE_FLOPPY       0x0102
 #define PCI_CLASS_STORAGE_IPI          0x0103
+#define PCI_CLASS_STORAGE_RAID         0x0104 
 #define PCI_CLASS_STORAGE_OTHER                0x0180
 
 #define PCI_BASE_CLASS_NETWORK         0x02
 #define PCI_CLASS_NETWORK_ETHERNET     0x0200
 #define PCI_CLASS_NETWORK_TOKEN_RING   0x0201
 #define PCI_CLASS_NETWORK_FDDI         0x0202
+#define PCI_CLASS_NETWORK_ATM          0x0203
 #define PCI_CLASS_NETWORK_OTHER                0x0280
 
 #define PCI_BASE_CLASS_DISPLAY         0x03
 #define  PCI_CLASS_BRIDGE_MC           0x0603
 #define  PCI_CLASS_BRIDGE_PCI          0x0604
 #define  PCI_CLASS_BRIDGE_PCMCIA       0x0605
+#define  PCI_CLASS_BRIDGE_NUBUS                0x0606
+#define  PCI_CLASS_BRIDGE_CARDBUS      0x0607
 #define  PCI_CLASS_BRIDGE_OTHER                0x0680
 
+
+#define PCI_BASE_CLASS_COMMUNICATION   0x07
+#define PCI_CLASS_COMMUNICATION_SERIAL 0x0700
+#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
+#define PCI_CLASS_COMMUNICATION_OTHER  0x0780
+
+#define PCI_BASE_CLASS_SYSTEM          0x08
+#define PCI_CLASS_SYSTEM_PIC           0x0800
+#define PCI_CLASS_SYSTEM_DMA           0x0801
+#define PCI_CLASS_SYSTEM_TIMER         0x0802
+#define PCI_CLASS_SYSTEM_RTC           0x0803
+#define PCI_CLASS_SYSTEM_OTHER         0x0880
+
+#define PCI_BASE_CLASS_INPUT           0x09
+#define PCI_CLASS_INPUT_KEYBOARD       0x0900
+#define PCI_CLASS_INPUT_PEN            0x0901
+#define PCI_CLASS_INPUT_MOUSE          0x0902
+#define PCI_CLASS_INPUT_OTHER          0x0980
+
+#define PCI_BASE_CLASS_DOCKING         0x0a
+#define PCI_CLASS_DOCKING_GENERIC      0x0a00
+#define PCI_CLASS_DOCKING_OTHER                0x0a01
+
+#define PCI_BASE_CLASS_PROCESSOR       0x0b
+#define PCI_CLASS_PROCESSOR_386                0x0b00
+#define PCI_CLASS_PROCESSOR_486                0x0b01
+#define PCI_CLASS_PROCESSOR_PENTIUM    0x0b02
+#define PCI_CLASS_PROCESSOR_ALPHA      0x0b10
+#define PCI_CLASS_PROCESSOR_POWERPC    0x0b20
+#define PCI_CLASS_PROCESSOR_CO         0x0b40
+
+#define PCI_BASE_CLASS_SERIAL          0x0c
+#define PCI_CLASS_SERIAL_FIREWIRE      0x0c00
+#define PCI_CLASS_SERIAL_ACCESS                0x0c01
+#define PCI_CLASS_SERIAL_SSA           0x0c02
+#define PCI_CLASS_SERIAL_USB           0x0c03
+#define PCI_CLASS_SERIAL_FIBER         0x0c04
+
 #define PCI_CLASS_OTHERS               0xff
 
 
 #define PCI_DEVICE_ID_INTEL_82371      0x122e
 #define PCI_DEVICE_ID_INTEL_82438      0x1230
 #define PCI_DEVICE_ID_INTEL_7116       0x1223
+#define PCI_DEVICE_ID_INTEL_82865      0x1227
 
 #define PCI_VENDOR_ID_SMC              0x1042
 #define PCI_DEVICE_ID_SMC_37C665       0x1000
 #define PCI_DEVICE_ID_AL_M1445         0x1445
 #define PCI_DEVICE_ID_AL_M1449         0x1449
 #define PCI_DEVICE_ID_AL_M1451         0x1451
+#define PCI_DEVICE_ID_AL_M1461         0x1461
 #define PCI_DEVICE_ID_AL_M4803         0x5215
 
 #define PCI_VENDOR_ID_TSENG            0x100c
index 4a1581a99fe83e6497e3a3efbe40041d3899b989..4ab4f5bf5b91a02629373ba22806c39d78ead832 100644 (file)
@@ -546,8 +546,8 @@ struct scc_channel {
 #define FDA    0x40            /* FIFO Data Available Status */
 #define FOY    0x80            /* FIFO Overflow Status */
 
-#endif /* _SCC_H */
-
 /* global functions */
 
 extern long scc_init(long kmem_start);
+
+#endif /* _SCC_H */
index 121969c62ce5b324615aa85643d593177ba26f01..9ff308ee4182cf393773b8b6fe24a92efbc028c6 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <asm/socket.h>                        /* arch-dependent defines       */
 #include <linux/sockios.h>             /* the SIOCxxx I/O controls     */
-
+#include <linux/uio.h>                 /* iovec support                */
 
 struct sockaddr {
   unsigned short       sa_family;      /* address family, AF_xxx       */
@@ -15,6 +15,16 @@ struct linger {
   int                  l_linger;       /* How long to linger for       */
 };
 
+struct msghdr 
+{
+       void    *       msg_name;       /* Socket name                  */
+       int             msg_namelen;    /* Length of name               */
+       struct iovec *  msg_iov;        /* Data blocks                  */
+       int             msg_iovlen;     /* Number of blocks             */
+       void    *       msg_accrights;  /* Per protocol magic (eg BSD file descriptor passing) */
+       int             msg_accrightslen;       /* Length of rights list */
+};
+
 /* Socket types. */
 #define SOCK_STREAM    1               /* stream (connection) socket   */
 #define SOCK_DGRAM     2               /* datagram (conn.less) socket  */
@@ -103,4 +113,11 @@ struct linger {
 #define SOPRI_NORMAL           1
 #define SOPRI_BACKGROUND       2
 
+#ifdef __KERNEL__
+extern void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
+extern int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode);
+extern void memcpy_toiovec(struct iovec *v, unsigned char *kdata, int len);
+extern int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen);
+extern int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr);
+#endif
 #endif /* _LINUX_SOCKET_H */
diff --git a/include/linux/uio.h b/include/linux/uio.h
new file mode 100644 (file)
index 0000000..8051b3d
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __LINUX_UIO_H
+#define __LINUX_UIO_H
+
+/*
+ *     Berkeley style UIO structures   -       Alan Cox 1994.
+ *
+ *             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.
+ */
+
+
+/* A word of warning: Our uio structure will clash with the C library one (which is now obsolete). Remove the C
+   library one from sys/uio.h */
+
+struct iovec
+{
+       void *iov_base;         /* BSD uses caddr_t (same thing in effect) */
+       int iov_len;
+};
+
+#define MAX_IOVEC      8       /* Maximum iovec's in one operation */
+
+#endif
index 046947e476fe4e9422e1edc7411fcf3bca650268..5a1244876f295b20c483566c5bace6c06e23b50d 100644 (file)
@@ -104,7 +104,6 @@ typedef struct {
        const char *name;
 } XD_SIGNATURE;
 
-u_long xd_init (u_long mem_start,u_long mem_end);
 void xd_setup (char *command,int *integers);
 static u_char xd_detect (u_char *controller,u_char **address);
 static u_char xd_initdrives (void (*init_drive)(u_char drive));
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
new file mode 100644 (file)
index 0000000..dc4a48d
--- /dev/null
@@ -0,0 +1,4 @@
+extern void unix_proto_init(struct net_proto *pro);
+
+typedef struct sock unix_socket;
+
index fa39c44404f49ab12b8119f1925837beb9e352d4..1bbe7cf17ff69433e3881a3b4f9373653200034b 100644 (file)
 #define SOCK_ARRAY_SIZE        256             /* Think big (also on some systems a byte is faster */
 
 
+/*
+ *     The AF_UNIX specific socket options
+ */
+struct unix_opt
+{
+       int                     family;
+       char *                  name;
+       int                     locks;
+       struct inode *          inode;
+       struct semaphore        readsem;
+       struct sock *           other;
+};
+
+
 /*
  * This structure really needs to be cleaned up.
  * Most of it is for TCP, and not used by any of
@@ -160,6 +175,16 @@ struct sock {
 #ifdef CONFIG_ATALK
   struct atalk_sock            at;
 #endif
+  
+/*
+ *     This is where all the private (optional) areas that dont overlap will eventually live
+ *     for now just AF_UNIX is here.
+ */
+
+  union
+  {
+       struct unix_opt         af_unix;
+  } protinfo;                  
 
 /* IP 'private area' or will be eventually */
   int                          ip_ttl;                 /* TTL setting                          */
diff --git a/include/net/unix.h b/include/net/unix.h
deleted file mode 100644 (file)
index dba4380..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * UNIX                An implementation of the AF_UNIX network domain for the
- *             LINUX operating system.  UNIX is implemented using the
- *             BSD Socket interface as the means of communication with
- *             the user level.
- *
- *             This file describes some things of the UNIX protocol family
- *             module.  It is mainly used for the "proc" sub-module now,
- *             but it may be useful for cleaning up the UNIX module as a
- *             whole later.
- *
- * Version:    @(#)unix.h      1.0.3   05/25/93
- *
- * Authors:    Orest Zborowski, <obz@Kodak.COM>
- *             Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- *             Dmitry Gorodchanin      -       proc locking
- *
- *             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.
- */
-
-
-#ifdef _LINUX_UN_H
-
-
-struct unix_proto_data {
-       int             refcnt;         /* cnt of reference 0=free      */
-                                       /* -1=not initialised   -bgm    */
-       struct socket   *socket;        /* socket we're bound to        */
-       int             protocol;
-       struct sockaddr_un      sockaddr_un;
-       short           sockaddr_len;   /* >0 if name bound             */
-       char            *buf;
-       int             bp_head, bp_tail;
-       struct inode    *inode;
-       struct unix_proto_data  *peerupd;
-       struct wait_queue *wait;        /* Lock across page faults (FvK) */
-       int             lock_flag;
-};
-
-extern struct unix_proto_data unix_datas[NSOCKETS_UNIX];
-
-
-#define last_unix_data         (unix_datas + NSOCKETS_UNIX - 1)
-
-
-#define UN_DATA(SOCK)          ((struct unix_proto_data *)(SOCK)->data)
-#define UN_PATH_OFFSET         ((unsigned long)((struct sockaddr_un *)0) \
-                                                       ->sun_path)
-
-/*
- * Buffer size must be power of 2. buffer mgmt inspired by pipe code.
- * note that buffer contents can wraparound, and we can write one byte less
- * than full size to discern full vs empty.
- */
-#define BUF_SIZE               PAGE_SIZE
-#define UN_BUF_AVAIL(UPD)      (((UPD)->bp_head - (UPD)->bp_tail) & \
-                                                               (BUF_SIZE-1))
-#define UN_BUF_SPACE(UPD)      ((BUF_SIZE-1) - UN_BUF_AVAIL(UPD))
-
-#endif /* _LINUX_UN_H */
-
-
-extern void    unix_proto_init(struct net_proto *pro);
index e5087b25ff2b7e974a289e02ec95c7b8d0add170..8e9e1dd5ea8feefeab32381f54019c5bd124e872 100644 (file)
@@ -369,7 +369,6 @@ static void parse_options(char *line)
        envp_init[envs+1] = NULL;
 }
 
-extern void check_bugs(void);
 extern void setup_arch(char **, unsigned long *, unsigned long *);
 
 asmlinkage void start_kernel(void)
index e6c136144572904ceda49fca19fca76048372d16..3e923629b8ec29d449114b17078230efa5eeb43b 100644 (file)
@@ -30,8 +30,8 @@ static unsigned long tvtojiffies(struct timeval *value)
        unsigned long sec = (unsigned) value->tv_sec;
        unsigned long usec = (unsigned) value->tv_usec;
 
-       if (sec > (unsigned) (LONG_MAX / HZ))
-               return LONG_MAX;
+       if (sec > (ULONG_MAX / HZ))
+               return ULONG_MAX;
        usec += 1000000 / HZ - 1;
        usec /= 1000000 / HZ;
        return HZ*sec+usec;
@@ -46,17 +46,20 @@ static void jiffiestotv(unsigned long jiffies, struct timeval *value)
 
 static int _getitimer(int which, struct itimerval *value)
 {
-       register long val, interval;
+       register unsigned long val, interval;
 
        switch (which) {
        case ITIMER_REAL:
                interval = current->it_real_incr;
                val = 0;
                if (del_timer(&current->real_timer)) {
-                       val = current->real_timer.expires-jiffies;
+                       unsigned long now = jiffies;
+                       val = current->real_timer.expires;
                        add_timer(&current->real_timer);
-                       if (val <= 0)
-                               val = interval;
+                       /* look out for negative/zero itimer.. */
+                       if (val <= now)
+                               val = now+1;
+                       val -= now;
                }
                break;
        case ITIMER_VIRTUAL:
@@ -95,10 +98,16 @@ asmlinkage int sys_getitimer(int which, struct itimerval *value)
 void it_real_fn(unsigned long __data)
 {
        struct task_struct * p = (struct task_struct *) __data;
+       unsigned long interval;
 
        send_sig(SIGALRM, p, 1);
-       if (p->it_real_incr) {
-               p->real_timer.expires = jiffies+p->it_real_incr;
+       interval = p->it_real_incr;
+       if (interval) {
+               unsigned long timeout = jiffies + interval;
+               /* check for overflow */
+               if (timeout < interval)
+                       timeout = ULONG_MAX;
+               p->real_timer.expires = timeout;
                add_timer(&p->real_timer);
        }
 }
@@ -115,12 +124,16 @@ int _setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
        switch (which) {
                case ITIMER_REAL:
                        del_timer(&current->real_timer);
-                       if (j) {
-                               current->real_timer.expires = jiffies+j;
-                               add_timer(&current->real_timer);
-                       }
                        current->it_real_value = j;
                        current->it_real_incr = i;
+                       if (!j)
+                               break;
+                       i = j + jiffies;
+                       /* check for overflow.. */
+                       if (i < j)
+                               i = ULONG_MAX;
+                       current->real_timer.expires = i;
+                       add_timer(&current->real_timer);
                        break;
                case ITIMER_VIRTUAL:
                        if (j)
index da15e334d593e0a1fef850654ccfbfd885f3826a..c894df3272a7adabd14c4dc860165df2e500b701 100644 (file)
@@ -68,16 +68,16 @@ extern struct file_operations * get_blkfops(unsigned int);
   
 extern void *sys_call_table;
 
-extern int aout_core_dump(long signr, struct pt_regs * regs);
-
 #ifdef CONFIG_FTAPE
 extern char * ftape_big_buffer;
 #endif
 
 #ifdef CONFIG_SCSI
 #include "../drivers/scsi/scsi.h"
+#include "../drivers/scsi/scsi_ioctl.h"
 #include "../drivers/scsi/hosts.h"
 #include "../drivers/scsi/constants.h"
+#include <linux/scsicam.h>
 
 extern int generic_proc_info(char *, char **, off_t, int, int, int);
 #endif
@@ -150,6 +150,7 @@ struct symbol_table symbol_table = {
        X(kmalloc),
        X(kfree_s),
        X(vmalloc),
+       X(vremap),
        X(vfree),
        X(mem_map),
 
index 0c51ad48f973d44c44ab11eba21f94ef4b0a5759..a93ec36dee175a54e5d79ba21a3ecee36eefd9a9 100644 (file)
@@ -716,12 +716,18 @@ static void do_timer(int irq, struct pt_regs * regs)
 asmlinkage unsigned int sys_alarm(unsigned int seconds)
 {
        struct itimerval it_new, it_old;
+       unsigned int oldalarm;
 
        it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
        it_new.it_value.tv_sec = seconds;
        it_new.it_value.tv_usec = 0;
        _setitimer(ITIMER_REAL, &it_new, &it_old);
-       return(it_old.it_value.tv_sec + (it_old.it_value.tv_usec / 1000000));
+       oldalarm = it_old.it_value.tv_sec;
+       /* ehhh.. We can't return 0 if we have an alarm pending.. */
+       /* And we'd better return too much than too little anyway */
+       if (it_old.it_value.tv_usec)
+               oldalarm++;
+       return oldalarm;
 }
 
 asmlinkage int sys_getpid(void)
index 6b37014ecda714c1b727161fcde5956b5e219e8d..5e76966d3988f82c54f41ff21d32cc6bb9b84d76 100644 (file)
@@ -118,7 +118,6 @@ static inline void free_one_pmd(pmd_t * dir)
 
 static inline void free_one_pgd(pgd_t * dir)
 {
-       int j;
        pmd_t * pmd;
 
        if (pgd_none(*dir))
@@ -130,12 +129,11 @@ static inline void free_one_pgd(pgd_t * dir)
        }
        pmd = pmd_offset(dir, 0);
        pgd_clear(dir);
-       if (pmd_inuse(pmd)) {
-               pmd_free(pmd);
-               return;
+       if (!pmd_inuse(pmd)) {
+               int j;
+               for (j = 0; j < PTRS_PER_PMD ; j++)
+                       free_one_pmd(pmd+j);
        }
-       for (j = 0; j < PTRS_PER_PMD ; j++)
-               free_one_pmd(pmd+j);
        pmd_free(pmd);
 }
        
@@ -258,7 +256,7 @@ static inline int copy_one_pmd(pmd_t * old_pmd, pmd_t * new_pmd)
        if (pmd_none(*old_pmd))
                return 0;
        if (pmd_bad(*old_pmd)) {
-               printk("copy_one_pmd: bad page table: probable memory corruption\n");
+               printk("copy_one_pmd: bad page table (%08lx): probable memory corruption\n", pmd_val(*old_pmd));
                pmd_clear(old_pmd);
                return 0;
        }
index 806f63fc90eb7d6eb6ca6106dcfd2453bcf62dc8..2831b985d4dded5a766606c2901b580e313097e1 100644 (file)
@@ -7,7 +7,7 @@ Initial patches to catch up with things we want to add.
 
 o      Merged in the Jorge Cwik fast checksum.         [TESTED]
 o      Added Arnt Gulbrandsen's fast UDP build.        [TESTED]
-o      Pauline Middelinks masquerade patch             [IN/COMPILES]
+o      Pauline Middelinks masquerade patch             [TESTED(bar spoof bug)]
 
 
 0.1
@@ -30,7 +30,7 @@ o     Protocol header cache support                   [TESTED]
 o      Fixed ip_build_xmit loopback bugs               [TESTED]
 o      Fixes for SIOCGSTAMP on SOCK_PACKET             [TESTED]
 o      Perfect hash on net_bh().                       [TESTED]
-o      Sonix ISDN driver.                              [NOT INCLUDED YET]
+o      Sonix ISDN driver.                              [SEPERATED/SENT]
 o      Use ip_build_xmit for raw sockets               [TESTED]
 o      3c501 fixed for speed                           [TESTED]
 ------->>>>>  ALPHA 002  <<<<<--------
@@ -46,7 +46,7 @@ o     IP build xmit fragment fixes                    [TESTED]
 o      TCP SWS probe fix                               [TESTED]
 o      Appletalk DDP                                   [TESTED]
 o      IP firewall bug fixed                           [TESTED]
-o      IP masquerade ftp port spoof                    [IN]
+o      IP masquerade ftp port spoof                    [IN/BUG]
 o      gcc 2.6.3 -O3 fix for checksum assembler        [TESTED]
 o      /proc support shows both timers                 [TESTED]
 o      TCP irtt support                                [TESTED]
@@ -73,7 +73,7 @@ o     Fixed a _stupid_ appletalk bug                  [TESTED]
 o      Missing include                                 [TESTED]
                -- Lots of people
 o      Can drop all source routes                      [TESTED]
-o      Printing fixes for ip_fw                        [IN]
+o      Printing fixes for ip_fw                        [TESTED]
 o      UDP checksum fix (Gerhard)                      [TESTED]
 o      Newer 3c505 driver from Juha Laiho              [IN]
 o      Security fix to axassociate                     [TESTED]
@@ -86,16 +86,16 @@ o   IP Firewall accounting zero bug                 [TESTED]
 
 o      Merged loadable firewall code                   [NOT INCLUDED YET]
 o      New buffers used totally non optimally          [TESTED]
-o      Fast ip_forwarding (needs changing)             [NOT INCLUDED YET]
+o      Fast ip_forwarding (needs changing)             [NOW INCLUDED IN 1.3.15]
 o      Fixed connection hang bug in new SWS code       [TESTED]
 o      Buffer management hack putting skbuff control
        after data in the frame because kmalloc is
        totally cache non-optimal                       [TESTED]
-o      Faster checksum [Tom May]                       [IN]
-o      Appletalk router fixes [Michael Callahan]       [IN]
+o      Faster checksum [Tom May]                       [TESTED]
+o      Appletalk router fixes [Michael Callahan]       [TESTED]
 o      TCP state error fixes [Mark Tamsky]             [TESTED]
 o      Verify area fixes [Heiko Eissfeldt]             [TESTED]
-o      Routes use metric field [John Naylor]           [IN]
+o      Routes use metric field [John Naylor]           [TESTED/NOT YET AS BSD]
 o      Major AX.25/NetROM fixes [John Nalor]           [TESTED]
 
 ------->>>>>  NET3 030  <<<<<----------
@@ -103,40 +103,40 @@ o Major AX.25/NetROM fixes [John Nalor]           [TESTED]
 o      Long word align ethernet IP headers (64byte align for pentium) [TESTED]
                (less helpful than I'd have liked)
 o      Fixed variable length header support to really work     [TESTED]
-o      Mend appletalk/ipx partially                    [IN]
+o      Mend appletalk/ipx partially                    [TESTED]
 o      Start playing with input checksum & copy        [TESTED]
-o      Fixed PPP and other oddments                    [IN]
-o      Mended IPIP                                     [Might work ;)]
+o      Fixed PPP and other oddments                    [TESTED]
+o      Mended IPIP                                     [TESTED]
 
 ------->>>>>    1.3.7   <<<<<----------
 
 o      Checksum bug fixed                              [TESTED]
-o      Lance driver panic cured                        [BROKEN]
+o      Lance driver panic cured                        [TESTED]
 o      DEC ALPHA stuff (Linus)                         [ASK HIM NOT ME]
 o      Always try to keep output packet order
        (eg for vat and BSD fast path tcp)              [TESTED]
 o      Copy the mac pointer in skb_clone               [TESTED]
-o      Fix tcpdump panic                               [IN]
+o      Fix tcpdump panic                               [TESTED]
 o      Fix dev_alloc_skb NULL deref bug                [TESTED]
 o      Fix Security error in SIGURG stuff              [TESTED]
-o      Missing 15 byte slack on ip_loopback            [IN, still has mcast bugs left!]
+o      Missing 15 byte slack on ip_loopback            [TESTED]
 
 ------->>>>>    1.3.8   <<<<<----------
 
-o      UDP snmp count fixed                            [IN]
-o      IP snmp out count fixed                         [IN]  (fragment still wrong)
-o      First bit of Dave Bonn's fast forwarding        [IN]
-o      Fix leaks and double free in firewalling        [IN]
+o      UDP snmp count fixed                            [TESTED]
+o      IP snmp out count fixed                         [TESTED]
+o      First bit of Dave Bonn's fast forwarding        [TESTED/NOW WORKS]
+o      Fix leaks and double free in firewalling        [TESTED]
 o      Fix memory scribble in ip_build_xmit            [TESTED]
 o      Do fast cases of ip_build_xmit first
        slows fragmented I/O down, speeds up smaller
        packets. UDP send ttcp can now touch 7.5Mbyte/sec
        with nothing else going on. UDP recv is slower 8( [TESTED]
-o      Fixed and enabled ethernet header caches        [IN]
-o      Removed junk from igmp                          [IN]
-o      Obscure UDP/copy&sum bug fix                    [IN]
-o      Fixed multicast                                 [IN]
-o      TCP does rerouting for most cases               [NOT WORKING YET]
+o      Fixed and enabled ethernet header caches        [TESTED]
+o      Removed junk from igmp                          [TESTED]
+o      Obscure UDP/copy&sum bug fix                    [TESTED]
+o      Fixed multicast                                 [TESTED]
+o      TCP does rerouting for most cases               [TESTED]
 
 ------->>>>>    1.3.14  <<<<<----------
 
@@ -145,24 +145,35 @@ o NetROM works                                    [IN]
 o      AX.25 works                                     [IN]
 o      Most modules need recompiling even though they
        load OK                                         [BLAME LINUS]
+o      Appletalk works nicely                          [CHECKED]
+o      Fast IP forwarding part 1 works                 [CHECKED]
 
 ------->>>>>   1.3.15  <<<<<---------
 o      Mike Shaver has started RFC1122 verification    [IN PROGRESS]
 o      Minor bug fixes                                 [IN]
 
-------->>>> ???? <<<--------
+------->>>> 1.3.16 <<<--------
+
+o      Missing patches for device change in TCP        [IN]
+o      Device locking                                  [IN]
+o      Infinite slip devices                           [IN]
+o      New AF_UNIX sockets                             [IN]
+o      Sendmsg/recvmsg (for some stuff only)           [IN]
+o      Device unload loopholes fixed                   [IN]
+o      Extra firewall abilities                        [IN]
+o      Appletalk node probe bug fix                    [IN]
+
+
 o      Finish merging the bridge code
-o      Device locking
 o      SIOCSLEEPRT patch
 o      Options support in ip_build_xmit                [PENDING]
 o      Fast checksum/copy on outgoing TCP
 o      Fast dev_grab_next() transmit reload function
        and dev_push_failed() ??
-o      Faster ip_forward                               [PENDING]
+o      Faster ip_forward last hit cache                [PENDING]
 o      Forwarding queue control (+ fairness algorithms ??)
 o      IP forward flow control.
-o      Infinite PPP/SLIP devices.
-o      PI2 card doesn't do AX.25 VC yet                [PENDING]
+o      Infinite PPP devices.
 o      AX.25 set protocol type
 o      Clean up RAW AX.25 sockets.
 o      Finish 802.2 Class I code to be compliant to the oddities of 802.2
@@ -171,7 +182,6 @@ o   Tidy BPQ support
 
 0.2
 ---
-o      New UNIX sockets include Pedro Roque's shutdown.
 o      New icmp.c.
 o      Better TCP window handling [Pedro Roque]
 o      IP option support.
@@ -197,7 +207,8 @@ Possible projects for victim^H^H^H^H^Holunteers
 
 1.     Verifying the correctness of implementation against RFC1122 and
 making a list of violations (BSD is sufficiently screwed up you can't
-implement all of RFC1122 and talk to it usefully).
+implement all of RFC1122 and talk to it usefully). [In progress - Mike
+Shaver]
 
 2.     Verifying all the error returns match the BSD ones (grotty job I
 wouldn't wish on anyone).
@@ -218,7 +229,7 @@ potential high speed TCP problems.
 5.     Fixing the IP fragment handling so that the total space allocated to
 fragments is limited and old fragments are deleted to make room for new ones
 when space is exhausted. Fixing the fragment handling to work at a decent
-speed wouldn't be bad either.
+speed wouldn't be bad either. [In progress - Arnt Gulbrandsen]
 
 6.     Delayed ack. This is mostly supported but not actually set up and
 used yet. Basically ack frames are held back 1/10th of a second in the hope
@@ -255,7 +266,8 @@ a maybe (so is finishing it ;))][Someone is working on Frame Relay].
 14.    Bidirectional PLIP. Also PLIP for the newer style parallel ports.
 
 15.    802.2LLC and thus Netbeui sockets. Becoming less important since the
-rumour is microsoft are phasing out netbeui for netbios/IP.
+rumour is microsoft are phasing out netbeui for netbios/IP.    
+       [Tentatively in progress]
 
 16.    X.25. This is one for a real head case with far too much time on 
 their hands. [Provisionally taken]
@@ -265,6 +277,8 @@ their hands. [Provisionally taken]
 18.    Implement swIPe under Linux.
 [In progress]
 
+19.    IPv4 IP-AH and IP-ESP.
+
 BTW: Don't let the magic words 'kernel programming' worry you. Its like DOS
 - you make a mistake you have to reboot. You do at least get dumps and a
 kernel logger that is reliable. There is now a loadable module allowing
index c21da2533f4a7ca9d101196f3d4265fb357989e7..b96d2885d18cde7aaf619b64f95c7c6b43de6656 100644 (file)
@@ -11,6 +11,8 @@
  *
  *     Fixes:
  *             Michael Callahan        :       Made routing work
+ *             Wesley Craig            :       Fix probing to listen to a
+ *                                             passed node id.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -318,6 +320,7 @@ static int atif_probe_device(struct atalk_iface *atif)
        int ct;
        int netrange=ntohs(atif->nets.nr_lastnet)-ntohs(atif->nets.nr_firstnet)+1;
        int probe_net=ntohs(atif->address.s_net);
+       int probe_node=atif->address.s_node;
        int netct;
        int nodect;
        
@@ -334,6 +337,9 @@ static int atif_probe_device(struct atalk_iface *atif)
                        probe_net=ntohs(atif->nets.nr_firstnet) + (jiffies%netrange);
        }
        
+       if(probe_node == ATADDR_ANYNODE)
+               probe_node = jiffies&0xFF;
+       
        
        /*
         *      Scan the networks.
@@ -342,14 +348,13 @@ static int atif_probe_device(struct atalk_iface *atif)
        for(netct=0;netct<=netrange;netct++)
        {
                /*
-                *      Sweep the available nodes from a random start.
+                *      Sweep the available nodes from a given start.
                 */
-               int nodeoff=jiffies&255;
-               
+
                atif->address.s_net=htons(probe_net);
                for(nodect=0;nodect<256;nodect++)
                {
-                       atif->address.s_node=((nodect+nodeoff)&0xFF);
+                       atif->address.s_node=((nodect+probe_node)&0xFF);
                        if(atif->address.s_node>0&&atif->address.s_node<254)
                        {
                                /*
index d22e63e003ae70533d0a17965196eb4a58c7be8b..4613297c7c5e6e55f0727156ea2e3ffdcf199741 100644 (file)
@@ -13,7 +13,7 @@
        $(AS) -o $*.o $<
 
 
-OBJS   := sock.o dev.o dev_mcast.o skbuff.o datagram.o
+OBJS   := sock.o dev.o dev_mcast.o skbuff.o datagram.o iovec.o
 
 ifdef CONFIG_NET
 
diff --git a/net/core/iovec.c b/net/core/iovec.c
new file mode 100644 (file)
index 0000000..c5c3c3a
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ *     iovec manipulation routines.
+ *
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/net.h>
+#include <asm/segment.h>
+
+
+extern inline int min(int x, int y)
+{
+       return x>y?y:x;
+}
+
+int verify_iovec(struct msghdr *m, struct iovec *iov, char *address, int mode)
+{
+       int err=0;
+       int len=0;
+       int ct;
+       
+       if(m->msg_name!=NULL)
+       {
+               if(mode==VERIFY_READ)
+                       err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);
+               else
+                       err=verify_area(mode, m->msg_name, m->msg_namelen);
+               if(err<0)
+                       return err;
+       }
+       if(m->msg_accrights!=NULL)
+       {
+               err=verify_area(mode, m->msg_accrights, m->msg_accrightslen);
+               if(err)
+                       return err;
+       }
+       
+       for(ct=0;ct<m->msg_iovlen;ct++)
+       {
+               err=verify_area(mode, m->msg_iov[ct].iov_base, m->msg_iov[ct].iov_len);
+               if(err)
+                       return err;
+               len+=m->msg_iov[ct].iov_len;
+       }
+       
+       return len;
+}
+
+/*
+ *     Copy kernel to iovec.
+ */
+void memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
+{
+       while(len>0)
+       {
+               memcpy_tofs(iov->iov_base, kdata,iov->iov_len);
+               kdata+=iov->iov_len;
+               len-=iov->iov_len;
+               iov++;
+       }
+}
+
+/*
+ *     Copy iovec to kernel.
+ */
+void memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len)
+{
+       int copy;
+       while(len>0)
+       {
+               copy=min(len,iov->iov_len);
+               memcpy_fromfs(kdata, iov->iov_base, copy);
+               len-=copy;
+               kdata+=copy;
+               iov++;
+       }
+}
+
index c7b921f05ea05b7b87aa7f029e3a44e92413b517..c9fbc17ffd269bccbb46fa7b18ef65dce7e2c726 100644 (file)
@@ -223,7 +223,7 @@ int ip_build_header(struct sk_buff *skb, unsigned long saddr, unsigned long dadd
         *      See if we need to look up the device.
         */
 
-#ifdef CONFIG_INET_MULTICAST   
+#ifdef CONFIG_IP_MULTICAST     
        if(MULTICAST(daddr) && *dev==NULL && skb->sk && *skb->sk->ip_mc_name)
                *dev=dev_get(skb->sk->ip_mc_name);
 #endif
@@ -854,9 +854,12 @@ void ip_fragment(struct sock *sk, struct sk_buff *skb, struct device *dev, int i
         */
 
        raw = skb->data;
-       iph = (struct iphdr *) (raw + dev->hard_header_len);
-
+#if 0
+       iph = (struct iphdr *) (raw + dev->hard_header_len);    
        skb->ip_hdr = iph;
+#else
+       iph = skb->ip_hdr;
+#endif
 
        /*
         *      Setup starting values.
@@ -1741,7 +1744,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
              struct sk_buff *skb, int free)
 {
        struct iphdr *iph;
-       unsigned char *ptr;
+/*     unsigned char *ptr;*/
 
        /* Sanity check */
        if (dev == NULL)
@@ -1768,11 +1771,15 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
         *      header length problem
         */
 
+#if 0
        ptr = skb->data;
        ptr += dev->hard_header_len;
-       iph = (struct iphdr *)ptr;
+       iph = (struct iphdr *)ptr;      
        skb->ip_hdr = iph;
-       iph->tot_len = ntohs(skb->len-dev->hard_header_len);
+#else
+       iph = skb->ip_hdr;
+#endif
+       iph->tot_len = ntohs(skb->len-(((unsigned char *)iph)-skb->data));
 
 #ifdef CONFIG_IP_FIREWALL
        if(ip_fw_chk(iph, dev, ip_fw_blk_chain, ip_fw_blk_policy, 0) != 1)
@@ -1801,7 +1808,7 @@ void ip_queue_xmit(struct sock *sk, struct device *dev,
         *      bits of it.
         */
 
-       if(skb->len > dev->mtu + dev->hard_header_len)
+       if(ntohs(iph->tot_len)> dev->mtu)
        {
                ip_fragment(sk,skb,dev,0);
                IS_SKB(skb);
@@ -2370,13 +2377,17 @@ int ip_build_xmit(struct sock *sk,
        ip_statistics.IpOutRequests++;
 
 
-#ifdef CONFIG_INET_MULTICAST   
+#ifdef CONFIG_IP_MULTICAST     
        if(sk && MULTICAST(daddr) && *sk->ip_mc_name)
        {
-               dev=dev_get(skb->ip_mc_name);
+               dev=dev_get(sk->ip_mc_name);
                if(!dev)
                        return -ENODEV;
                rt=NULL;
+               if (sk->saddr && (!LOOPBACK(sk->saddr) || LOOPBACK(daddr)))
+                       saddr = sk->saddr;
+               else
+                       saddr = dev->pa_addr;
        }
        else
        {
@@ -2438,7 +2449,7 @@ int ip_build_xmit(struct sock *sk,
                        saddr = sk->saddr;
                        
                dev=rt->rt_dev;
-#ifdef CONFIG_INET_MULTICAST
+#ifdef CONFIG_IP_MULTICAST
        }
 #endif         
 
@@ -2691,15 +2702,15 @@ int ip_build_xmit(struct sock *sk,
                        if(sk==NULL || sk->ip_mc_loop) 
                        {
                                if(skb->daddr==IGMP_ALL_HOSTS)
-                                       ip_loopback(rt->rt_dev,skb);
+                                       ip_loopback(rt?rt->rt_dev:dev,skb);
                                else 
                                {
-                                       struct ip_mc_list *imc=rt->rt_dev->ip_mc_list;
+                                       struct ip_mc_list *imc=rt?rt->rt_dev->ip_mc_list:dev->ip_mc_list;
                                        while(imc!=NULL) 
                                        {
                                                if(imc->multiaddr==daddr) 
                                                {
-                                                       ip_loopback(rt->rt_dev,skb);
+                                                       ip_loopback(rt?rt->rt_dev:dev,skb);
                                                        break;
                                                }
                                                imc=imc->next;
index ce465334284657220fb5954e2ce3c31be70c5192..2bfbe4ff71c9ab53e74a3ee027b5978f9f378ce0 100644 (file)
@@ -19,6 +19,9 @@
  *     Porting bidirectional entries from BSD, fixing accounting issues,
  *     adding struct ip_fwpkt for checking packets with interface address
  *             Jos Vos 5/Mar/1995.
+ *     Established connections (ACK check), ACK check on bidirectional rules,
+ *     ICMP type check.
+ *             Wilfred Mollenvanger 7/7/1995.
  *
  * Masquerading functionality
  *
@@ -179,10 +182,11 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
        struct ip_fw *f;
        struct tcphdr           *tcp=(struct tcphdr *)((unsigned long *)ip+ip->ihl);
        struct udphdr           *udp=(struct udphdr *)((unsigned long *)ip+ip->ihl);
+       struct icmphdr          *icmp=(struct icmphdr *)((unsigned long *)ip+ip->ihl);
        __u32                   src, dst;
-       __u16                   src_port=0, dst_port=0;
+       __u16                   src_port=0, dst_port=0, icmp_type=0;
        unsigned short          f_prt=0, prt;
-       char                    notcpsyn=1, frag1, match;
+       char                    notcpsyn=1, notcpack=1, frag1, match;
        unsigned short          f_flag;
 
        /*
@@ -233,7 +237,10 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                        if (frag1) {
                                src_port=ntohs(tcp->source);
                                dst_port=ntohs(tcp->dest);
-                               if(tcp->syn && !tcp->ack)
+                               if(tcp->ack)
+                                       /* We *DO* have ACK, value FALSE */
+                                       notcpack=0;
+                               if(tcp->syn && notcpack)
                                        /* We *DO* have SYN, value FALSE */
                                        notcpsyn=0;
                        }
@@ -249,7 +256,8 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                        prt=IP_FW_F_UDP;
                        break;
                case IPPROTO_ICMP:
-                       dprintf2("ICMP:%d ",((char *)portptr)[0]&0xff);
+                       icmp_type=(__u16)(icmp->type);
+                       dprintf2("ICMP:%d ",icmp_type);
                        prt=IP_FW_F_ICMP;
                        break;
                default:
@@ -335,6 +343,21 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                         
                         if((f->fw_flg&IP_FW_F_TCPSYN) && notcpsyn)
                                continue;
+
+                       /*
+                        * When a bidirectional rule is used we only check
+                        * for ack bits on reverse matches. This way it's
+                        * easy to set up rules which only allow connections
+                        * initiated from "normal" match adresses.
+                        */
+
+                       if((f->fw_flg&IP_FW_F_TCPACK) && notcpack)
+                               if(f->fw_flg&IP_FW_F_BIDIR) {
+                                       if(match & 0x02)
+                                               continue;
+                               } else
+                                       continue;
+
                        /*
                         *      Specific firewall - packet's protocol
                         *      must match firewall's.
@@ -343,7 +366,10 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol
                        if(prt!=f_prt)
                                continue;
                                
-                       if(!(prt==IP_FW_F_ICMP || ((match & 0x01) &&
+                       if((prt==IP_FW_F_ICMP &&
+                               ! port_match(&f->fw_pts[0], f->fw_nsp,
+                                       icmp_type,f->fw_flg&IP_FW_F_SRNG)) ||
+                           !(prt==IP_FW_F_ICMP || ((match & 0x01) &&
                                port_match(&f->fw_pts[0], f->fw_nsp, src_port,
                                        f->fw_flg&IP_FW_F_SRNG) &&
                                port_match(&f->fw_pts[f->fw_nsp], f->fw_ndp, dst_port,
@@ -612,12 +638,13 @@ static struct sk_buff *revamp(struct sk_buff *skb, struct device *dev, struct ip
                if (!ftp->init_seq)
                        ftp->init_seq = th->seq;
  
-               skb2 = alloc_skb(skb->len+ftp->delta, GFP_ATOMIC);
+               skb2 = alloc_skb(MAX_HEADER + skb->len+ftp->delta, GFP_ATOMIC);
                if (skb2 == NULL) {
                        printk("MASQUERADE: No memory available\n");
                        return skb;
                }
                skb2->free = skb->free;
+               skb_reserve(skb2,MAX_HEADER);
                skb_put(skb2,skb->len + ftp->delta);
                skb2->h.raw = &skb2->data[skb->h.raw - skb->data];
  
@@ -1289,7 +1316,7 @@ int ip_fw_ctl(int stage, void *m, int len)
                if ( len < sizeof(struct ip_fwpkt) )
                {
 #ifdef DEBUG_CONFIG_IP_FIREWALL
-                       printf("ip_fw_ctl: length=%d, expected %d\n",
+                       printk("ip_fw_ctl: length=%d, expected %d\n",
                                len, sizeof(struct ip_fwpkt));
 #endif
                        return( EINVAL );
index ecab558cd91549c3f8976a597d8f73eeb6c9dea6..9cc86b335d83c1f9fb5791c04d949c3a9db445c3 100644 (file)
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
+ * Fixes
+ *     Alan Cox        :       Rarp delete on device down needed as
+ *                             reported by Walter Wolfgang.
+ *
  */
 
 #include <linux/types.h>
@@ -87,16 +91,6 @@ static struct packet_type rarp_packet_type =
 
 static initflag = 1;
 
-/*
- *     Called once when data first added to rarp cache with ioctl.
- */
-
-static void rarp_init (void)
-{
-       /* Register the packet type */
-       rarp_packet_type.type=htons(ETH_P_RARP);
-       dev_add_pack(&rarp_packet_type);
-}
 
 /*
  *     Release the memory for this entry.
@@ -133,6 +127,56 @@ static void rarp_destroy(unsigned long ip_addr)
        sti();
 }
 
+/*
+ *     Flush a device.
+ */
+
+static void rarp_destroy_dev(struct device *dev)
+{
+       struct rarp_table *entry;
+       struct rarp_table **pentry;
+  
+       cli();
+       pentry = &rarp_tables;
+       while ((entry = *pentry) != NULL)
+       {
+               if (entry->dev == dev)
+               {
+                       *pentry = entry->next;
+                       sti();
+                       rarp_release_entry(entry);
+               }
+               else
+                       pentry = &entry->next;
+       }
+       sti();
+}
+
+static int rarp_device_event(unsigned long event, void *ptr)
+{
+       if(event!=NETDEV_DOWN)
+               return NOTIFY_DONE;
+       rarp_destroy_dev((struct device *)ptr);
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Called once when data first added to rarp cache with ioctl.
+ */
+static struct notifier_block rarp_dev_notifier={
+       rarp_device_event,
+       NULL,
+       0
+};
+static void rarp_init (void)
+{
+       /* Register the packet type */
+       rarp_packet_type.type=htons(ETH_P_RARP);
+       dev_add_pack(&rarp_packet_type);
+       register_netdevice_notifier(&rarp_dev_notifier);
+}
 
 /*
  *     Receive an arp request by the device layer.  Maybe it should be 
@@ -145,8 +189,8 @@ int rarp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
 /*
  *     We shouldn't use this type conversion. Check later.
  */
-       struct arphdr *rarp = (struct arphdr *)skb->h.raw;
-       unsigned char *rarp_ptr = (unsigned char *)(rarp+1);
+       struct arphdr *rarp = (struct arphdr *)skb_pull(skb,sizeof(struct arphdr));
+       unsigned char *rarp_ptr = skb->data;
        struct rarp_table *entry;
        long sip,tip;
        unsigned char *sha,*tha;            /* s for "source", t for "target" */
index 76def985788e60af79d4262d919e1e983ad90c94..fcfb2df73e7bb48bf43d93aad40bc9bc2cb43171 100644 (file)
@@ -13,7 +13,7 @@
 #define CONFIG_UNIX            /* always present...    */
 
 #ifdef CONFIG_UNIX
-#include <net/unix.h>
+#include <net/af_unix.h>
 #endif
 #ifdef CONFIG_INET
 #include <linux/inet.h>
index 9c8663967d095e5eb52d92dedf51d7a0d77e39dd..a644878cb3431da118f10625af30248188e3fd79 100644 (file)
@@ -32,6 +32,7 @@
  *             Alan Cox        :       Made sock_alloc()/sock_release() public
  *                                     for NetROM and future kernel nfsd type
  *                                     stuff.
+ *             Alan Cox        :       sendmsg/recvmsg basics.
  *
  *
  *             This program is free software; you can redistribute it and/or
@@ -115,7 +116,7 @@ static int sockets_in_use  = 0;
 
 #define MAX_SOCK_ADDR  128             /* 108 for Unix domain - 16 for IP, 16 for IPX, about 80 for AX.25 */
  
-static int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr)
+int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr)
 {
        int err;
        if(ulen<0||ulen>MAX_SOCK_ADDR)
@@ -128,7 +129,7 @@ static int move_addr_to_kernel(void *uaddr, int ulen, void *kaddr)
        return 0;
 }
 
-static int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen)
+int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen)
 {
        int err;
        int len;
@@ -1089,6 +1090,86 @@ asmlinkage int sys_shutdown(int fd, int how)
        return(sock->ops->shutdown(sock, how));
 }
 
+/*
+ *     BSD sendmsg interface
+ */
+asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned int flags)
+{
+       struct socket *sock;
+       struct file *file;
+       char address[MAX_SOCK_ADDR];
+       struct iovec iov[MAX_IOVEC];
+       struct msghdr msg_sys;
+       int err;
+       int total_len;
+       
+       if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL))
+               return(-EBADF);
+       if (!(sock = sockfd_lookup(fd, NULL)))
+               return(-ENOTSOCK);
+       
+       err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr));
+       if(err)
+               return err;
+       memcpy_fromfs(&msg_sys,msg,sizeof(struct msghdr));
+       if(msg_sys.msg_iovlen>MAX_IOVEC)
+               return -EINVAL;
+       err=verify_iovec(&msg_sys,iov,address, VERIFY_READ);
+       if(err<0)
+               return err;
+       total_len=err;
+       
+       if(sock->ops->sendmsg==NULL)
+               return -EOPNOTSUPP;
+       return sock->ops->sendmsg(sock, &msg_sys, total_len, (file->f_flags&O_NONBLOCK), flags);
+}
+
+/*
+ *     BSD recvmsg interface
+ */
+asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
+{
+       struct socket *sock;
+       struct file *file;
+       char address[MAX_SOCK_ADDR];
+       struct iovec iov[MAX_IOVEC];
+       struct msghdr msg_sys;
+       int err;
+       int total_len;
+       int addr_len;
+       int len;
+       
+       if (fd < 0 || fd >= NR_OPEN || ((file = current->files->fd[fd]) == NULL))
+               return(-EBADF);
+       if (!(sock = sockfd_lookup(fd, NULL)))
+               return(-ENOTSOCK);
+       
+       err=verify_area(VERIFY_READ, msg,sizeof(struct msghdr));
+       if(err)
+               return err;
+       memcpy_fromfs(&msg_sys,msg,sizeof(struct msghdr));
+       if(msg_sys.msg_iovlen>MAX_IOVEC)
+               return -EINVAL;
+       err=verify_iovec(&msg_sys,iov,address, VERIFY_WRITE);
+       if(err<0)
+               return err;
+       total_len=err;
+       
+       if(sock->ops->recvmsg==NULL)
+               return -EOPNOTSUPP;
+       len=sock->ops->recvmsg(sock, &msg_sys, total_len, (file->f_flags&O_NONBLOCK), flags, &addr_len);
+       if(len<0)
+               return len;
+       /*
+        *      Fixme: writing actual length into original msghdr.
+        */
+       if(msg_sys.msg_name!=NULL && (err=move_addr_to_user(address,addr_len, msg_sys.msg_name, &msg_sys.msg_namelen))<0)
+               return err;
+       return len;
+}
+
 
 /*
  *     Perform a file control on a socket file descriptor.
@@ -1120,12 +1201,12 @@ int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg)
 asmlinkage int sys_socketcall(int call, unsigned long *args)
 {
        int er;
-       unsigned char nargs[16]={0,3,3,3,2,3,3,3,
-                                4,4,4,6,6,2,5,5};
+       unsigned char nargs[18]={0,3,3,3,2,3,3,3,
+                                4,4,4,6,6,2,5,5,3,3};
 
        unsigned long a0,a1;
                                 
-       if(call<1||call>SYS_GETSOCKOPT)
+       if(call<1||call>SYS_RECVMSG)
                return -EINVAL;
                
        er=verify_area(VERIFY_READ, args, nargs[call] * sizeof(unsigned long));
@@ -1198,6 +1279,14 @@ asmlinkage int sys_socketcall(int call, unsigned long *args)
                                get_user(args+2),
                                (char *)get_user(args+3),
                                (int *)get_user(args+4)));
+               case SYS_SENDMSG:
+                               return sys_sendmsg(a0,
+                                       (struct msghdr *) a1,
+                                       get_user(args+2));
+               case SYS_RECVMSG:
+                               return sys_recvmsg(a0,
+                                       (struct msghdr *) a1,
+                                       get_user(args+2));
        }
        return -EINVAL; /* to keep gcc happy */
 }
index de74dab6d0a7e68a10ffde9920311ab1e48184ec..f42d996ab0187b1834dbcd9d36434594136d975d 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Makefile for the UNIX Protocol Family.
+# Makefile for the Linux TCP/IP (INET) layer.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
 # removes any old dependencies. DON'T put your own dependencies here
 .s.o:
        $(AS) -o $*.o $<
 
-OBJS   = sock.o proc.o
 
-unix.o: $(OBJS)
-       $(LD) -r -o unix.o $(OBJS)
+OBJS   := af_unix.o
+
+
+unix.o:        $(OBJS)
+               $(LD) -r -o unix.o $(OBJS)
 
 dep:
-       $(CPP) -M *.c > .depend
+               $(CPP) -M *.c > .depend
 
 tar:
-       tar -cvf /dev/f1 .
+               tar -cvf /dev/f1 .
 
 
 include $(TOPDIR)/Rules.make
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
new file mode 100644 (file)
index 0000000..e8fdd26
--- /dev/null
@@ -0,0 +1,1016 @@
+/*
+ * NET3:       Implementation of BSD Unix domain sockets.
+ *
+ * Authors:    Alan Cox, <alan@cymru.net>
+ *
+ *             Currently this contains all but the file descriptor passing code.
+ *             Before that goes in the odd bugs in the iovec handlers need 
+ *             fixing, and this bit testing. BSD fd passing is a trivial part
+ *             of the exercise.
+ *
+ *             This program is free software; you can redistribute it and/or
+ *             modify it under the terms of the GNU General Public License
+ *             as published by the Free Software Foundation; either version
+ *             2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/stat.h>
+#include <linux/socket.h>
+#include <linux/un.h>
+#include <linux/fcntl.h>
+#include <linux/termios.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <linux/net.h>
+#include <linux/in.h>
+#include <linux/fs.h>
+#include <linux/malloc.h>
+#include <asm/segment.h>
+#include <linux/skbuff.h>
+/*#include <linux/netprotocol.h>*/
+#include <linux/netdevice.h>
+#include <net/sock.h>
+#include <net/tcp.h>
+#include <net/af_unix.h>
+
+static unix_socket *volatile unix_socket_list=NULL;
+
+#define min(a,b)       (((a)<(b))?(a):(b))
+
+/*
+ * Make sure the unix name is null-terminated.
+ */
+static inline void unix_mkname(struct sockaddr_un * sun, unsigned long len)
+{
+       if (len >= sizeof(*sun))
+               len = sizeof(*sun)-1;
+       ((char *)sun)[len]=0;
+}
+
+/*
+ *     Note: Sockets may not be removed _during_ an interrupt or net_bh
+ *     handler using this technique. They can be added although we do not
+ *     use this facility.
+ */
+static void unix_remove_socket(unix_socket *sk)
+{
+       unix_socket *s;
+       
+       cli();
+       s=unix_socket_list;
+       if(s==sk)
+       {
+               unix_socket_list=s->next;
+               sti();
+               return;
+       }
+       while(s && s->next)
+       {
+               if(s->next==sk)
+               {
+                       s->next=sk->next;
+                       sti();
+                       return;
+               }
+               s=s->next;
+       }
+       sti();
+}
+
+static void unix_insert_socket(unix_socket *sk)
+{
+       cli();
+       sk->next=unix_socket_list;
+       unix_socket_list=sk;
+       sti();
+}
+
+static unix_socket *unix_find_socket(struct inode *i)
+{
+       unix_socket *s;
+       cli();
+       s=unix_socket_list;
+       while(s)
+       {
+               if(s->protinfo.af_unix.inode==i)
+               {
+                       sti();
+                       return(s);
+               }
+               s=s->next;
+       }
+       sti();
+       return(NULL);
+}
+
+/*
+ *     Delete a unix socket. We have to allow for deferring this on a timer.
+ */
+
+static void unix_destroy_timer(unsigned long data)
+{
+       unix_socket *sk=(unix_socket *)data;
+       if(sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
+       {
+               if(sk->protinfo.af_unix.name)
+                       kfree(sk->protinfo.af_unix.name);
+               kfree_s(sk,sizeof(*sk));
+               return;
+       }
+       
+       /*
+        *      Retry;
+        */
+        
+       init_timer(&sk->timer);
+       sk->timer.expires=jiffies+10*HZ;        /* No real hurry try it every 10 seconds or so */
+       add_timer(&sk->timer);
+}
+        
+        
+static void unix_delayed_delete(unix_socket *sk)
+{
+       init_timer(&sk->timer);
+       sk->timer.data=(unsigned long)sk;
+       sk->timer.expires=jiffies+HZ;           /* Normally 1 second after will clean up. After that we try every 10 */
+       sk->timer.function=unix_destroy_timer;
+       add_timer(&sk->timer);
+}
+       
+static void unix_destroy_socket(unix_socket *sk)
+{
+       struct sk_buff *skb;
+       unix_remove_socket(sk);
+       
+       while((skb=skb_dequeue(&sk->receive_queue))!=NULL)
+       {
+               if(sk->state==TCP_LISTEN)
+               {
+                       unix_socket *osk=skb->sk;
+                       osk->state=TCP_CLOSE;
+                       kfree_skb(skb, FREE_WRITE);     /* Now surplus - free the skb first before the socket */
+                       osk->state_change(osk);         /* So the connect wakes and cleans up (if any) */
+                       /* osk will be destroyed when it gets to close or the timer fires */                    
+               }
+               else
+               {
+/*                     unix_kill_credentials(skb);     *//* Throw out any passed fd's */
+                       kfree_skb(skb,FREE_WRITE);
+               }
+       }
+       
+       if(sk->protinfo.af_unix.inode!=NULL)
+       {
+               iput(sk->protinfo.af_unix.inode);
+               sk->protinfo.af_unix.inode=NULL;
+       }
+       
+       if(--sk->protinfo.af_unix.locks==0 && sk->wmem_alloc==0)
+       {
+               if(sk->protinfo.af_unix.name)
+                       kfree(sk->protinfo.af_unix.name);
+               kfree_s(sk,sizeof(*sk));
+       }
+       else
+       {
+               sk->dead=1;
+               unix_delayed_delete(sk);        /* Try every so often until buffers are all freed */
+       }
+}
+
+/*
+ *     Fixme: We need async I/O on AF_UNIX doing next.
+ */
+static int unix_fcntl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       return -EINVAL;
+}
+
+/*
+ *     Yes socket options work with the new unix domain socketry!!!!!!!
+ */
+static int unix_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen)
+{
+       unix_socket *sk=sock->data;
+       if(level!=SOL_SOCKET)
+               return -EOPNOTSUPP;
+       return sock_setsockopt(sk,level,optname,optval,optlen); 
+}
+
+static int unix_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen)
+{
+       unix_socket *sk=sock->data;
+       if(level!=SOL_SOCKET)
+               return -EOPNOTSUPP;
+       return sock_getsockopt(sk,level,optname,optval,optlen);
+}
+
+static int unix_listen(struct socket *sock, int backlog)
+{
+       unix_socket *sk=sock->data;
+       if(sk->type!=SOCK_STREAM)
+               return -EOPNOTSUPP;             /* Only stream sockets accept */
+       sk->max_ack_backlog=backlog;
+       sk->state=TCP_LISTEN;
+       return 0;
+}
+
+static void def_callback1(struct sock *sk)
+{
+       if(!sk->dead)
+               wake_up_interruptible(sk->sleep);
+}
+
+static void def_callback2(struct sock *sk, int len)
+{
+       if(!sk->dead)
+               wake_up_interruptible(sk->sleep);
+}
+
+static int unix_create(struct socket *sock, int protocol)
+{
+       unix_socket *sk;
+/*     printk("Unix create\n");*/
+       if(protocol)
+               return -EPROTONOSUPPORT;
+       sk=(unix_socket *)kmalloc(sizeof(*sk),GFP_KERNEL);
+       if(sk==NULL)
+               return -ENOMEM;
+       sk->type=sock->type;
+       switch(sock->type)
+       {
+               case SOCK_STREAM:
+                       break;
+               case SOCK_DGRAM:
+                       break;
+               default:
+                       kfree_s(sk,sizeof(*sk));
+                       return -ESOCKTNOSUPPORT;
+       }
+       skb_queue_head_init(&sk->write_queue);
+       skb_queue_head_init(&sk->receive_queue);
+       skb_queue_head_init(&sk->back_log);
+       sk->protinfo.af_unix.family=AF_UNIX;
+       sk->protinfo.af_unix.inode=NULL;
+       sk->protinfo.af_unix.locks=1;   /* Us */
+       sk->protinfo.af_unix.readsem=MUTEX;     /* single task reading lock */
+       sk->protinfo.af_unix.name=NULL;
+       sk->protinfo.af_unix.other=NULL;
+       sk->protocol=0;
+       sk->rmem_alloc=0;
+       sk->wmem_alloc=0;
+       sk->dead=0;
+       sk->next=NULL;
+       sk->broadcast=0;
+       sk->rcvbuf=SK_RMEM_MAX;
+       sk->sndbuf=SK_WMEM_MAX;
+       sk->inuse=0;
+       sk->debug=0;
+       sk->prot=NULL;
+       sk->err=0;
+       sk->localroute=0;
+       sk->send_head=NULL;
+       sk->state=TCP_CLOSE;
+       sk->priority=SOPRI_NORMAL;
+       sk->ack_backlog=0;
+       sk->shutdown=0;
+       sk->state_change=def_callback1;
+       sk->data_ready=def_callback2;
+       sk->write_space=def_callback1;
+       sk->error_report=def_callback1;
+       sk->mtu=4096;
+       sk->socket=sock;
+       sock->data=(void *)sk;
+       sk->sleep=sock->wait;
+       sk->zapped=0;
+       unix_insert_socket(sk);
+       return 0;
+}
+
+static int unix_dup(struct socket *newsock, struct socket *oldsock)
+{
+       return unix_create(newsock,0);
+}
+
+static int unix_release(struct socket *sock, struct socket *peer)
+{
+       unix_socket *sk=sock->data;
+       unix_socket *skpair;
+       
+       /* May not have data attached */
+       
+       if(sk==NULL)
+               return 0;
+               
+       sk->state_change(sk);
+       sk->dead=1;
+       skpair=(unix_socket *)sk->protinfo.af_unix.other;       /* Person we send to (default) */
+       if(sk->type==SOCK_STREAM && skpair!=NULL && skpair->state!=TCP_LISTEN)
+       {
+               skpair->shutdown=SHUTDOWN_MASK;         /* No more writes */
+               skpair->state_change(skpair);           /* Wake any blocked writes */
+       }
+       if(skpair!=NULL)
+               skpair->protinfo.af_unix.locks--;               /* It may now die */
+       sk->protinfo.af_unix.other=NULL;                        /* No pair */
+       unix_destroy_socket(sk);                        /* Try and flush out this socket. Throw our buffers at least */
+       return 0;
+}
+
+
+static unix_socket *unix_find_other(char *path, int *error)
+{
+       int old_fs;
+       int err;
+       struct inode *inode;
+       unix_socket *u;
+       
+       old_fs=get_fs();
+       set_fs(get_ds());
+       err = open_namei(path, 2, S_IFSOCK, &inode, NULL);
+       set_fs(old_fs);
+       if(err<0)
+       {
+               *error=err;
+               return NULL;
+       }
+       u=unix_find_socket(inode);
+       iput(inode);
+       if(u==NULL)
+       {
+               *error=-ECONNREFUSED;
+               return NULL;
+       }
+       return u;
+}
+
+
+static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+       struct sockaddr_un *sun=(struct sockaddr_un *)uaddr;
+       unix_socket *sk=sock->data;
+       int old_fs;
+       int err;
+       
+       if(addr_len>sizeof(struct sockaddr_un) || addr_len<3 || sun->sun_family!=AF_UNIX)
+               return -EINVAL;
+       unix_mkname(sun, addr_len);
+       /*
+        *      Put ourselves in the filesystem
+        */
+       if(sk->protinfo.af_unix.inode!=NULL)
+               return -EINVAL;
+       
+       sk->protinfo.af_unix.name=kmalloc(addr_len+1, GFP_KERNEL);
+       if(sk->protinfo.af_unix.name==NULL)
+               return -ENOMEM;
+       memcpy(sk->protinfo.af_unix.name, sun->sun_path, addr_len+1);
+       
+       old_fs=get_fs();
+       set_fs(get_ds());
+       
+       err=do_mknod(sk->protinfo.af_unix.name,S_IFSOCK|S_IRWXUGO,0);
+       if(err==0)
+               err=open_namei(sk->protinfo.af_unix.name, 2, S_IFSOCK, &sk->protinfo.af_unix.inode, NULL);
+       
+       set_fs(old_fs);
+       
+       if(err<0)
+       {
+               kfree_s(sk->protinfo.af_unix.name,addr_len+1);
+               sk->protinfo.af_unix.name=NULL;
+               if(err==-EEXIST)
+                       return -EADDRINUSE;
+               else
+                       return err;
+       }
+       
+       return 0;
+       
+}
+
+static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
+{
+       unix_socket *sk=sock->data;
+       struct sockaddr_un *sun=(struct sockaddr_un *)uaddr;
+       unix_socket *other;
+       struct sk_buff *skb;
+       int err;
+
+       unix_mkname(sun, addr_len);
+       if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
+       {
+               if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
+               {
+                       sock->state=SS_CONNECTED;
+                       return 0;
+               }
+               if(sock->state==SS_CONNECTING && sk->state == TCP_CLOSE)
+               {
+                       sock->state=SS_UNCONNECTED;
+                       return -ECONNREFUSED;
+               }
+               if(sock->state==SS_CONNECTING)
+                       return -EALREADY;
+               return -EISCONN;
+       }
+       
+       if(sun->sun_family!=AF_UNIX)
+               return -EINVAL;
+
+       if(sk->type==SOCK_DGRAM && sk->protinfo.af_unix.other)
+       {
+               sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
+               sk->protinfo.af_unix.other=NULL;
+               sock->state=SS_UNCONNECTED;
+       }
+
+       if(sock->type==SOCK_DGRAM)
+       {
+               sock->state=SS_CONNECTED;
+               sk->state=TCP_ESTABLISHED;
+               return 0;                       /* Done */
+       }
+       
+
+       if(sock->state==SS_UNCONNECTED)
+       {
+               /*
+                *      Now ready to connect
+                */
+        
+               skb=sock_alloc_send_skb(sk, 0, 0, &err); /* Marker object */
+               if(skb==NULL)
+                       return err;
+               skb->sk=sk;                             /* So they know it is us */
+               skb->free=1;
+               sk->state=TCP_CLOSE;
+               unix_mkname(sun, addr_len);
+               other=unix_find_other(sun->sun_path, &err);
+               if(other==NULL)
+               {
+                       kfree_skb(skb, FREE_WRITE);
+                       return err;
+               }
+               other->protinfo.af_unix.locks++;                /* Lock the other socket so it doesn't run off for a moment */
+               other->ack_backlog++;
+               sk->protinfo.af_unix.other=other;
+               skb_queue_tail(&other->receive_queue,skb);
+               sk->state=TCP_SYN_SENT;
+               sock->state=SS_CONNECTING;
+               sti();
+               other->data_ready(other,0);             /* Wake up ! */         
+       }
+                       
+       
+       /* Wait for an accept */
+       
+       cli();
+       while(sk->state==TCP_SYN_SENT)
+       {
+               if(flags&O_NONBLOCK)
+               {
+                       sti();
+                       return -EINPROGRESS;
+               }
+               interruptible_sleep_on(sk->sleep);
+               if(current->signal & ~current->blocked)
+               {
+                       sti();
+                       return -ERESTARTSYS;
+               }
+       }
+       
+       /*
+        *      Has the other end closed on us ?
+        */
+        
+       if(sk->state==TCP_CLOSE)
+       {
+               sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
+               sk->protinfo.af_unix.other=NULL;
+               sock->state=SS_UNCONNECTED;
+               return -ECONNREFUSED;
+       }
+       
+       /*
+        *      Amazingly it has worked
+        */
+        
+       sock->state=SS_CONNECTED;
+       return 0;
+       
+}
+
+static int unix_socketpair(struct socket *a, struct socket *b)
+{
+       int err;
+       unix_socket *ska,*skb;  
+       
+       err=unix_create(a, 0);
+       if(err)
+               return err;
+       err=unix_create(b, 0);
+       if(err)
+       {
+               unix_release(a, NULL);
+               a->data=NULL;
+               return err;
+       }
+
+       ska=a->data;
+       skb=b->data;
+
+       /* Join our sockets back to back */
+       ska->protinfo.af_unix.locks++;
+       skb->protinfo.af_unix.locks++;
+       ska->protinfo.af_unix.other=skb;
+       skb->protinfo.af_unix.other=ska;
+       ska->state=TCP_ESTABLISHED;
+       skb->state=TCP_ESTABLISHED;
+       return 0;
+}
+
+static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
+{
+       unix_socket *sk=sock->data;
+       unix_socket *newsk, *tsk;
+       struct sk_buff *skb;
+       
+       if(sk->type!=SOCK_STREAM)
+       {
+               return -EOPNOTSUPP;
+       }
+       if(sk->state!=TCP_LISTEN)
+       {
+               return -EINVAL;
+       }
+               
+       newsk=newsock->data;
+       if(sk->protinfo.af_unix.name!=NULL)
+       {
+               newsk->protinfo.af_unix.name=kmalloc(strlen(sk->protinfo.af_unix.name)+1, GFP_KERNEL);
+               if(newsk->protinfo.af_unix.name==NULL)
+                       return -ENOMEM;
+               strcpy(newsk->protinfo.af_unix.name, sk->protinfo.af_unix.name);
+       }
+               
+       do
+       {
+               cli();
+               skb=skb_dequeue(&sk->receive_queue);
+               if(skb==NULL)
+               {
+                       if(flags&O_NONBLOCK)
+                       {
+                               sti();
+                               return -EAGAIN;
+                       }
+                       interruptible_sleep_on(sk->sleep);
+                       if(current->signal & ~current->blocked)
+                       {
+                               sti();
+                               return -ERESTARTSYS;
+                       }
+                       sti();
+               }
+       }
+       while(skb==NULL);
+       tsk=skb->sk;
+       kfree_skb(skb, FREE_WRITE);     /* The buffer is just used as a tag */
+       sk->ack_backlog--;
+       newsk->protinfo.af_unix.other=tsk;
+       tsk->protinfo.af_unix.other=newsk;
+       tsk->state=TCP_ESTABLISHED;
+       newsk->state=TCP_ESTABLISHED;
+       newsk->protinfo.af_unix.locks++;        /* Swap lock over */
+       sk->protinfo.af_unix.locks--;   /* Locked to child socket not master */
+       tsk->protinfo.af_unix.locks++;  /* Back lock */
+       sti();
+       tsk->state_change(tsk);         /* Wake up any sleeping connect */
+       return 0;
+}
+
+static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
+{
+       unix_socket *sk=sock->data;
+       struct sockaddr_un *sun=(struct sockaddr_un *)uaddr;
+       
+       if(peer)
+       {
+               if(sk->protinfo.af_unix.other==NULL)
+                       return -ENOTCONN;
+               sk=sk->protinfo.af_unix.other;
+       }
+       sun->sun_family=AF_UNIX;
+       if(sk->protinfo.af_unix.name==NULL)
+       {
+               *sun->sun_path=0;
+               *uaddr_len=3;
+               return 0;               /* Not bound */
+       }
+       *uaddr_len=sizeof(short)+strlen(sk->protinfo.af_unix.name)+1;
+       strcpy(sun->sun_path,sk->protinfo.af_unix.name);                /* 108 byte limited */
+       return 0;
+}
+
+static int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int nonblock, int flags)
+{
+       unix_socket *sk=sock->data;
+       unix_socket *other;
+       struct sockaddr_un *sun=msg->msg_name;
+       int err,size;
+       struct sk_buff *skb;
+
+       if(sk->err)
+       {
+               cli();
+               err=sk->err;
+               sk->err=0;
+               sti();
+               return -err;
+       }
+       
+       if(flags || msg->msg_accrights) /* For now */
+               return -EINVAL;
+               
+       if(sun!=NULL)
+       {
+               if(sock->type==SOCK_STREAM)
+               {
+                       if(sk->state==TCP_ESTABLISHED)
+                               return -EISCONN;
+                       else
+                               return -EOPNOTSUPP;
+               }
+       }
+       if(sun==NULL)
+       {
+               if(sk->protinfo.af_unix.other==NULL)
+                       return -EINVAL;
+       }
+
+       /*
+        *      Optimisation for the fact that under 0.01% of X messages typically
+        *      need breaking up.
+        */
+
+       if(len>(sk->sndbuf-sizeof(struct sk_buff))/2)   /* Keep two messages in the pipe so it schedules better */
+       {
+               if(sock->type==SOCK_DGRAM)
+                       return -EMSGSIZE;
+               len=(sk->sndbuf-sizeof(struct sk_buff))/2;
+       }
+        
+       size=/*protocol_size(&proto_unix)+*/len;
+       skb=sock_alloc_send_skb(sk,size,nonblock, &err);
+       if(skb==NULL)
+               return err;
+/*     protocol_adjust(skb,&proto_unix);*/
+       skb->sk=sk;
+       skb->free=1;
+       memcpy_fromiovec(skb_put(skb,len),msg->msg_iov, len);
+
+       cli();
+       if(sun==NULL)
+       {
+               other=sk->protinfo.af_unix.other;
+       }
+       else
+       {
+               unix_mkname(sun, msg->msg_namelen);
+               other=unix_find_other(sun->sun_path, &err);
+               if(other==NULL)
+               {
+                       kfree_skb(skb, FREE_WRITE);
+                       return err;
+               }
+       }
+       skb_queue_tail(&other->receive_queue, skb);
+       sti();
+       other->data_ready(other,len);
+       return len;
+}
+               
+static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
+{
+       unix_socket *sk=sock->data;
+       struct sockaddr_un *sun=msg->msg_name;
+       int err;
+       struct sk_buff *skb;
+       int copied=0;
+       unsigned char *sp;
+       int len;
+       int num;
+       struct iovec *iov=msg->msg_iov;
+       int ct=msg->msg_iovlen;
+       
+       if(addr_len)
+               *addr_len=0;
+               
+       if(sk->err)
+       {
+               cli();
+               err=sk->err;
+               sk->err=0;
+               sti();
+               return -sk->err;
+       }
+       
+/*     printk("get rcv sem\n");*/
+       down(&sk->protinfo.af_unix.readsem);            /* Lock the socket */
+/*     printk("got rcv sem\n");*/
+
+       while(ct--)
+       {
+               int done=0;
+               sp=iov->iov_base;
+               len=iov->iov_len;
+               iov++;
+               
+               while(done<len)
+               {
+                       if(copied & (flags&MSG_PEEK))
+                       {
+                               up(&sk->protinfo.af_unix.readsem);
+                               return copied;
+                       }
+                       cli();
+                       skb=skb_peek(&sk->receive_queue);
+                       if(skb==NULL)
+                       {
+                               up(&sk->protinfo.af_unix.readsem);
+                               if(sk->shutdown&RCV_SHUTDOWN)
+                                       return copied;
+                               if(noblock)
+                               {
+                                       if(copied)
+                                               return copied;
+                                       return -EAGAIN;
+                               }
+                               interruptible_sleep_on(sk->sleep);
+                               if( current->signal & ~current->blocked)
+                               {
+                                       sti();
+                                       if(copied)
+                                               return copied;
+                                       return -ERESTARTSYS;
+                               }
+                               sti();
+                               down(&sk->protinfo.af_unix.readsem);
+                               continue;
+                       }
+                       if(msg->msg_name!=NULL)
+                       {
+                               sun->sun_family=AF_UNIX;
+                               if(skb->sk->protinfo.af_unix.name)
+                               {
+                                       memcpy(sun->sun_path, skb->sk->protinfo.af_unix.name, 108);
+                                       if(addr_len)
+                                               *addr_len=strlen(sun->sun_path)+sizeof(short);
+                               }
+                               else
+                                       if(addr_len)
+                                               *addr_len=sizeof(short);
+                       }
+                       num=min(skb->len,size-copied);
+                       copied+=num;
+                       done+=num;
+                       if(flags&MSG_PEEK)
+                       {
+                               memcpy_tofs(sp, skb->data, num);
+                               break;
+                       }
+                       else
+                       {
+                               memcpy_tofs(sp, skb->data,num);
+                               skb_pull(skb,num);
+                               sp+=num;
+                               if(skb->len==0)
+                               {
+                                       skb_unlink(skb);
+                                       kfree_skb(skb, FREE_WRITE);
+                                       if(sock->type==SOCK_DGRAM)
+                                               break;
+                               }
+                       }
+               }       
+       }       
+       up(&sk->protinfo.af_unix.readsem);
+       return copied;
+}
+
+static int unix_shutdown(struct socket *sock, int mode)
+{
+       unix_socket *sk=(unix_socket *)sock->data;
+       unix_socket *other=sk->protinfo.af_unix.other;
+       if(mode&SEND_SHUTDOWN)
+       {
+               sk->shutdown|=SEND_SHUTDOWN;
+               sk->state_change(sk);
+               if(other)
+               {
+                       other->shutdown|=RCV_SHUTDOWN;
+                       other->state_change(other);
+               }
+       }
+       other=sk->protinfo.af_unix.other;
+       if(mode&RCV_SHUTDOWN)
+       {
+               sk->shutdown|=RCV_SHUTDOWN;
+               sk->state_change(sk);
+               if(other)
+               {
+                       other->shutdown|=SEND_SHUTDOWN;
+                       other->state_change(other);
+               }
+       }
+       return 0;
+}
+
+               
+static int unix_select(struct socket *sock,  int sel_type, select_table *wait)
+{
+       return datagram_select(sock->data,sel_type,wait);
+}
+
+static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       unix_socket *sk=sock->data;
+       int err;
+       long amount=0;
+                       
+       switch(cmd)
+       {
+       
+               case TIOCOUTQ:
+                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+                       if(err)
+                               return err;
+                       amount=sk->sndbuf-sk->wmem_alloc;
+                       if(amount<0)
+                               amount=0;
+                       put_fs_long(amount,(unsigned long *)arg);
+                       return 0;
+               case TIOCINQ:
+               {
+                       struct sk_buff *skb;
+                       if(sk->state==TCP_LISTEN)
+                               return -EINVAL;
+                       /* These two are safe on a single CPU system as only user tasks fiddle here */
+                       if((skb=skb_peek(&sk->receive_queue))!=NULL)
+                               amount=skb->len;
+                       err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(unsigned long));
+                       put_fs_long(amount,(unsigned long *)arg);
+                       return 0;
+               }
+
+               default:
+                       return -EINVAL;
+       }
+       /*NOTREACHED*/
+       return(0);
+}
+
+/* Exported for procfs. */
+
+int unix_get_info(char *buffer, char **start, off_t offset, int length)
+{
+       off_t pos=0;
+       off_t begin=0;
+       int len=0;
+       unix_socket *s=unix_socket_list;
+       
+       len+= sprintf(buffer,"Num       RefCount Protocol Flags    Type St Path\n");
+       
+       while(s!=NULL)
+       {
+               len+=sprintf(buffer+len,"%p: %08X %08X %08lX %04X %02X",
+                       s,
+                       s->protinfo.af_unix.locks,
+                       0,
+                       s->socket->flags,
+                       s->socket->type,
+                       s->socket->state);
+               if(s->protinfo.af_unix.name!=NULL)
+                       len+=sprintf(buffer+len, " %s\n", s->protinfo.af_unix.name);
+               else
+                       buffer[len++]='\n';
+               
+               pos=begin+len;
+               if(pos<offset)
+               {
+                       len=0;
+                       begin=pos;
+               }
+               if(pos>offset+length)
+                       break;
+               s=s->next;
+       }
+       *start=buffer+(offset-begin);
+       len-=(offset-begin);
+       if(len>length)
+               len=length;
+       return len;
+}
+
+/*
+ *     For AF_UNIX we flip everything into an iovec. If this doesnt do any speed harm then it will
+ *     be easier for all the low levels to be totally iovec based.
+ */
+static int unix_recvfrom(struct socket *sock, void *ubuf, int size, int noblock, unsigned flags,
+               struct sockaddr *sa, int *addr_len)
+{
+       struct iovec iov;
+       struct msghdr msg;
+       iov.iov_base=ubuf;
+       iov.iov_len=size;
+       msg.msg_name=(void *)sa;
+       msg.msg_namelen=get_user(addr_len);
+       msg.msg_accrights=NULL;
+       msg.msg_iov=&iov;
+       msg.msg_iovlen=1;
+       return unix_recvmsg(sock,&msg,size,noblock,flags,addr_len);     
+}
+
+static int unix_read(struct socket *sock, char *ubuf, int size, int noblock)
+{
+       return unix_recvfrom(sock,ubuf,size,noblock,0,NULL,NULL);
+}
+
+static int unix_recv(struct socket *sock, void *ubuf, int size, int noblock, unsigned int flags)
+{
+       return unix_recvfrom(sock,ubuf,size,noblock,flags,NULL,NULL);
+}
+
+static int unix_sendto(struct socket *sock, const void *ubuf, int size, int noblock, unsigned flags,
+               struct sockaddr *sa, int addr_len)
+{
+       struct iovec iov;
+       struct msghdr msg;
+       iov.iov_base=(void *)ubuf;
+       iov.iov_len=size;
+       msg.msg_name=(void *)sa;
+       msg.msg_namelen=addr_len;
+       msg.msg_accrights=NULL;
+       msg.msg_iov=&iov;
+       msg.msg_iovlen=1;
+       return unix_sendmsg(sock,&msg,size,noblock,flags);      
+}
+
+static int unix_write(struct socket *sock, const char *ubuf, int size, int noblock)
+{      
+       return unix_sendto(sock,ubuf,size,noblock, 0, NULL, 0);
+}
+
+static int unix_send(struct socket *sock, const void *ubuf, int size, int noblock, unsigned int flags)
+{
+       return unix_sendto(sock,ubuf,size,noblock, flags, NULL, 0);
+}
+
+
+static struct proto_ops unix_proto_ops = {
+       AF_UNIX,
+       
+       unix_create,
+       unix_dup,
+       unix_release,
+       unix_bind,
+       unix_connect,
+       unix_socketpair,
+       unix_accept,
+       unix_getname,
+       unix_read,
+       unix_write,
+       unix_select,
+       unix_ioctl,
+       unix_listen,
+       unix_send,
+       unix_recv,
+       unix_sendto,
+       unix_recvfrom,
+       unix_shutdown,
+       unix_setsockopt,
+       unix_getsockopt,
+       unix_fcntl,
+       unix_sendmsg,
+       unix_recvmsg
+};
+
+
+void unix_proto_init(struct net_proto *pro)
+{
+       printk("NET3: Unix domain sockets 0.07 BETA for Linux NET3.030.\n");
+       sock_register(unix_proto_ops.family, &unix_proto_ops);
+}
diff --git a/net/unix/proc.c b/net/unix/proc.c
deleted file mode 100644 (file)
index 64a7773..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * UNIX                An implementation of the AF_UNIX network domain for the
- *             LINUX operating system.  UNIX is implemented using the
- *             BSD Socket interface as the means of communication with
- *             the user level.
- *
- *             The functions in this file provide an interface between
- *             the PROC file system and the "unix" family of networking
- *             protocols. It is mainly used for debugging and statistics.
- *
- * Version:    @(#)proc.c      1.0.4   05/23/93
- *
- * Authors:    Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *             Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
- *             Fred Baumgarten, <dc6iq@insu1.etec.uni-kalrsruhe.de>
- *
- * Fixes:
- *             Dmitry Gorodchanin      :       /proc locking fix
- *             Mathijs Maassen         :       unbound /proc fix.
- *             Alan Cox                :       Fix sock=NULL race
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or (at your option) any later version.
- */
-#include <linux/autoconf.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/net.h>
-#include <linux/un.h>
-#include <linux/param.h>
-#include <net/unix.h>
-
-
-/* Called from PROCfs. */
-int unix_get_info(char *buffer, char **start, off_t offset, int length)
-{
-       off_t pos=0;
-       off_t begin=0;
-       int len=0;
-       int i;
-       unsigned long flags;
-       socket_state s_state;
-       short s_type;
-       long s_flags;
-       
-       len += sprintf(buffer, "Num RefCount Protocol Flags    Type St Path\n");
-
-       for(i = 0; i < NSOCKETS_UNIX; i++) 
-       {
-               save_flags(flags);
-               cli();
-               if (unix_datas[i].refcnt>0 && unix_datas[i].socket!=NULL)
-               {
-                       /* sprintf is slow... lock only for the variable reads */
-                       s_type=unix_datas[i].socket->type;
-                       s_flags=unix_datas[i].socket->flags;
-                       s_state=unix_datas[i].socket->state;
-                       restore_flags(flags);
-                       len += sprintf(buffer+len, "%2d: %08X %08X %08lX %04X %02X", i,
-                               unix_datas[i].refcnt,
-                               unix_datas[i].protocol,
-                               s_flags,
-                               s_type,
-                               s_state
-                       );
-
-                       /* If socket is bound to a filename, we'll print it. */
-                       if(unix_datas[i].sockaddr_len>0) 
-                       {
-                               len += sprintf(buffer+len, " %s\n",
-                               unix_datas[i].sockaddr_un.sun_path);
-                       } 
-                       else 
-                       { /* just add a newline */
-                               buffer[len++]='\n';
-                       }
-                       
-                       pos=begin+len;
-                       if(pos<offset)
-                       {
-                               len=0;
-                               begin=pos;
-                       }
-                       if(pos>offset+length)
-                               break;
-               }
-               else
-                       restore_flags(flags);
-       }
-       
-       *start=buffer+(offset-begin);
-       len-=(offset-begin);
-       if(len>length)
-               len=length;
-       return len;
-}
diff --git a/net/unix/sock.c b/net/unix/sock.c
deleted file mode 100644 (file)
index 4faa638..0000000
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * UNIX                An implementation of the AF_UNIX network domain for the
- *             LINUX operating system.  UNIX is implemented using the
- *             BSD Socket interface as the means of communication with
- *             the user level.
- *
- * Version:    @(#)sock.c      1.0.5   05/25/93
- *
- * Authors:    Orest Zborowski, <obz@Kodak.COM>
- *             Ross Biro, <bir7@leland.Stanford.Edu>
- *             Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
- *
- * Fixes:
- *             Alan Cox        :       Verify Area
- *             NET2E Team      :       Page fault locks
- *     Dmitry Gorodchanin      :       /proc locking
- *
- * To Do:
- *     Some nice person is looking into Unix sockets done properly. NET3
- *     will replace all of this and include datagram sockets and socket
- *     options - so please stop asking me for them 8-)
- *
- *
- *             This program is free software; you can redistribute it and/or
- *             modify it under the terms of the GNU General Public License
- *             as published by the Free Software Foundation; either version
- *             2 of the License, or(at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/socket.h>
-#include <linux/un.h>
-#include <linux/fcntl.h>
-#include <linux/termios.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/fs.h>
-#include <linux/malloc.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-
-#include <stdarg.h>
-
-#include <net/unix.h>
-
-/*
- *     Because these have the address in them they casually waste an extra 8K of kernel data
- *     space that need not be wasted.
- */
-struct unix_proto_data unix_datas[NSOCKETS_UNIX];
-
-static int unix_proto_create(struct socket *sock, int protocol);
-static int unix_proto_dup(struct socket *newsock, struct socket *oldsock);
-static int unix_proto_release(struct socket *sock, struct socket *peer);
-static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
-                          int sockaddr_len);
-static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
-                             int sockaddr_len, int flags);
-static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2);
-static int unix_proto_accept(struct socket *sock, struct socket *newsock, 
-                            int flags);
-static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
-                             int *usockaddr_len, int peer);
-static int unix_proto_read(struct socket *sock, char *ubuf, int size,
-                          int nonblock);
-static int unix_proto_write(struct socket *sock, const char *ubuf, int size,
-                           int nonblock);
-static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait);
-static int unix_proto_ioctl(struct socket *sock, unsigned int cmd,
-                           unsigned long arg);
-static int unix_proto_listen(struct socket *sock, int backlog);
-static int unix_proto_send(struct socket *sock, const void *buff, int len,
-                           int nonblock, unsigned flags);
-static int unix_proto_recv(struct socket *sock, void *buff, int len,
-                           int nonblock, unsigned flags);
-static int unix_proto_sendto(struct socket *sock, const void *buff, int len,
-                             int nonblock, unsigned flags,
-                             struct sockaddr *addr, int addr_len);
-static int unix_proto_recvfrom(struct socket *sock, void *buff, int len,
-                               int nonblock, unsigned flags,
-                               struct sockaddr *addr, int *addr_len);
-
-static int unix_proto_shutdown(struct socket *sock, int how);
-
-static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
-                                 char *optval, int optlen);
-static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
-                                 char *optval, int *optlen);
-
-
-static inline int min(int a, int b)
-{
-       if (a < b)
-               return(a);
-       return(b);
-}
-
-
-
-/* Support routines doing anti page fault locking 
- * FvK & Matt Dillon (borrowed From NET2E3)
- */
-
-/*
- * Locking for unix-domain sockets.  We don't use the socket structure's
- * wait queue because it is allowed to 'go away' outside of our control,
- * whereas unix_proto_data structures stick around.
- */
-static void unix_lock(struct unix_proto_data *upd)
-{
-       while (upd->lock_flag)
-               sleep_on(&upd->wait);
-       upd->lock_flag = 1;
-}
-
-
-static void unix_unlock(struct unix_proto_data *upd)
-{
-       upd->lock_flag = 0;
-       wake_up(&upd->wait);
-}
-
-/*
- *     We don't have to do anything. 
- */
-static int unix_proto_listen(struct socket *sock, int backlog)
-{
-       return(0);
-}
-
-/*
- *     Until the new NET3 Unix code is done we have no options.
- */
-
-static int unix_proto_setsockopt(struct socket *sock, int level, int optname,
-                     char *optval, int optlen)
-{
-       return(-EOPNOTSUPP);
-}
-
-
-static int unix_proto_getsockopt(struct socket *sock, int level, int optname,
-                     char *optval, int *optlen)
-{
-       return(-EOPNOTSUPP);
-}
-
-
-/*
- *     SendTo() doesn't matter as we also have no Datagram support!
- */
-
-static int unix_proto_sendto(struct socket *sock, const void *buff, int len, int nonblock, 
-                 unsigned flags,  struct sockaddr *addr, int addr_len)
-{
-       return(-EOPNOTSUPP);
-}     
-
-static int unix_proto_recvfrom(struct socket *sock, void *buff, int len, int nonblock, 
-                   unsigned flags, struct sockaddr *addr, int *addr_len)
-{
-       return(-EOPNOTSUPP);
-}     
-
-/*
- *     You can't shutdown a unix domain socket.
- */
-
-static int unix_proto_shutdown(struct socket *sock, int how)
-{
-       return(-EOPNOTSUPP);
-}
-
-
-/*
- *     Send data to a unix socket.
- */
-static int unix_proto_send(struct socket *sock, const void *buff, int len, int nonblock,
-               unsigned flags)
-{
-       if (flags != 0) 
-               return(-EINVAL);
-       return(unix_proto_write(sock, (const char *) buff, len, nonblock));
-}
-
-
-/* 
- *     Receive data. This version of AF_UNIX also lacks MSG_PEEK 8(
- */
-static int unix_proto_recv(struct socket *sock, void *buff, int len, int nonblock,
-               unsigned flags)
-{
-       if (flags != 0) 
-               return(-EINVAL);
-       return(unix_proto_read(sock, (char *) buff, len, nonblock));
-}
-
-/*
- *     Given an address and an inode go find a unix control structure
- */
-static struct unix_proto_data *
-unix_data_lookup(struct sockaddr_un *sockun, int sockaddr_len,
-                struct inode *inode)
-{
-        struct unix_proto_data *upd;
-
-        for(upd = unix_datas; upd <= last_unix_data; ++upd) 
-        {
-               if (upd->refcnt > 0 && upd->socket &&
-                       upd->socket->state == SS_UNCONNECTED &&
-                       upd->sockaddr_un.sun_family == sockun->sun_family &&
-                       upd->inode == inode) 
-                       
-                       return(upd);
-       }
-       return(NULL);
-}
-
-/*
- *     We allocate a page of data for the socket. This is woefully inadequate and helps cause vast
- *     amounts of excess task switching and blocking when transferring stuff like bitmaps via X.
- *     It doesn't help this problem that the Linux scheduler is desperately in need of a major 
- *     rewrite. Somewhere near 16K would be better maybe 32.
- */
-
-static struct unix_proto_data *
-unix_data_alloc(void)
-{
-       struct unix_proto_data *upd;
-
-       cli();
-       for(upd = unix_datas; upd <= last_unix_data; ++upd) 
-       {
-               if (!upd->refcnt) 
-               {
-                       upd->refcnt = -1;       /* unix domain socket not yet initialised - bgm */
-                       sti();
-                       upd->socket = NULL;
-                       upd->sockaddr_len = 0;
-                       upd->sockaddr_un.sun_family = 0;
-                       upd->buf = NULL;
-                       upd->bp_head = upd->bp_tail = 0;
-                       upd->inode = NULL;
-                       upd->peerupd = NULL;
-                       return(upd);
-               }
-       }
-       sti();
-       return(NULL);
-}
-
-/*
- *     The data area is owned by all its users. Thus we need to track owners
- *     carefully and not free data at the wrong moment. These look like they need
- *     interrupt protection but they don't because no interrupt ever fiddles with
- *     these counts. With an SMP Linux you'll need to protect these!
- */
-
-static inline void unix_data_ref(struct unix_proto_data *upd)
-{
-       if (!upd) 
-       {
-               return;
-       }
-       ++upd->refcnt;
-}
-
-
-static void unix_data_deref(struct unix_proto_data *upd)
-{
-       if (!upd) 
-       {
-               return;
-       }
-       if (upd->refcnt == 1) 
-       {
-               if (upd->buf) 
-               {
-                       free_page((unsigned long)upd->buf);
-                       upd->buf = NULL;
-                       upd->bp_head = upd->bp_tail = 0;
-               }
-       }
-       --upd->refcnt;
-}
-
-
-/*
- *     Upon a create, we allocate an empty protocol data,
- *     and grab a page to buffer writes.
- */
-static int unix_proto_create(struct socket *sock, int protocol)
-{
-       struct unix_proto_data *upd;
-
-       /*
-        *      No funny SOCK_RAW stuff
-        */
-        
-       if (protocol != 0) 
-       {
-               return(-EINVAL);
-       }
-
-       if (!(upd = unix_data_alloc())) 
-       {
-               printk("UNIX: create: can't allocate buffer\n");
-               return(-ENOMEM);
-       }
-       if (!(upd->buf = (char*) get_free_page(GFP_USER))) 
-       {
-               printk("UNIX: create: can't get page!\n");
-               unix_data_deref(upd);
-               return(-ENOMEM);
-       }
-       upd->protocol = protocol;
-       upd->socket = sock;
-       UN_DATA(sock) = upd;
-       upd->refcnt = 1;        /* Now it's complete - bgm */
-       return(0);
-}
-
-/*
- *     Duplicate a socket.
- */
-
-static int unix_proto_dup(struct socket *newsock, struct socket *oldsock)
-{
-       struct unix_proto_data *upd = UN_DATA(oldsock);
-       return(unix_proto_create(newsock, upd->protocol));
-}
-
-
-/*
- *     Release a Unix domain socket.
- */
-static int unix_proto_release(struct socket *sock, struct socket *peer)
-{
-       struct unix_proto_data *upd = UN_DATA(sock);
-
-       if (!upd) 
-               return(0);
-
-       if (upd->socket != sock) 
-       {
-               printk("UNIX: release: socket link mismatch!\n");
-               return(-EINVAL);
-       }
-
-       if (upd->inode) 
-       {
-               iput(upd->inode);
-               upd->inode = NULL;
-       }
-
-       UN_DATA(sock) = NULL;
-       upd->socket = NULL;
-
-       if (upd->peerupd)
-               unix_data_deref(upd->peerupd);
-       unix_data_deref(upd);
-       return(0);
-}
-
-
-/*
- *     Bind a name to a socket.
- *     This is where much of the work is done: we allocate a fresh page for
- *     the buffer, grab the appropriate inode and set things up.
- *
- *     FIXME: what should we do if an address is already bound?
- *       Here we return EINVAL, but it may be necessary to re-bind.
- *       I think thats what BSD does in the case of datagram sockets...
- */
-static int unix_proto_bind(struct socket *sock, struct sockaddr *umyaddr,
-               int sockaddr_len)
-{
-       char fname[UNIX_PATH_MAX + 1];
-       struct unix_proto_data *upd = UN_DATA(sock);
-       unsigned long old_fs;
-       int i;
-
-       if (sockaddr_len <= UN_PATH_OFFSET ||
-               sockaddr_len > sizeof(struct sockaddr_un)) 
-       {
-               return(-EINVAL);
-       }
-       if (upd->sockaddr_len || upd->inode) 
-       {
-               /*printk("UNIX: bind: already bound!\n");*/
-               return(-EINVAL);
-       }
-       memcpy(&upd->sockaddr_un, umyaddr, sockaddr_len);
-       upd->sockaddr_un.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       if (upd->sockaddr_un.sun_family != AF_UNIX) 
-       {
-               return(-EINVAL);
-       }
-
-       memcpy(fname, upd->sockaddr_un.sun_path, sockaddr_len-UN_PATH_OFFSET);
-       fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       old_fs = get_fs();
-       set_fs(get_ds());
-
-       i = do_mknod(fname, S_IFSOCK | S_IRWXUGO, 0);
-
-       if (i == 0) 
-               i = open_namei(fname, 2, S_IFSOCK, &upd->inode, NULL);
-       set_fs(old_fs);
-       if (i < 0) 
-       {
-/*             printk("UNIX: bind: can't open socket %s\n", fname);*/
-               if(i==-EEXIST)
-                       i=-EADDRINUSE;
-               return(i);
-       }
-       upd->sockaddr_len = sockaddr_len;       /* now it's legal */
-       
-       return(0);
-}
-
-
-/*
- *     Perform a connection. we can only connect to unix sockets
- *     (I can't for the life of me find an application where that
- *     wouldn't be the case!)
- */
-
-static int unix_proto_connect(struct socket *sock, struct sockaddr *uservaddr,
-                  int sockaddr_len, int flags)
-{
-       char fname[sizeof(((struct sockaddr_un *)0)->sun_path) + 1];
-       struct sockaddr_un sockun;
-       struct unix_proto_data *serv_upd;
-       struct inode *inode;
-       unsigned long old_fs;
-       int i;
-
-       if (sockaddr_len <= UN_PATH_OFFSET ||
-               sockaddr_len > sizeof(struct sockaddr_un)) 
-       {
-               return(-EINVAL);
-       }
-
-       if (sock->state == SS_CONNECTING) 
-               return(-EINPROGRESS);
-       if (sock->state == SS_CONNECTED)
-               return(-EISCONN);
-
-       memcpy(&sockun, uservaddr, sockaddr_len);
-       sockun.sun_path[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       if (sockun.sun_family != AF_UNIX) 
-       {
-               return(-EINVAL);
-       }
-
-/*
- * Try to open the name in the filesystem - this is how we
- * identify ourselves and our server. Note that we don't
- * hold onto the inode that long, just enough to find our
- * server. When we're connected, we mooch off the server.
- */
-
-       memcpy(fname, sockun.sun_path, sockaddr_len-UN_PATH_OFFSET);
-       fname[sockaddr_len-UN_PATH_OFFSET] = '\0';
-       old_fs = get_fs();
-       set_fs(get_ds());
-       i = open_namei(fname, 2, S_IFSOCK, &inode, NULL);
-       set_fs(old_fs);
-       if (i < 0) 
-       {
-               return(i);
-       }
-         
-       serv_upd = unix_data_lookup(&sockun, sockaddr_len, inode);
-       iput(inode);
-       if (!serv_upd) 
-       {
-               return(-EINVAL);
-       }
-       
-       if ((i = sock_awaitconn(sock, serv_upd->socket, flags)) < 0) 
-       {
-               return(i);
-       }
-
-       if (sock->conn) 
-       {
-               unix_data_ref(UN_DATA(sock->conn));
-               UN_DATA(sock)->peerupd = UN_DATA(sock->conn); /* ref server */
-       }
-       return(0);
-}
-
-
-/*
- *     To do a socketpair, we just connect the two datas, easy!
- *     Since we always wait on the socket inode, they're no contention
- *     for a wait area, and deadlock prevention in the case of a process
- *     writing to itself is, ignored, in true unix fashion!
- */
-static int unix_proto_socketpair(struct socket *sock1, struct socket *sock2)
-{
-       struct unix_proto_data *upd1 = UN_DATA(sock1), *upd2 = UN_DATA(sock2);
-
-       unix_data_ref(upd1);
-       unix_data_ref(upd2);
-       upd1->peerupd = upd2;
-       upd2->peerupd = upd1;
-       return(0);
-}
-
-
-/* 
- *     On accept, we ref the peer's data for safe writes. 
- */
-
-static int unix_proto_accept(struct socket *sock, struct socket *newsock, int flags)
-{
-       struct socket *clientsock;
-
-/*
- * If there aren't any sockets awaiting connection,
- * then wait for one, unless nonblocking.
- */
-
-       while(!(clientsock = sock->iconn)) 
-       {
-               if (flags & O_NONBLOCK) 
-                       return(-EAGAIN);
-               sock->flags |= SO_WAITDATA;
-               interruptible_sleep_on(sock->wait);
-               sock->flags &= ~SO_WAITDATA;
-               if (current->signal & ~current->blocked) 
-               {
-                       return(-ERESTARTSYS);
-               }
-       }
-/*
- * Great. Finish the connection relative to server and client,
- * wake up the client and return the new fd to the server.
- */
-
-       sock->iconn = clientsock->next;
-       clientsock->next = NULL;
-       newsock->conn = clientsock;
-       clientsock->conn = newsock;
-       clientsock->state = SS_CONNECTED;
-       newsock->state = SS_CONNECTED;
-       unix_data_ref(UN_DATA(clientsock));
-       UN_DATA(newsock)->peerupd            = UN_DATA(clientsock);
-       UN_DATA(newsock)->sockaddr_un        = UN_DATA(sock)->sockaddr_un;
-       UN_DATA(newsock)->sockaddr_len       = UN_DATA(sock)->sockaddr_len;
-       wake_up_interruptible(clientsock->wait);
-       sock_wake_async(clientsock, 0);
-       return(0);
-}
-
-
-/*
- *     Gets the current name or the name of the connected socket. 
- */
-static int unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
-                  int *usockaddr_len, int peer)
-{
-       struct unix_proto_data *upd;
-       int len;
-
-       if (peer) 
-       {
-               if (sock->state != SS_CONNECTED) 
-               {
-                       return(-EINVAL);
-               }
-               upd = UN_DATA(sock->conn);
-       }
-       else
-               upd = UN_DATA(sock);
-
-       len = upd->sockaddr_len;
-       memcpy(usockaddr, &upd->sockaddr_un, len);
-       *usockaddr_len=len;
-       return(0);
-}
-
-
-/* 
- *     We read from our own buf. 
- */
-static int unix_proto_read(struct socket *sock, char *ubuf, int size, int nonblock)
-{
-       struct unix_proto_data *upd;
-       int todo, avail;
-
-       if ((todo = size) <= 0) 
-               return(0);
-
-       upd = UN_DATA(sock);
-       while(!(avail = UN_BUF_AVAIL(upd))) 
-       {
-               if (sock->state != SS_CONNECTED) 
-               {
-                       return((sock->state == SS_DISCONNECTING) ? 0 : -EINVAL);
-               }
-               if (nonblock) 
-                       return(-EAGAIN);
-               sock->flags |= SO_WAITDATA;
-               interruptible_sleep_on(sock->wait);
-               sock->flags &= ~SO_WAITDATA;
-               if (current->signal & ~current->blocked) 
-               {
-                       return(-ERESTARTSYS);
-               }
-       }
-
-/*
- *     Copy from the read buffer into the user's buffer,
- *     watching for wraparound. Then we wake up the writer.
- */
-   
-       unix_lock(upd);
-       do 
-       {
-               int part, cando;
-
-               if (avail <= 0) 
-               {
-                       printk("UNIX: read: AVAIL IS NEGATIVE!!!\n");
-                       send_sig(SIGKILL, current, 1);
-                       return(-EPIPE);
-               }
-
-               if ((cando = todo) > avail) 
-                       cando = avail;
-               if (cando >(part = BUF_SIZE - upd->bp_tail)) 
-                       cando = part;
-               memcpy_tofs(ubuf, upd->buf + upd->bp_tail, cando);
-               upd->bp_tail =(upd->bp_tail + cando) &(BUF_SIZE-1);
-               ubuf += cando;
-               todo -= cando;
-               if (sock->state == SS_CONNECTED)
-               {
-                       wake_up_interruptible(sock->conn->wait);
-                       sock_wake_async(sock->conn, 2);
-               }
-               avail = UN_BUF_AVAIL(upd);
-       } 
-       while(todo && avail);
-       unix_unlock(upd);
-       return(size - todo);
-}
-
-
-/*
- *     We write to our peer's buf. When we connected we ref'd this
- *     peer so we are safe that the buffer remains, even after the
- *     peer has disconnected, which we check other ways.
- */
-static int unix_proto_write(struct socket *sock, const char *ubuf, int size, int nonblock)
-{
-       struct unix_proto_data *pupd;
-       int todo, space;
-
-       if ((todo = size) <= 0)
-               return(0);
-       if (sock->state != SS_CONNECTED) 
-       {
-               if (sock->state == SS_DISCONNECTING) 
-               {
-                       send_sig(SIGPIPE, current, 1);
-                       return(-EPIPE);
-               }
-               return(-EINVAL);
-       }
-       pupd = UN_DATA(sock)->peerupd;  /* safer than sock->conn */
-
-       while(!(space = UN_BUF_SPACE(pupd))) 
-       {
-               sock->flags |= SO_NOSPACE;
-               if (nonblock) 
-                       return(-EAGAIN);
-               sock->flags &= ~SO_NOSPACE;
-               interruptible_sleep_on(sock->wait);
-               if (current->signal & ~current->blocked) 
-               {
-                       return(-ERESTARTSYS);
-               }
-               if (sock->state == SS_DISCONNECTING) 
-               {
-                       send_sig(SIGPIPE, current, 1);
-                       return(-EPIPE);
-               }
-       }
-
-/*
- *     Copy from the user's buffer to the write buffer,
- *     watching for wraparound. Then we wake up the reader.
- */
-   
-       unix_lock(pupd);
-
-       do 
-       {
-               int part, cando;
-
-               if (space <= 0) 
-               {
-                       printk("UNIX: write: SPACE IS NEGATIVE!!!\n");
-                       send_sig(SIGKILL, current, 1);
-                       return(-EPIPE);
-               }
-
-               /*
-                *      We may become disconnected inside this loop, so watch
-                *      for it (peerupd is safe until we close).
-                */
-                
-               if (sock->state == SS_DISCONNECTING) 
-               {
-                       send_sig(SIGPIPE, current, 1);
-                       unix_unlock(pupd);
-                       return(-EPIPE);
-               }
-               
-               if ((cando = todo) > space) 
-                       cando = space;
-
-               if (cando >(part = BUF_SIZE - pupd->bp_head))
-                       cando = part;
-       
-               memcpy_fromfs(pupd->buf + pupd->bp_head, ubuf, cando);
-               pupd->bp_head =(pupd->bp_head + cando) &(BUF_SIZE-1);
-               ubuf += cando;
-               todo -= cando;
-               if (sock->state == SS_CONNECTED)
-               {
-                       wake_up_interruptible(sock->conn->wait);
-                       sock_wake_async(sock->conn, 1);
-               }
-               space = UN_BUF_SPACE(pupd);
-       }
-       while(todo && space);
-
-       unix_unlock(pupd);
-       return(size - todo);
-}
-
-/*
- *     Select on a unix domain socket.
- */
-
-static int unix_proto_select(struct socket *sock, int sel_type, select_table * wait)
-{
-       struct unix_proto_data *upd, *peerupd;
-
-       /* 
-        *      Handle server sockets specially.
-        */
-       if (sock->flags & SO_ACCEPTCON) 
-       {
-               if (sel_type == SEL_IN) 
-               {
-                       if (sock->iconn) 
-                               return(1);
-                       select_wait(sock->wait, wait);
-                       return(sock->iconn ? 1 : 0);
-               }
-               select_wait(sock->wait, wait);
-               return(0);
-       }
-
-       if (sel_type == SEL_IN) 
-       {
-               upd = UN_DATA(sock);
-               if (UN_BUF_AVAIL(upd))  /* even if disconnected */
-                       return(1);
-               else if (sock->state != SS_CONNECTED) 
-               {
-                       return(1);
-               }
-               select_wait(sock->wait,wait);
-               return(0);
-       }
-
-       if (sel_type == SEL_OUT) 
-       {
-               if (sock->state != SS_CONNECTED) 
-               {
-                       return(1);
-               }
-               peerupd = UN_DATA(sock->conn);
-               if (UN_BUF_SPACE(peerupd) > 0) 
-                       return(1);
-               select_wait(sock->wait,wait);
-               return(0);
-       }
-
-       /*
-        * Exceptions - SEL_EX 
-        */
-
-       return(0);
-}
-
-
-/*
- *     ioctl() calls sent to an AF_UNIX socket
- */
-
-static int unix_proto_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       struct unix_proto_data *upd, *peerupd;
-       int er;
-
-       upd = UN_DATA(sock);
-       peerupd = (sock->state == SS_CONNECTED) ? UN_DATA(sock->conn) : NULL;
-
-       switch(cmd) 
-       {
-               case TIOCINQ:
-                       if (sock->flags & SO_ACCEPTCON) 
-                               return(-EINVAL);
-                       er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
-                       if(er)
-                               return er;
-                       if (UN_BUF_AVAIL(upd) || peerupd)
-                               put_fs_long(UN_BUF_AVAIL(upd),(unsigned long *)arg);
-                       else
-                               put_fs_long(0,(unsigned long *)arg);
-                       break;
-               case TIOCOUTQ:
-                       if (sock->flags & SO_ACCEPTCON) 
-                               return(-EINVAL);
-                       er=verify_area(VERIFY_WRITE,(void *)arg, sizeof(unsigned long));
-                       if(er)
-                               return er;
-                       if (peerupd) 
-                               put_fs_long(UN_BUF_SPACE(peerupd),(unsigned long *)arg);
-                       else
-                               put_fs_long(0,(unsigned long *)arg);
-                       break;
-               default:
-                       return(-EINVAL);
-       }
-       return(0);
-}
-
-
-static struct proto_ops unix_proto_ops = {
-       AF_UNIX,
-       unix_proto_create,
-       unix_proto_dup,
-       unix_proto_release,
-       unix_proto_bind,
-       unix_proto_connect,
-       unix_proto_socketpair,
-       unix_proto_accept,
-       unix_proto_getname,
-       unix_proto_read,
-       unix_proto_write,
-       unix_proto_select,
-       unix_proto_ioctl,
-       unix_proto_listen,
-       unix_proto_send,
-       unix_proto_recv,
-       unix_proto_sendto,
-       unix_proto_recvfrom,
-       unix_proto_shutdown,
-       unix_proto_setsockopt,
-       unix_proto_getsockopt,
-       NULL                            /* unix_proto_fcntl     */
-};
-
-/*
- *     Initialise the Unix domain protocol.
- */
-
-void unix_proto_init(struct net_proto *pro)
-{
-       struct unix_proto_data *upd;
-
-       /*
-        *      Tell SOCKET that we are alive... 
-        */
-
-       (void) sock_register(unix_proto_ops.family, &unix_proto_ops);
-
-       for(upd = unix_datas; upd <= last_unix_data; ++upd) 
-       {
-               upd->refcnt = 0;
-       }
-}